Files
kata-containers/virtcontainers/pkg/oci/utils_test.go
Jose Carlos Venegas Munoz 618cfbf1db vc: sandbox: Let sandbox manage VM resources.
- Container only is responsable of namespaces and cgroups
inside the VM.

- Sandbox will manage VM resources.

The resouces has to be re-calculated and updated:

- Create new Container: If a new container is created the cpus and memory
may be updated.

- Container update: The update call will change the cgroups of a container.
the sandbox would need to resize the cpus and VM depending the update.

To manage the resources from sandbox the hypervisor interaface adds two methods.

- resizeMemory().

This function will be used by the sandbox to request
increase or decrease the VM memory.

- resizeCPUs()

vcpus are requested to the hypervisor based
on the sum of all the containers in the sandbox.

The CPUs calculations use the container cgroup information all the time.

This should allow do better calculations.

For example.

2 containers in a pod.

container 1 cpus = .5
container 2 cpus = .5

Now:
Sandbox requested vcpus 1

Before:
Sandbox requested vcpus 2

When a update request is done only some atributes have
information. If cpu and quota are nil or 0 we dont update them.

If we would updated them the sandbox calculations would remove already
removed vcpus.

This commit also moves the sandbox resource update call at container.update()
just before the container cgroups information is updated.

Fixes: #833

Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
2018-12-13 16:33:14 -06:00

854 lines
21 KiB
Go

// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package oci
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
"testing"
"github.com/kubernetes-incubator/cri-o/pkg/annotations"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert"
"golang.org/x/sys/unix"
vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/device/config"
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
)
const (
tempBundlePath = "/tmp/virtc/ocibundle/"
containerID = "virtc-oci-test"
consolePath = "/tmp/virtc/console"
fileMode = os.FileMode(0640)
dirMode = os.FileMode(0750)
capabilitiesSpecArray = `
{
"ociVersion": "1.0.0-rc2-dev",
"process": {
"capabilities": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID"
]
}
}`
capabilitiesSpecStruct = `
{
"ociVersion": "1.0.0-rc5",
"process": {
"capabilities": {
"bounding": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID"
],
"effective": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID"
],
"inheritable": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID"
],
"permitted": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID"
]
}
}
}`
)
func createConfig(fileName string, fileData string) (string, error) {
configPath := path.Join(tempBundlePath, fileName)
err := ioutil.WriteFile(configPath, []byte(fileData), fileMode)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to create config file %s %v\n", configPath, err)
return "", err
}
return configPath, nil
}
func TestMinimalSandboxConfig(t *testing.T) {
configPath, err := createConfig("config.json", minimalConfig)
if err != nil {
t.Fatal(err)
}
savedFunc := config.GetHostPathFunc
// Simply assign container path to host path for device.
config.GetHostPathFunc = func(devInfo config.DeviceInfo) (string, error) {
return devInfo.ContainerPath, nil
}
defer func() {
config.GetHostPathFunc = savedFunc
}()
runtimeConfig := RuntimeConfig{
HypervisorType: vc.QemuHypervisor,
AgentType: vc.HyperstartAgent,
ProxyType: vc.CCProxyType,
ShimType: vc.CCShimType,
Console: consolePath,
}
capList := []string{"CAP_AUDIT_WRITE", "CAP_KILL", "CAP_NET_BIND_SERVICE"}
expectedCmd := vc.Cmd{
Args: []string{"sh"},
Envs: []vc.EnvVar{
{
Var: "PATH",
Value: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
},
{
Var: "TERM",
Value: "xterm",
},
},
WorkDir: "/",
User: "0",
PrimaryGroup: "0",
SupplementaryGroups: []string{"10", "29"},
Interactive: true,
Console: consolePath,
NoNewPrivileges: true,
Capabilities: vc.LinuxCapabilities{
Bounding: capList,
Effective: capList,
Inheritable: capList,
Permitted: capList,
Ambient: capList,
},
}
expectedMounts := []vc.Mount{
{
Source: "proc",
Destination: "/proc",
Type: "proc",
Options: nil,
HostPath: "",
},
{
Source: "tmpfs",
Destination: "/dev",
Type: "tmpfs",
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
HostPath: "",
},
{
Source: "devpts",
Destination: "/dev/pts",
Type: "devpts",
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
HostPath: "",
},
}
var minimalOCISpec CompatOCISpec
//Marshal and unmarshall json to compare sandboxConfig and expectedSandboxConfig
if err := json.Unmarshal([]byte(minimalConfig), &minimalOCISpec); err != nil {
t.Fatal(err)
}
if minimalOCISpec.Process != nil {
caps, err := ContainerCapabilities(minimalOCISpec)
if err != nil {
t.Fatal(err)
}
minimalOCISpec.Process.Capabilities = caps
}
ociSpecJSON, err := json.Marshal(minimalOCISpec)
if err != nil {
t.Fatal(err)
}
devInfo := config.DeviceInfo{
ContainerPath: "/dev/vfio/17",
Major: 242,
Minor: 0,
DevType: "c",
UID: 0,
GID: 0,
}
expectedDeviceInfo := []config.DeviceInfo{
devInfo,
}
expectedContainerConfig := vc.ContainerConfig{
ID: containerID,
RootFs: path.Join(tempBundlePath, "rootfs"),
ReadonlyRootfs: true,
Cmd: expectedCmd,
Annotations: map[string]string{
vcAnnotations.ConfigJSONKey: string(ociSpecJSON),
vcAnnotations.BundlePathKey: tempBundlePath,
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
},
Mounts: expectedMounts,
DeviceInfos: expectedDeviceInfo,
Resources: specs.LinuxResources{Devices: []specs.LinuxDeviceCgroup{
{Allow: false, Type: "", Major: (*int64)(nil), Minor: (*int64)(nil), Access: "rwm"},
}},
}
expectedNetworkConfig := vc.NetworkConfig{}
expectedSandboxConfig := vc.SandboxConfig{
ID: containerID,
Hostname: "testHostname",
HypervisorType: vc.QemuHypervisor,
AgentType: vc.HyperstartAgent,
ProxyType: vc.CCProxyType,
ShimType: vc.CCShimType,
NetworkModel: vc.DefaultNetworkModel,
NetworkConfig: expectedNetworkConfig,
Containers: []vc.ContainerConfig{expectedContainerConfig},
Annotations: map[string]string{
vcAnnotations.ConfigJSONKey: string(ociSpecJSON),
vcAnnotations.BundlePathKey: tempBundlePath,
},
SystemdCgroup: true,
}
ociSpec, err := ParseConfigJSON(tempBundlePath)
if err != nil {
t.Fatalf("Could not parse config.json: %v", err)
}
sandboxConfig, err := SandboxConfig(ociSpec, runtimeConfig, tempBundlePath, containerID, consolePath, false, true)
if err != nil {
t.Fatalf("Could not create Sandbox configuration %v", err)
}
if reflect.DeepEqual(sandboxConfig, expectedSandboxConfig) == false {
t.Fatalf("Got %v\n expecting %v", sandboxConfig, expectedSandboxConfig)
}
if err := os.Remove(configPath); err != nil {
t.Fatal(err)
}
}
func testStatusToOCIStateSuccessful(t *testing.T, cStatus vc.ContainerStatus, expected specs.State) {
ociState := StatusToOCIState(cStatus)
if reflect.DeepEqual(ociState, expected) == false {
t.Fatalf("Got %v\n expecting %v", ociState, expected)
}
}
func TestStatusToOCIStateSuccessfulWithReadyState(t *testing.T) {
testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"
state := vc.State{
State: vc.StateReady,
}
containerAnnotations := map[string]string{
vcAnnotations.ConfigJSONKey: minimalConfig,
vcAnnotations.BundlePathKey: tempBundlePath,
}
cStatus := vc.ContainerStatus{
ID: testContID,
State: state,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}
expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "created",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}
testStatusToOCIStateSuccessful(t, cStatus, expected)
}
func TestStatusToOCIStateSuccessfulWithRunningState(t *testing.T) {
testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"
state := vc.State{
State: vc.StateRunning,
}
containerAnnotations := map[string]string{
vcAnnotations.ConfigJSONKey: minimalConfig,
vcAnnotations.BundlePathKey: tempBundlePath,
}
cStatus := vc.ContainerStatus{
ID: testContID,
State: state,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}
expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "running",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}
testStatusToOCIStateSuccessful(t, cStatus, expected)
}
func TestStatusToOCIStateSuccessfulWithStoppedState(t *testing.T) {
testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"
state := vc.State{
State: vc.StateStopped,
}
containerAnnotations := map[string]string{
vcAnnotations.ConfigJSONKey: minimalConfig,
vcAnnotations.BundlePathKey: tempBundlePath,
}
cStatus := vc.ContainerStatus{
ID: testContID,
State: state,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}
expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "stopped",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}
testStatusToOCIStateSuccessful(t, cStatus, expected)
}
func TestStatusToOCIStateSuccessfulWithNoState(t *testing.T) {
testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"
containerAnnotations := map[string]string{
vcAnnotations.ConfigJSONKey: minimalConfig,
vcAnnotations.BundlePathKey: tempBundlePath,
}
cStatus := vc.ContainerStatus{
ID: testContID,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}
expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}
testStatusToOCIStateSuccessful(t, cStatus, expected)
}
func TestStateToOCIState(t *testing.T) {
var state vc.State
if ociState := StateToOCIState(state); ociState != "" {
t.Fatalf("Expecting \"created\" state, got \"%s\"", ociState)
}
state.State = vc.StateReady
if ociState := StateToOCIState(state); ociState != "created" {
t.Fatalf("Expecting \"created\" state, got \"%s\"", ociState)
}
state.State = vc.StateRunning
if ociState := StateToOCIState(state); ociState != "running" {
t.Fatalf("Expecting \"created\" state, got \"%s\"", ociState)
}
state.State = vc.StateStopped
if ociState := StateToOCIState(state); ociState != "stopped" {
t.Fatalf("Expecting \"created\" state, got \"%s\"", ociState)
}
state.State = vc.StatePaused
if ociState := StateToOCIState(state); ociState != "paused" {
t.Fatalf("Expecting \"paused\" state, got \"%s\"", ociState)
}
}
func TestEnvVars(t *testing.T) {
envVars := []string{"foo=bar", "TERM=xterm", "HOME=/home/foo", "TERM=\"bar\"", "foo=\"\""}
expectecVcEnvVars := []vc.EnvVar{
{
Var: "foo",
Value: "bar",
},
{
Var: "TERM",
Value: "xterm",
},
{
Var: "HOME",
Value: "/home/foo",
},
{
Var: "TERM",
Value: "\"bar\"",
},
{
Var: "foo",
Value: "\"\"",
},
}
vcEnvVars, err := EnvVars(envVars)
if err != nil {
t.Fatalf("Could not create environment variable slice %v", err)
}
if reflect.DeepEqual(vcEnvVars, expectecVcEnvVars) == false {
t.Fatalf("Got %v\n expecting %v", vcEnvVars, expectecVcEnvVars)
}
}
func TestMalformedEnvVars(t *testing.T) {
envVars := []string{"foo"}
r, err := EnvVars(envVars)
if err == nil {
t.Fatalf("EnvVars() succeeded unexpectedly: [%s] variable=%s value=%s", envVars[0], r[0].Var, r[0].Value)
}
envVars = []string{"=foo"}
r, err = EnvVars(envVars)
if err == nil {
t.Fatalf("EnvVars() succeeded unexpectedly: [%s] variable=%s value=%s", envVars[0], r[0].Var, r[0].Value)
}
envVars = []string{"=foo="}
r, err = EnvVars(envVars)
if err == nil {
t.Fatalf("EnvVars() succeeded unexpectedly: [%s] variable=%s value=%s", envVars[0], r[0].Var, r[0].Value)
}
}
func TestGetConfigPath(t *testing.T) {
expected := filepath.Join(tempBundlePath, "config.json")
configPath := getConfigPath(tempBundlePath)
if configPath != expected {
t.Fatalf("Got %s, Expecting %s", configPath, expected)
}
}
func testGetContainerTypeSuccessful(t *testing.T, annotations map[string]string, expected vc.ContainerType) {
containerType, err := GetContainerType(annotations)
if err != nil {
t.Fatal(err)
}
if containerType != expected {
t.Fatalf("Got %s, Expecting %s", containerType, expected)
}
}
func TestGetContainerTypePodSandbox(t *testing.T) {
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
}
testGetContainerTypeSuccessful(t, annotations, vc.PodSandbox)
}
func TestGetContainerTypePodContainer(t *testing.T) {
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
}
testGetContainerTypeSuccessful(t, annotations, vc.PodContainer)
}
func TestGetContainerTypeFailure(t *testing.T) {
expected := vc.UnknownContainerType
containerType, err := GetContainerType(map[string]string{})
if err == nil {
t.Fatalf("This test should fail because annotations is empty")
}
if containerType != expected {
t.Fatalf("Got %s, Expecting %s", containerType, expected)
}
}
func testContainerTypeSuccessful(t *testing.T, ociSpec CompatOCISpec, expected vc.ContainerType) {
containerType, err := ociSpec.ContainerType()
if err != nil {
t.Fatal(err)
}
if containerType != expected {
t.Fatalf("Got %s, Expecting %s", containerType, expected)
}
}
func TestContainerTypePodSandbox(t *testing.T) {
var ociSpec CompatOCISpec
ociSpec.Annotations = map[string]string{
annotations.ContainerType: annotations.ContainerTypeSandbox,
}
testContainerTypeSuccessful(t, ociSpec, vc.PodSandbox)
}
func TestContainerTypePodContainer(t *testing.T) {
var ociSpec CompatOCISpec
ociSpec.Annotations = map[string]string{
annotations.ContainerType: annotations.ContainerTypeContainer,
}
testContainerTypeSuccessful(t, ociSpec, vc.PodContainer)
}
func TestContainerTypePodSandboxEmptyAnnotation(t *testing.T) {
testContainerTypeSuccessful(t, CompatOCISpec{}, vc.PodSandbox)
}
func TestContainerTypeFailure(t *testing.T) {
var ociSpec CompatOCISpec
expected := vc.UnknownContainerType
unknownType := "unknown_type"
ociSpec.Annotations = map[string]string{
annotations.ContainerType: unknownType,
}
containerType, err := ociSpec.ContainerType()
if err == nil {
t.Fatalf("This test should fail because the container type is %s", unknownType)
}
if containerType != expected {
t.Fatalf("Got %s, Expecting %s", containerType, expected)
}
}
func TestSandboxIDSuccessful(t *testing.T) {
var ociSpec CompatOCISpec
testSandboxID := "testSandboxID"
ociSpec.Annotations = map[string]string{
annotations.SandboxID: testSandboxID,
}
sandboxID, err := ociSpec.SandboxID()
if err != nil {
t.Fatal(err)
}
if sandboxID != testSandboxID {
t.Fatalf("Got %s, Expecting %s", sandboxID, testSandboxID)
}
}
func TestSandboxIDFailure(t *testing.T) {
var ociSpec CompatOCISpec
sandboxID, err := ociSpec.SandboxID()
if err == nil {
t.Fatalf("This test should fail because annotations is empty")
}
if sandboxID != "" {
t.Fatalf("Got %s, Expecting empty sandbox ID", sandboxID)
}
}
func TestAddKernelParamValid(t *testing.T) {
var config RuntimeConfig
expected := []vc.Param{
{
Key: "foo",
Value: "bar",
},
}
err := config.AddKernelParam(expected[0])
if err != nil || reflect.DeepEqual(config.HypervisorConfig.KernelParams, expected) == false {
t.Fatal()
}
}
func TestAddKernelParamInvalid(t *testing.T) {
var config RuntimeConfig
invalid := []vc.Param{
{
Key: "",
Value: "bar",
},
}
err := config.AddKernelParam(invalid[0])
if err == nil {
t.Fatal()
}
}
func TestDeviceTypeFailure(t *testing.T) {
var ociSpec CompatOCISpec
invalidDeviceType := "f"
ociSpec.Linux = &specs.Linux{}
ociSpec.Linux.Devices = []specs.LinuxDevice{
{
Path: "/dev/vfio",
Type: invalidDeviceType,
},
}
_, err := containerDeviceInfos(ociSpec)
assert.NotNil(t, err, "This test should fail as device type [%s] is invalid ", invalidDeviceType)
}
func TestContains(t *testing.T) {
s := []string{"char", "block", "pipe"}
assert.True(t, contains(s, "char"))
assert.True(t, contains(s, "pipe"))
assert.False(t, contains(s, "chara"))
assert.False(t, contains(s, "socket"))
}
func TestDevicePathEmpty(t *testing.T) {
var ociSpec CompatOCISpec
ociSpec.Linux = &specs.Linux{}
ociSpec.Linux.Devices = []specs.LinuxDevice{
{
Type: "c",
Major: 252,
Minor: 1,
},
}
_, err := containerDeviceInfos(ociSpec)
assert.NotNil(t, err, "This test should fail as path cannot be empty for device")
}
func TestContainerCapabilities(t *testing.T) {
var ociSpec CompatOCISpec
ociSpec.Process = &CompatOCIProcess{}
ociSpec.Process.Capabilities = map[string]interface{}{
"bounding": []interface{}{"CAP_KILL"},
"effective": []interface{}{"CAP_KILL", "CAP_LEASE"},
"permitted": []interface{}{"CAP_SETUID"},
"inheritable": []interface{}{"CAP_KILL", "CAP_LEASE", "CAP_SYS_ADMIN"},
"ambient": []interface{}{""},
}
c, err := ContainerCapabilities(ociSpec)
assert.Nil(t, err)
assert.Equal(t, c.Bounding, []string{"CAP_KILL"})
assert.Equal(t, c.Effective, []string{"CAP_KILL", "CAP_LEASE"})
assert.Equal(t, c.Permitted, []string{"CAP_SETUID"})
assert.Equal(t, c.Inheritable, []string{"CAP_KILL", "CAP_LEASE", "CAP_SYS_ADMIN"})
assert.Equal(t, c.Ambient, []string{""})
ociSpec.Process.Capabilities = []interface{}{"CAP_LEASE", "CAP_SETUID"}
c, err = ContainerCapabilities(ociSpec)
assert.Nil(t, err)
assert.Equal(t, c.Bounding, []string{"CAP_LEASE", "CAP_SETUID"})
assert.Equal(t, c.Effective, []string{"CAP_LEASE", "CAP_SETUID"})
assert.Equal(t, c.Permitted, []string{"CAP_LEASE", "CAP_SETUID"})
assert.Equal(t, c.Inheritable, []string{"CAP_LEASE", "CAP_SETUID"})
assert.Equal(t, c.Ambient, []string{"CAP_LEASE", "CAP_SETUID"})
ociSpec.Process.Capabilities = nil
c, err = ContainerCapabilities(ociSpec)
assert.Nil(t, err)
assert.Equal(t, c.Bounding, []string(nil))
assert.Equal(t, c.Effective, []string(nil))
assert.Equal(t, c.Permitted, []string(nil))
assert.Equal(t, c.Inheritable, []string(nil))
assert.Equal(t, c.Ambient, []string(nil))
}
// use specs.Spec to decode the spec, the content of capabilities is [] string
func TestCompatOCISpecWithArray(t *testing.T) {
compatOCISpec := CompatOCISpec{}
err := json.Unmarshal([]byte(capabilitiesSpecArray), &compatOCISpec)
assert.Nil(t, err, "use CompatOCISpec to decode capabilitiesSpecArray failed")
ociSpecJSON, err := json.Marshal(compatOCISpec)
assert.Nil(t, err, "encode compatOCISpec failed")
// use specs.Spec to decode the spec, specs.Spec' capabilities is struct,
// but the content of spec' capabilities is [] string
ociSpec := specs.Spec{}
err = json.Unmarshal(ociSpecJSON, &ociSpec)
assert.NotNil(t, err, "This test should fail")
caps, err := ContainerCapabilities(compatOCISpec)
assert.Nil(t, err, "decode capabilities failed")
compatOCISpec.Process.Capabilities = caps
ociSpecJSON, err = json.Marshal(compatOCISpec)
assert.Nil(t, err, "encode compatOCISpec failed")
// capabilities has been chaged to struct
err = json.Unmarshal(ociSpecJSON, &ociSpec)
assert.Nil(t, err, "This test should fail")
}
// use specs.Spec to decode the spec, the content of capabilities is struct
func TestCompatOCISpecWithStruct(t *testing.T) {
compatOCISpec := CompatOCISpec{}
err := json.Unmarshal([]byte(capabilitiesSpecStruct), &compatOCISpec)
assert.Nil(t, err, "use CompatOCISpec to decode capabilitiesSpecStruct failed")
ociSpecJSON, err := json.Marshal(compatOCISpec)
assert.Nil(t, err, "encode compatOCISpec failed")
ociSpec := specs.Spec{}
err = json.Unmarshal(ociSpecJSON, &ociSpec)
assert.Nil(t, err, "This test should not fail")
}
func TestGetShmSize(t *testing.T) {
containerConfig := vc.ContainerConfig{
Mounts: []vc.Mount{},
}
shmSize, err := getShmSize(containerConfig)
assert.Nil(t, err)
assert.Equal(t, shmSize, uint64(0))
m := vc.Mount{
Source: "/dev/shm",
Destination: "/dev/shm",
Type: "tmpfs",
Options: nil,
}
containerConfig.Mounts = append(containerConfig.Mounts, m)
shmSize, err = getShmSize(containerConfig)
assert.Nil(t, err)
assert.Equal(t, shmSize, uint64(vc.DefaultShmSize))
containerConfig.Mounts[0].Source = "/var/run/shared/shm"
containerConfig.Mounts[0].Type = "bind"
_, err = getShmSize(containerConfig)
assert.NotNil(t, err)
}
func TestGetShmSizeBindMounted(t *testing.T) {
if os.Geteuid() != 0 {
t.Skip("Test disabled as requires root privileges")
}
dir, err := ioutil.TempDir("", "")
assert.Nil(t, err)
defer os.RemoveAll(dir)
shmPath := filepath.Join(dir, "shm")
err = os.Mkdir(shmPath, 0700)
assert.Nil(t, err)
size := 8192
shmOptions := "mode=1777,size=" + strconv.Itoa(size)
err = unix.Mount("shm", shmPath, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, shmOptions)
assert.Nil(t, err)
defer unix.Unmount(shmPath, 0)
containerConfig := vc.ContainerConfig{
Mounts: []vc.Mount{
{
Source: shmPath,
Destination: "/dev/shm",
Type: "bind",
Options: nil,
},
},
}
shmSize, err := getShmSize(containerConfig)
assert.Nil(t, err)
assert.Equal(t, shmSize, uint64(size))
}
func TestMain(m *testing.M) {
/* Create temp bundle directory if necessary */
err := os.MkdirAll(tempBundlePath, dirMode)
if err != nil {
fmt.Printf("Unable to create %s %v\n", tempBundlePath, err)
os.Exit(1)
}
defer os.RemoveAll(tempBundlePath)
os.Exit(m.Run())
}