libct/cg: simplify getting cgroup manager

1. Make Rootless and Systemd flags part of config.Cgroups.

2. Make all cgroup managers (not just fs2) return error (so it can do
   more initialization -- added by the following commits).

3. Replace complicated cgroup manager instantiation in factory_linux
   by a single (and simple) libcontainer/cgroups/manager.New() function.

4. getUnifiedPath is simplified to check that only a single path is
   supplied (rather than checking that other paths, if supplied,
   are the same).

[v2: can't -> cannot]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2021-08-07 12:22:16 -07:00
parent 147ad561e8
commit 097c6d7425
17 changed files with 188 additions and 222 deletions
+12 -111
View File
@@ -14,10 +14,7 @@ import (
"github.com/moby/sys/mountinfo"
"golang.org/x/sys/unix"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fs"
"github.com/opencontainers/runc/libcontainer/cgroups/fs2"
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
"github.com/opencontainers/runc/libcontainer/cgroups/manager"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/configs/validate"
"github.com/opencontainers/runc/libcontainer/intelrdt"
@@ -30,10 +27,7 @@ const (
execFifoFilename = "exec.fifo"
)
var (
idRegex = regexp.MustCompile(`^[\w+-\.]+$`)
errNoSystemd = errors.New("systemd not running on this host, can't use systemd as cgroups manager")
)
var idRegex = regexp.MustCompile(`^[\w+-\.]+$`)
// InitArgs returns an options func to configure a LinuxFactory with the
// provided init binary path and arguments.
@@ -54,100 +48,6 @@ func InitArgs(args ...string) func(*LinuxFactory) error {
}
}
func getUnifiedPath(paths map[string]string) string {
path := ""
for k, v := range paths {
if path == "" {
path = v
} else if v != path {
panic(fmt.Errorf("expected %q path to be unified path %q, got %q", k, path, v))
}
}
// can be empty
if path != "" {
if filepath.Clean(path) != path || !filepath.IsAbs(path) {
panic(fmt.Errorf("invalid dir path %q", path))
}
}
return path
}
func systemdCgroupV2(l *LinuxFactory, rootless bool) error {
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
return systemd.NewUnifiedManager(config, getUnifiedPath(paths), rootless)
}
return nil
}
// SystemdCgroups is an options func to configure a LinuxFactory to return
// containers that use systemd to create and manage cgroups.
func SystemdCgroups(l *LinuxFactory) error {
if !systemd.IsRunningSystemd() {
return errNoSystemd
}
if cgroups.IsCgroup2UnifiedMode() {
return systemdCgroupV2(l, false)
}
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
return systemd.NewLegacyManager(config, paths)
}
return nil
}
// RootlessSystemdCgroups is rootless version of SystemdCgroups.
func RootlessSystemdCgroups(l *LinuxFactory) error {
if !systemd.IsRunningSystemd() {
return errNoSystemd
}
if !cgroups.IsCgroup2UnifiedMode() {
return errors.New("cgroup v2 not enabled on this host, can't use systemd (rootless) as cgroups manager")
}
return systemdCgroupV2(l, true)
}
func cgroupfs2(l *LinuxFactory, rootless bool) error {
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
m, err := fs2.NewManager(config, getUnifiedPath(paths), rootless)
if err != nil {
panic(err)
}
return m
}
return nil
}
func cgroupfs(l *LinuxFactory, rootless bool) error {
if cgroups.IsCgroup2UnifiedMode() {
return cgroupfs2(l, rootless)
}
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
return fs.NewManager(config, paths, rootless)
}
return nil
}
// Cgroupfs is an options func to configure a LinuxFactory to return containers
// that use the native cgroups filesystem implementation to create and manage
// cgroups.
func Cgroupfs(l *LinuxFactory) error {
return cgroupfs(l, false)
}
// RootlessCgroupfs is an options func to configure a LinuxFactory to return
// containers that use the native cgroups filesystem implementation to create
// and manage cgroups. The difference between RootlessCgroupfs and Cgroupfs is
// that RootlessCgroupfs can transparently handle permission errors that occur
// during rootless container (including euid=0 in userns) setup (while still allowing cgroup usage if
// they've been set up properly).
func RootlessCgroupfs(l *LinuxFactory) error {
return cgroupfs(l, true)
}
// IntelRdtfs is an options func to configure a LinuxFactory to return
// containers that use the Intel RDT "resource control" filesystem to
// create and manage Intel RDT resources (e.g., L3 cache, memory bandwidth).
@@ -201,10 +101,6 @@ func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
CriuPath: "criu",
}
if err := Cgroupfs(l); err != nil {
return nil, err
}
for _, opt := range options {
if opt == nil {
continue
@@ -241,9 +137,6 @@ type LinuxFactory struct {
// Validator provides validation to container configurations.
Validator validate.Validator
// NewCgroupsManager returns an initialized cgroups manager for a single container.
NewCgroupsManager func(config *configs.Cgroup, paths map[string]string) cgroups.Manager
// NewIntelRdtManager returns an initialized Intel RDT manager for a single container.
NewIntelRdtManager func(config *configs.Config, id string, path string) intelrdt.Manager
}
@@ -273,6 +166,10 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
if err := os.Chown(containerRoot, unix.Geteuid(), unix.Getegid()); err != nil {
return nil, err
}
cm, err := manager.New(config.Cgroups)
if err != nil {
return nil, err
}
c := &linuxContainer{
id: id,
root: containerRoot,
@@ -282,7 +179,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
criuPath: l.CriuPath,
newuidmapPath: l.NewuidmapPath,
newgidmapPath: l.NewgidmapPath,
cgroupManager: l.NewCgroupsManager(config.Cgroups, nil),
cgroupManager: cm,
}
if l.NewIntelRdtManager != nil {
c.intelRdtManager = l.NewIntelRdtManager(config, id, "")
@@ -312,6 +209,10 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
processStartTime: state.InitProcessStartTime,
fds: state.ExternalDescriptors,
}
cm, err := manager.NewWithPaths(state.Config.Cgroups, state.CgroupPaths)
if err != nil {
return nil, err
}
c := &linuxContainer{
initProcess: r,
initProcessStartTime: state.InitProcessStartTime,
@@ -322,7 +223,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
criuPath: l.CriuPath,
newuidmapPath: l.NewuidmapPath,
newgidmapPath: l.NewgidmapPath,
cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths),
cgroupManager: cm,
root: containerRoot,
created: state.Created,
}