Remove main package dependency on criurpc

Commit 7f64fb47 made the main package, and runc/libcontainer's CriuOpts
depend on criu/rpc. This is not good; among the other things, it makes
it complicated to make c/r optional.

Let's switch CriuOpts.ManageCgroupsMode to a string (yes, it's an APIt
breaking change) and move the cgroup mode string parsing to
libcontainer.

While at it, let's better document ManageCgroupsMode.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2024-12-05 16:15:23 -08:00
parent e0752069a5
commit c487840f75
3 changed files with 69 additions and 63 deletions
+1 -16
View File
@@ -8,7 +8,6 @@ import (
"path/filepath"
"strconv"
criu "github.com/checkpoint-restore/go-criu/v6/rpc"
"github.com/moby/sys/userns"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
@@ -132,6 +131,7 @@ func criuOptions(context *cli.Context) (*libcontainer.CriuOpts, error) {
StatusFd: context.Int("status-fd"),
LsmProfile: context.String("lsm-profile"),
LsmMountContext: context.String("lsm-mount-context"),
ManageCgroupsMode: context.String("manage-cgroups-mode"),
}
// CRIU options below may or may not be set.
@@ -152,21 +152,6 @@ func criuOptions(context *cli.Context) (*libcontainer.CriuOpts, error) {
}
}
switch context.String("manage-cgroups-mode") {
case "":
// do nothing
case "soft":
opts.ManageCgroupsMode = criu.CriuCgMode_SOFT
case "full":
opts.ManageCgroupsMode = criu.CriuCgMode_FULL
case "strict":
opts.ManageCgroupsMode = criu.CriuCgMode_STRICT
case "ignore":
opts.ManageCgroupsMode = criu.CriuCgMode_IGNORE
default:
return nil, errors.New("Invalid manage-cgroups-mode value")
}
// runc doesn't manage network devices and their configuration.
nsmask := unix.CLONE_NEWNET
+32 -14
View File
@@ -295,6 +295,11 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
return errors.New("invalid directory to save checkpoint")
}
cgMode, err := criuCgMode(criuOpts.ManageCgroupsMode)
if err != nil {
return err
}
// Since a container can be C/R'ed multiple times,
// the checkpoint directory may already exist.
if err := os.Mkdir(criuOpts.ImagesDirectory, 0o700); err != nil && !os.IsExist(err) {
@@ -313,7 +318,8 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
LogLevel: proto.Int32(4),
LogFile: proto.String(logFile),
Root: proto.String(c.config.Rootfs),
ManageCgroups: proto.Bool(true),
ManageCgroups: proto.Bool(true), // Obsoleted by ManageCgroupsMode.
ManageCgroupsMode: &cgMode,
NotifyScripts: proto.Bool(true),
Pid: proto.Int32(int32(c.initProcess.pid())),
ShellJob: proto.Bool(criuOpts.ShellJob),
@@ -381,12 +387,6 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
rpcOpts.TrackMem = proto.Bool(true)
}
// append optional manage cgroups mode
if criuOpts.ManageCgroupsMode != 0 {
mode := criuOpts.ManageCgroupsMode
rpcOpts.ManageCgroupsMode = &mode
}
var t criurpc.CriuReqType
if criuOpts.PreDump {
feat := criurpc.CriuFeatures{
@@ -634,6 +634,12 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
if criuOpts.ImagesDirectory == "" {
return errors.New("invalid directory to restore checkpoint")
}
cgMode, err := criuCgMode(criuOpts.ManageCgroupsMode)
if err != nil {
return err
}
logDir := criuOpts.ImagesDirectory
imageDir, err := os.Open(criuOpts.ImagesDirectory)
if err != nil {
@@ -669,7 +675,8 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
LogFile: proto.String(logFile),
RstSibling: proto.Bool(true),
Root: proto.String(root),
ManageCgroups: proto.Bool(true),
ManageCgroups: proto.Bool(true), // Obsoleted by ManageCgroupsMode.
ManageCgroupsMode: &cgMode,
NotifyScripts: proto.Bool(true),
ShellJob: proto.Bool(criuOpts.ShellJob),
ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections),
@@ -757,12 +764,6 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
c.restoreNetwork(req, criuOpts)
}
// append optional manage cgroups mode
if criuOpts.ManageCgroupsMode != 0 {
mode := criuOpts.ManageCgroupsMode
req.Opts.ManageCgroupsMode = &mode
}
var (
fds []string
fdJSON []byte
@@ -1184,3 +1185,20 @@ func (c *Container) criuNotifications(resp *criurpc.CriuResp, process *Process,
}
return nil
}
func criuCgMode(mode string) (criurpc.CriuCgMode, error) {
switch mode {
case "":
return criurpc.CriuCgMode_DEFAULT, nil
case "soft":
return criurpc.CriuCgMode_SOFT, nil
case "full":
return criurpc.CriuCgMode_FULL, nil
case "strict":
return criurpc.CriuCgMode_STRICT, nil
case "ignore":
return criurpc.CriuCgMode_IGNORE, nil
default:
return 0, errors.New("invalid manage-cgroups-mode value")
}
}
+6 -3
View File
@@ -1,7 +1,5 @@
package libcontainer
import criu "github.com/checkpoint-restore/go-criu/v6/rpc"
type CriuPageServerInfo struct {
Address string // IP address of CRIU page server
Port int32 // port number of CRIU page server
@@ -24,11 +22,16 @@ type CriuOpts struct {
PreDump bool // call criu predump to perform iterative checkpoint
PageServer CriuPageServerInfo // allow to dump to criu page server
VethPairs []VethPairName // pass the veth to criu when restore
ManageCgroupsMode criu.CriuCgMode // dump or restore cgroup mode
EmptyNs uint32 // don't c/r properties for namespace from this mask
AutoDedup bool // auto deduplication for incremental dumps
LazyPages bool // restore memory pages lazily using userfaultfd
StatusFd int // fd for feedback when lazy server is ready
LsmProfile string // LSM profile used to restore the container
LsmMountContext string // LSM mount context value to use during restore
// ManageCgroupsMode tells how criu should manage cgroups during
// checkpoint or restore. Possible values are: "soft", "full",
// "strict", "ignore", or "" (empty string) for criu default.
// See https://criu.org/CGroups for more details.
ManageCgroupsMode string
}