From 0e16bd9b53eb3c57ea6fe59fc6d9385c2edb9fd9 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Fri, 6 Apr 2018 10:26:08 -0700 Subject: [PATCH] Detect whether Delegate is available on both slices and scopes Starting with systemd 237, in preparation for cgroup v2, delegation is only now available for scopes, not slices. Update libcontainer code to detect whether delegation is available on both and use that information when creating new slices. Signed-off-by: Filipe Brandenburger --- libcontainer/cgroups/systemd/apply_systemd.go | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/libcontainer/cgroups/systemd/apply_systemd.go b/libcontainer/cgroups/systemd/apply_systemd.go index 3c1543e8169..ac65d43adc7 100644 --- a/libcontainer/cgroups/systemd/apply_systemd.go +++ b/libcontainer/cgroups/systemd/apply_systemd.go @@ -75,7 +75,8 @@ var ( hasStartTransientUnit bool hasStartTransientSliceUnit bool hasTransientDefaultDependencies bool - hasDelegate bool + hasDelegateScope bool + hasDelegateSlice bool ) func newProp(name string, units interface{}) systemdDbus.Property { @@ -150,12 +151,12 @@ func UseSystemd() bool { theConn.StopUnit(scope, "replace", nil) // Assume StartTransientUnit on a scope allows Delegate - hasDelegate = true - dl := newProp("Delegate", true) - if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{dl}, nil); err != nil { + hasDelegateScope = true + dlScope := newProp("Delegate", true) + if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{dlScope}, nil); err != nil { if dbusError, ok := err.(dbus.Error); ok { if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") { - hasDelegate = false + hasDelegateScope = false } } } @@ -187,6 +188,22 @@ func UseSystemd() bool { time.Sleep(time.Millisecond) } + // Not critical because of the stop unit logic above. + theConn.StopUnit(slice, "replace", nil) + + // Assume StartTransientUnit on a slice allows Delegate + hasDelegateSlice = true + dlSlice := newProp("Delegate", true) + if _, err := theConn.StartTransientUnit(slice, "replace", []systemdDbus.Property{dlSlice}, nil); err != nil { + if dbusError, ok := err.(dbus.Error); ok { + // Starting with systemd v237, Delegate is not even a property of slices anymore, + // so the D-Bus call fails with "InvalidArgs" error. + if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") || strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.InvalidArgs") { + hasDelegateSlice = false + } + } + } + // Not critical because of the stop unit logic above. theConn.StopUnit(scope, "replace", nil) theConn.StopUnit(slice, "replace", nil) @@ -242,9 +259,16 @@ func (m *Manager) Apply(pid int) error { properties = append(properties, newProp("PIDs", []uint32{uint32(pid)})) } - if hasDelegate { - // This is only supported on systemd versions 218 and above. - properties = append(properties, newProp("Delegate", true)) + // Check if we can delegate. This is only supported on systemd versions 218 and above. + if strings.HasSuffix(unitName, ".slice") { + if hasDelegateSlice { + // systemd 237 and above no longer allows delegation on a slice + properties = append(properties, newProp("Delegate", true)) + } + } else { + if hasDelegateScope { + properties = append(properties, newProp("Delegate", true)) + } } // Always enable accounting, this gets us the same behaviour as the fs implementation,