diff --git a/restore.go b/restore.go index 873540d2..9d071a93 100644 --- a/restore.go +++ b/restore.go @@ -92,7 +92,7 @@ using the runc checkpoint command.`, if err != nil { fatal(err) } - config, err := createLibcontainerConfig(id, spec) + config, err := createLibcontainerConfig(id, context.GlobalBool("systemd-cgroup"), spec) if err != nil { fatal(err) } diff --git a/spec.go b/spec.go index 87bbff88..bee95dc8 100644 --- a/spec.go +++ b/spec.go @@ -215,7 +215,7 @@ func loadSpec(cPath string) (spec *specs.Spec, err error) { return spec, validateProcessSpec(&spec.Process) } -func createLibcontainerConfig(cgroupName string, spec *specs.Spec) (*configs.Config, error) { +func createLibcontainerConfig(cgroupName string, useSystemdCgroup bool, spec *specs.Spec) (*configs.Config, error) { // runc's cwd will always be the bundle path rcwd, err := os.Getwd() if err != nil { @@ -266,7 +266,7 @@ func createLibcontainerConfig(cgroupName string, spec *specs.Spec) (*configs.Con if err := setupUserNamespace(spec, config); err != nil { return nil, err } - c, err := createCgroupConfig(cgroupName, spec) + c, err := createCgroupConfig(cgroupName, useSystemdCgroup, spec) if err != nil { return nil, err } @@ -311,26 +311,47 @@ func createLibcontainerMount(cwd string, m specs.Mount) *configs.Mount { } } -func createCgroupConfig(name string, spec *specs.Spec) (*configs.Cgroup, error) { +func createCgroupConfig(name string, useSystemdCgroup bool, spec *specs.Spec) (*configs.Cgroup, error) { var ( err error myCgroupPath string ) - if spec.Linux.CgroupsPath != nil { - myCgroupPath = libcontainerUtils.CleanPath(*spec.Linux.CgroupsPath) - } else { - myCgroupPath, err = cgroups.GetThisCgroupDir("devices") - if err != nil { - return nil, err - } - myCgroupPath = filepath.Join(myCgroupPath, name) - } - c := &configs.Cgroup{ - Path: myCgroupPath, Resources: &configs.Resources{}, } + + if spec.Linux.CgroupsPath != nil { + myCgroupPath = libcontainerUtils.CleanPath(*spec.Linux.CgroupsPath) + } + + if useSystemdCgroup { + if myCgroupPath == "" { + c.Parent = "system.slice" + c.ScopePrefix = "runc" + c.Name = name + } else { + // Parse the path from expected "slice:prefix:name" + // for e.g. "system.slice:docker:1234" + parts := strings.Split(myCgroupPath, ":") + if len(parts) != 3 { + return nil, fmt.Errorf("expected cgroupsPath to be of format \"slice:prefix:name\" for systemd cgroups") + } + c.Parent = parts[0] + c.ScopePrefix = parts[1] + c.Name = parts[2] + } + } else { + if myCgroupPath == "" { + myCgroupPath, err = cgroups.GetThisCgroupDir("devices") + if err != nil { + return nil, err + } + myCgroupPath = filepath.Join(myCgroupPath, name) + } + c.Path = myCgroupPath + } + c.Resources.AllowedDevices = allowedDevices r := spec.Linux.Resources if r == nil { diff --git a/spec_test.go b/spec_test.go index 156ee62c..73af04c3 100644 --- a/spec_test.go +++ b/spec_test.go @@ -15,7 +15,7 @@ func TestLinuxCgroupsPathSpecified(t *testing.T) { spec := &specs.Spec{} spec.Linux.CgroupsPath = &cgroupsPath - cgroup, err := createCgroupConfig("ContainerID", spec) + cgroup, err := createCgroupConfig("ContainerID", false, spec) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) } @@ -28,7 +28,7 @@ func TestLinuxCgroupsPathSpecified(t *testing.T) { func TestLinuxCgroupsPathNotSpecified(t *testing.T) { spec := &specs.Spec{} - cgroup, err := createCgroupConfig("ContainerID", spec) + cgroup, err := createCgroupConfig("ContainerID", false, spec) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) } diff --git a/utils.go b/utils.go index 01b07e0a..f5d29c3e 100644 --- a/utils.go +++ b/utils.go @@ -12,6 +12,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" "github.com/opencontainers/runc/libcontainer" + "github.com/opencontainers/runc/libcontainer/cgroups/systemd" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/specs/specs-go" ) @@ -146,7 +147,15 @@ func loadFactory(context *cli.Context) (libcontainer.Factory, error) { if err != nil { return nil, err } - return libcontainer.New(abs, libcontainer.Cgroupfs, func(l *libcontainer.LinuxFactory) error { + cgroupManager := libcontainer.Cgroupfs + if context.GlobalBool("systemd-cgroup") { + if systemd.UseSystemd() { + cgroupManager = libcontainer.SystemdCgroups + } else { + return nil, fmt.Errorf("systemd cgroup flag passed, but systemd support for managing cgroups is not available.") + } + } + return libcontainer.New(abs, cgroupManager, func(l *libcontainer.LinuxFactory) error { l.CriuPath = context.GlobalString("criu") return nil }) @@ -285,7 +294,7 @@ func createPidFile(path string, process *libcontainer.Process) error { } func createContainer(context *cli.Context, id string, spec *specs.Spec) (libcontainer.Container, error) { - config, err := createLibcontainerConfig(id, spec) + config, err := createLibcontainerConfig(id, context.GlobalBool("systemd-cgroup"), spec) if err != nil { return nil, err }