cli: add systemd-cgroup option

Add support for cgroup driver systemd.
systemd cgroup is not applied in the VM since in some cases like initrd images
there is no systemd running and nobody can update a systemd cgroup using
systemctl.

fixes #596

Signed-off-by: Julio Montes <julio.montes@intel.com>
This commit is contained in:
Julio Montes 2018-09-18 14:50:09 -05:00
parent a8284f875b
commit 00751754a9
10 changed files with 91 additions and 52 deletions

View File

@ -83,6 +83,7 @@ var createCLICommand = cli.Command{
console, console,
context.String("pid-file"), context.String("pid-file"),
true, true,
context.Bool("systemd-cgroup"),
runtimeConfig, runtimeConfig,
) )
}, },
@ -91,7 +92,7 @@ var createCLICommand = cli.Command{
// Use a variable to allow tests to modify its value // Use a variable to allow tests to modify its value
var getKernelParamsFunc = getKernelParams var getKernelParamsFunc = getKernelParams
func create(ctx context.Context, containerID, bundlePath, console, pidFilePath string, detach bool, func create(ctx context.Context, containerID, bundlePath, console, pidFilePath string, detach, systemdCgroup bool,
runtimeConfig oci.RuntimeConfig) error { runtimeConfig oci.RuntimeConfig) error {
var err error var err error
@ -146,7 +147,7 @@ func create(ctx context.Context, containerID, bundlePath, console, pidFilePath s
var process vc.Process var process vc.Process
switch containerType { switch containerType {
case vc.PodSandbox: case vc.PodSandbox:
process, err = createSandbox(ctx, ociSpec, runtimeConfig, containerID, bundlePath, console, disableOutput) process, err = createSandbox(ctx, ociSpec, runtimeConfig, containerID, bundlePath, console, disableOutput, systemdCgroup)
if err != nil { if err != nil {
return err return err
} }
@ -252,7 +253,7 @@ func setKernelParams(containerID string, runtimeConfig *oci.RuntimeConfig) error
} }
func createSandbox(ctx context.Context, ociSpec oci.CompatOCISpec, runtimeConfig oci.RuntimeConfig, func createSandbox(ctx context.Context, ociSpec oci.CompatOCISpec, runtimeConfig oci.RuntimeConfig,
containerID, bundlePath, console string, disableOutput bool) (vc.Process, error) { containerID, bundlePath, console string, disableOutput, systemdCgroup bool) (vc.Process, error) {
span, ctx := trace(ctx, "createSandbox") span, ctx := trace(ctx, "createSandbox")
defer span.Finish() defer span.Finish()
@ -261,7 +262,7 @@ func createSandbox(ctx context.Context, ociSpec oci.CompatOCISpec, runtimeConfig
return vc.Process{}, err return vc.Process{}, err
} }
sandboxConfig, err := oci.SandboxConfig(ociSpec, runtimeConfig, bundlePath, containerID, console, disableOutput) sandboxConfig, err := oci.SandboxConfig(ociSpec, runtimeConfig, bundlePath, containerID, console, disableOutput, systemdCgroup)
if err != nil { if err != nil {
return vc.Process{}, err return vc.Process{}, err
} }

View File

@ -326,19 +326,20 @@ func TestCreateInvalidArgs(t *testing.T) {
console string console string
pidFilePath string pidFilePath string
detach bool detach bool
systemdCgroup bool
runtimeConfig oci.RuntimeConfig runtimeConfig oci.RuntimeConfig
} }
data := []testData{ data := []testData{
{"", "", "", "", false, oci.RuntimeConfig{}}, {"", "", "", "", false, false, oci.RuntimeConfig{}},
{"", "", "", "", true, oci.RuntimeConfig{}}, {"", "", "", "", true, true, oci.RuntimeConfig{}},
{"foo", "", "", "", true, oci.RuntimeConfig{}}, {"foo", "", "", "", true, false, oci.RuntimeConfig{}},
{testContainerID, bundlePath, testConsole, pidFilePath, false, runtimeConfig}, {testContainerID, bundlePath, testConsole, pidFilePath, false, false, runtimeConfig},
{testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig}, {testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig},
} }
for i, d := range data { for i, d := range data {
err := create(context.Background(), d.containerID, d.bundlePath, d.console, d.pidFilePath, d.detach, d.runtimeConfig) err := create(context.Background(), d.containerID, d.bundlePath, d.console, d.pidFilePath, d.detach, d.systemdCgroup, d.runtimeConfig)
assert.Errorf(err, "test %d (%+v)", i, d) assert.Errorf(err, "test %d (%+v)", i, d)
} }
} }
@ -377,7 +378,7 @@ func TestCreateInvalidConfigJSON(t *testing.T) {
f.Close() f.Close()
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.Errorf(err, "%+v", detach) assert.Errorf(err, "%+v", detach)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
os.RemoveAll(path) os.RemoveAll(path)
@ -421,7 +422,7 @@ func TestCreateInvalidContainerType(t *testing.T) {
assert.NoError(err) assert.NoError(err)
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.Errorf(err, "%+v", detach) assert.Errorf(err, "%+v", detach)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
os.RemoveAll(path) os.RemoveAll(path)
@ -466,7 +467,7 @@ func TestCreateContainerInvalid(t *testing.T) {
assert.NoError(err) assert.NoError(err)
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.Errorf(err, "%+v", detach) assert.Errorf(err, "%+v", detach)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
os.RemoveAll(path) os.RemoveAll(path)
@ -561,7 +562,7 @@ func TestCreateProcessCgroupsPathSuccessful(t *testing.T) {
assert.NoError(err) assert.NoError(err)
for _, detach := range []bool{true, false} { for _, detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, detach, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, detach, true, runtimeConfig)
assert.NoError(err, "detached: %+v", detach) assert.NoError(err, "detached: %+v", detach)
os.RemoveAll(path) os.RemoveAll(path)
} }
@ -645,7 +646,7 @@ func TestCreateCreateCgroupsFilesFail(t *testing.T) {
assert.NoError(err) assert.NoError(err)
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.Errorf(err, "%+v", detach) assert.Errorf(err, "%+v", detach)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
os.RemoveAll(path) os.RemoveAll(path)
@ -721,7 +722,7 @@ func TestCreateCreateCreatePidFileFail(t *testing.T) {
assert.NoError(err) assert.NoError(err)
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.Errorf(err, "%+v", detach) assert.Errorf(err, "%+v", detach)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
os.RemoveAll(path) os.RemoveAll(path)
@ -791,7 +792,7 @@ func TestCreate(t *testing.T) {
assert.NoError(err) assert.NoError(err)
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.NoError(err, "%+v", detach) assert.NoError(err, "%+v", detach)
os.RemoveAll(path) os.RemoveAll(path)
} }
@ -848,7 +849,7 @@ func TestCreateInvalidKernelParams(t *testing.T) {
} }
for detach := range []bool{true, false} { for detach := range []bool{true, false} {
err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, runtimeConfig) err := create(context.Background(), testContainerID, bundlePath, testConsole, pidFilePath, true, true, runtimeConfig)
assert.Errorf(err, "%+v", detach) assert.Errorf(err, "%+v", detach)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
os.RemoveAll(path) os.RemoveAll(path)
@ -893,7 +894,7 @@ func TestCreateSandboxConfigFail(t *testing.T) {
Quota: &quota, Quota: &quota,
} }
_, err = createSandbox(context.Background(), spec, runtimeConfig, testContainerID, bundlePath, testConsole, true) _, err = createSandbox(context.Background(), spec, runtimeConfig, testContainerID, bundlePath, testConsole, true, true)
assert.Error(err) assert.Error(err)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
} }
@ -928,7 +929,7 @@ func TestCreateCreateSandboxFail(t *testing.T) {
spec, err := readOCIConfigFile(ociConfigFile) spec, err := readOCIConfigFile(ociConfigFile)
assert.NoError(err) assert.NoError(err)
_, err = createSandbox(context.Background(), spec, runtimeConfig, testContainerID, bundlePath, testConsole, true) _, err = createSandbox(context.Background(), spec, runtimeConfig, testContainerID, bundlePath, testConsole, true, true)
assert.Error(err) assert.Error(err)
assert.True(vcmock.IsMockError(err)) assert.True(vcmock.IsMockError(err))
} }

View File

@ -105,6 +105,10 @@ var runtimeFlags = []cli.Flag{
Name: showConfigPathsOption, Name: showConfigPathsOption,
Usage: "show config file paths that will be checked for (in order)", Usage: "show config file paths that will be checked for (in order)",
}, },
cli.BoolFlag{
Name: "systemd-cgroup",
Usage: "enable systemd cgroup support, expects cgroupsPath to be of form \"slice:prefix:name\" for e.g. \"system.slice:runc:434234\"",
},
} }
// runtimeCommands is the list of supported command-line (sub-) // runtimeCommands is the list of supported command-line (sub-)

View File

@ -75,11 +75,12 @@ var runCLICommand = cli.Command{
context.String("console-socket"), context.String("console-socket"),
context.String("pid-file"), context.String("pid-file"),
context.Bool("detach"), context.Bool("detach"),
context.Bool("systemd-cgroup"),
runtimeConfig) runtimeConfig)
}, },
} }
func run(ctx context.Context, containerID, bundle, console, consoleSocket, pidFile string, detach bool, func run(ctx context.Context, containerID, bundle, console, consoleSocket, pidFile string, detach, systemdCgroup bool,
runtimeConfig oci.RuntimeConfig) error { runtimeConfig oci.RuntimeConfig) error {
span, ctx := trace(ctx, "run") span, ctx := trace(ctx, "run")
defer span.Finish() defer span.Finish()
@ -89,7 +90,7 @@ func run(ctx context.Context, containerID, bundle, console, consoleSocket, pidFi
return err return err
} }
if err := create(ctx, containerID, bundle, consolePath, pidFile, detach, runtimeConfig); err != nil { if err := create(ctx, containerID, bundle, consolePath, pidFile, detach, systemdCgroup, runtimeConfig); err != nil {
return err return err
} }

View File

@ -118,32 +118,33 @@ func TestRunInvalidArgs(t *testing.T) {
consoleSocket string consoleSocket string
pidFile string pidFile string
detach bool detach bool
systemdCgroup bool
runtimeConfig oci.RuntimeConfig runtimeConfig oci.RuntimeConfig
} }
args := []testArgs{ args := []testArgs{
{"", "", "", "", "", true, oci.RuntimeConfig{}}, {"", "", "", "", "", true, true, oci.RuntimeConfig{}},
{"", "", "", "", "", false, oci.RuntimeConfig{}}, {"", "", "", "", "", false, false, oci.RuntimeConfig{}},
{"", "", "", "", "", true, runtimeConfig}, {"", "", "", "", "", true, false, runtimeConfig},
{"", "", "", "", "", false, runtimeConfig}, {"", "", "", "", "", false, true, runtimeConfig},
{"", "", "", "", pidFilePath, false, runtimeConfig}, {"", "", "", "", pidFilePath, false, false, runtimeConfig},
{"", "", "", "", inexistentPath, false, runtimeConfig}, {"", "", "", "", inexistentPath, false, false, runtimeConfig},
{"", "", "", "", pidFilePath, false, runtimeConfig}, {"", "", "", "", pidFilePath, false, true, runtimeConfig},
{"", "", "", inexistentPath, pidFilePath, false, runtimeConfig}, {"", "", "", inexistentPath, pidFilePath, false, true, runtimeConfig},
{"", "", inexistentPath, inexistentPath, pidFilePath, false, runtimeConfig}, {"", "", inexistentPath, inexistentPath, pidFilePath, false, false, runtimeConfig},
{"", "", inexistentPath, "", pidFilePath, false, runtimeConfig}, {"", "", inexistentPath, "", pidFilePath, false, false, runtimeConfig},
{"", "", consolePath, "", pidFilePath, false, runtimeConfig}, {"", "", consolePath, "", pidFilePath, false, true, runtimeConfig},
{"", bundlePath, consolePath, "", pidFilePath, false, runtimeConfig}, {"", bundlePath, consolePath, "", pidFilePath, false, true, runtimeConfig},
{testContainerID, inexistentPath, consolePath, "", pidFilePath, false, oci.RuntimeConfig{}}, {testContainerID, inexistentPath, consolePath, "", pidFilePath, false, true, oci.RuntimeConfig{}},
{testContainerID, inexistentPath, consolePath, "", inexistentPath, false, oci.RuntimeConfig{}}, {testContainerID, inexistentPath, consolePath, "", inexistentPath, false, true, oci.RuntimeConfig{}},
{testContainerID, bundlePath, consolePath, "", pidFilePath, false, oci.RuntimeConfig{}}, {testContainerID, bundlePath, consolePath, "", pidFilePath, false, false, oci.RuntimeConfig{}},
{testContainerID, inexistentPath, consolePath, "", pidFilePath, false, runtimeConfig}, {testContainerID, inexistentPath, consolePath, "", pidFilePath, false, false, runtimeConfig},
{testContainerID, inexistentPath, consolePath, "", inexistentPath, false, runtimeConfig}, {testContainerID, inexistentPath, consolePath, "", inexistentPath, false, true, runtimeConfig},
{testContainerID, bundlePath, consolePath, "", pidFilePath, false, runtimeConfig}, {testContainerID, bundlePath, consolePath, "", pidFilePath, false, true, runtimeConfig},
} }
for i, a := range args { for i, a := range args {
err := run(context.Background(), a.containerID, a.bundle, a.console, a.consoleSocket, a.pidFile, a.detach, a.runtimeConfig) err := run(context.Background(), a.containerID, a.bundle, a.console, a.consoleSocket, a.pidFile, a.detach, a.systemdCgroup, a.runtimeConfig)
assert.Errorf(err, "test %d (%+v)", i, a) assert.Errorf(err, "test %d (%+v)", i, a)
} }
} }
@ -289,7 +290,7 @@ func TestRunContainerSuccessful(t *testing.T) {
testingImpl.DeleteContainerFunc = nil testingImpl.DeleteContainerFunc = nil
}() }()
err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, d.runtimeConfig) err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, true, d.runtimeConfig)
// should return ExitError with the message and exit code // should return ExitError with the message and exit code
e, ok := err.(*cli.ExitError) e, ok := err.(*cli.ExitError)
@ -367,7 +368,7 @@ func TestRunContainerDetachSuccessful(t *testing.T) {
testingImpl.DeleteContainerFunc = nil testingImpl.DeleteContainerFunc = nil
}() }()
err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, true, d.runtimeConfig) err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, true, true, d.runtimeConfig)
// should not return ExitError // should not return ExitError
assert.NoError(err) assert.NoError(err)
@ -440,7 +441,7 @@ func TestRunContainerDeleteFail(t *testing.T) {
testingImpl.DeleteContainerFunc = nil testingImpl.DeleteContainerFunc = nil
}() }()
err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, d.runtimeConfig) err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, true, d.runtimeConfig)
// should not return ExitError // should not return ExitError
err, ok := err.(*cli.ExitError) err, ok := err.(*cli.ExitError)
@ -517,7 +518,7 @@ func TestRunContainerWaitFail(t *testing.T) {
testingImpl.DeleteContainerFunc = nil testingImpl.DeleteContainerFunc = nil
}() }()
err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, d.runtimeConfig) err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, true, d.runtimeConfig)
// should not return ExitError // should not return ExitError
err, ok := err.(*cli.ExitError) err, ok := err.(*cli.ExitError)
@ -575,7 +576,7 @@ func TestRunContainerStartFail(t *testing.T) {
testingImpl.StatusContainerFunc = nil testingImpl.StatusContainerFunc = nil
}() }()
err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, d.runtimeConfig) err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, true, d.runtimeConfig)
// should not return ExitError // should not return ExitError
err, ok := err.(*cli.ExitError) err, ok := err.(*cli.ExitError)
@ -630,7 +631,7 @@ func TestRunContainerStartFailExistingContainer(t *testing.T) {
testingImpl.StartSandboxFunc = nil testingImpl.StartSandboxFunc = nil
}() }()
err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, d.runtimeConfig) err = run(context.Background(), d.sandbox.ID(), d.bundlePath, d.consolePath, "", d.pidFilePath, false, true, d.runtimeConfig)
assert.Error(err) assert.Error(err)
assert.False(vcmock.IsMockError(err)) assert.False(vcmock.IsMockError(err))
} }

View File

@ -11,6 +11,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -714,7 +715,7 @@ func (k *kataAgent) replaceOCIMountsForStorages(spec *specs.Spec, volumeStorages
return nil return nil
} }
func constraintGRPCSpec(grpcSpec *grpc.Spec) { func constraintGRPCSpec(grpcSpec *grpc.Spec, systemdCgroup bool) {
// Disable Hooks since they have been handled on the host and there is // Disable Hooks since they have been handled on the host and there is
// no reason to send them to the agent. It would make no sense to try // no reason to send them to the agent. It would make no sense to try
// to apply them on the guest. // to apply them on the guest.
@ -734,6 +735,24 @@ func constraintGRPCSpec(grpcSpec *grpc.Spec) {
grpcSpec.Linux.Resources.HugepageLimits = nil grpcSpec.Linux.Resources.HugepageLimits = nil
grpcSpec.Linux.Resources.Network = nil grpcSpec.Linux.Resources.Network = nil
// There are three main reasons to do not apply systemd cgroups in the VM
// - Initrd image doesn't have systemd.
// - Nobody will be able to modify the resources of a specific container by using systemctl set-property.
// - docker is not running in the VM.
if systemdCgroup {
// Convert systemd cgroup to cgroupfs
// systemd cgroup path: slice:prefix:name
re := regexp.MustCompile(`([[:alnum:]]|.)+:([[:alnum:]]|.)+:([[:alnum:]]|.)+`)
systemdCgroupPath := re.FindString(grpcSpec.Linux.CgroupsPath)
if systemdCgroupPath != "" {
slice := strings.Split(systemdCgroupPath, ":")
// 0 - slice: system.slice
// 1 - prefix: docker
// 2 - name: abc123
grpcSpec.Linux.CgroupsPath = filepath.Join("/", slice[1], slice[2])
}
}
// Disable network namespace since it is already handled on the host by // Disable network namespace since it is already handled on the host by
// virtcontainers. The network is a complex part which cannot be simply // virtcontainers. The network is a complex part which cannot be simply
// passed to the agent. // passed to the agent.
@ -964,7 +983,7 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
// We need to constraint the spec to make sure we're not passing // We need to constraint the spec to make sure we're not passing
// irrelevant information to the agent. // irrelevant information to the agent.
constraintGRPCSpec(grpcSpec) constraintGRPCSpec(grpcSpec, sandbox.config.SystemdCgroup)
k.handleShm(grpcSpec, sandbox) k.handleShm(grpcSpec, sandbox)

View File

@ -421,6 +421,7 @@ func TestAppendDevices(t *testing.T) {
func TestConstraintGRPCSpec(t *testing.T) { func TestConstraintGRPCSpec(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
expectedCgroupPath := "/foo/bar"
g := &pb.Spec{ g := &pb.Spec{
Hooks: &pb.Hooks{}, Hooks: &pb.Hooks{},
@ -448,10 +449,11 @@ func TestConstraintGRPCSpec(t *testing.T) {
HugepageLimits: []pb.LinuxHugepageLimit{}, HugepageLimits: []pb.LinuxHugepageLimit{},
Network: &pb.LinuxNetwork{}, Network: &pb.LinuxNetwork{},
}, },
CgroupsPath: "system.slice:foo:bar",
}, },
} }
constraintGRPCSpec(g) constraintGRPCSpec(g, true)
// check nil fields // check nil fields
assert.Nil(g.Hooks) assert.Nil(g.Hooks)
@ -470,6 +472,9 @@ func TestConstraintGRPCSpec(t *testing.T) {
// check mounts // check mounts
assert.Len(g.Mounts, 1) assert.Len(g.Mounts, 1)
// check cgroup path
assert.Equal(expectedCgroupPath, g.Linux.CgroupsPath)
} }
func TestHandleShm(t *testing.T) { func TestHandleShm(t *testing.T) {

View File

@ -453,7 +453,7 @@ func addAssetAnnotations(ocispec CompatOCISpec, config *vc.SandboxConfig) {
// SandboxConfig converts an OCI compatible runtime configuration file // SandboxConfig converts an OCI compatible runtime configuration file
// to a virtcontainers sandbox configuration structure. // to a virtcontainers sandbox configuration structure.
func SandboxConfig(ocispec CompatOCISpec, runtime RuntimeConfig, bundlePath, cid, console string, detach bool) (vc.SandboxConfig, error) { func SandboxConfig(ocispec CompatOCISpec, runtime RuntimeConfig, bundlePath, cid, console string, detach, systemdCgroup bool) (vc.SandboxConfig, error) {
containerConfig, err := ContainerConfig(ocispec, bundlePath, cid, console, detach) containerConfig, err := ContainerConfig(ocispec, bundlePath, cid, console, detach)
if err != nil { if err != nil {
return vc.SandboxConfig{}, err return vc.SandboxConfig{}, err
@ -507,6 +507,8 @@ func SandboxConfig(ocispec CompatOCISpec, runtime RuntimeConfig, bundlePath, cid
}, },
ShmSize: shmSize, ShmSize: shmSize,
SystemdCgroup: systemdCgroup,
} }
addAssetAnnotations(ocispec, &sandboxConfig) addAssetAnnotations(ocispec, &sandboxConfig)

View File

@ -231,6 +231,8 @@ func TestMinimalSandboxConfig(t *testing.T) {
vcAnnotations.ConfigJSONKey: string(ociSpecJSON), vcAnnotations.ConfigJSONKey: string(ociSpecJSON),
vcAnnotations.BundlePathKey: tempBundlePath, vcAnnotations.BundlePathKey: tempBundlePath,
}, },
SystemdCgroup: true,
} }
ociSpec, err := ParseConfigJSON(tempBundlePath) ociSpec, err := ParseConfigJSON(tempBundlePath)
@ -238,7 +240,7 @@ func TestMinimalSandboxConfig(t *testing.T) {
t.Fatalf("Could not parse config.json: %v", err) t.Fatalf("Could not parse config.json: %v", err)
} }
sandboxConfig, err := SandboxConfig(ociSpec, runtimeConfig, tempBundlePath, containerID, consolePath, false) sandboxConfig, err := SandboxConfig(ociSpec, runtimeConfig, tempBundlePath, containerID, consolePath, false, true)
if err != nil { if err != nil {
t.Fatalf("Could not create Sandbox configuration %v", err) t.Fatalf("Could not create Sandbox configuration %v", err)
} }

View File

@ -352,6 +352,9 @@ type SandboxConfig struct {
// Stateful keeps sandbox resources in memory across APIs. Users will be responsible // Stateful keeps sandbox resources in memory across APIs. Users will be responsible
// for calling Release() to release the memory resources. // for calling Release() to release the memory resources.
Stateful bool Stateful bool
// SystemdCgroup enables systemd cgroup support
SystemdCgroup bool
} }
func (s *Sandbox) trace(name string) (opentracing.Span, context.Context) { func (s *Sandbox) trace(name string) (opentracing.Span, context.Context) {