diff --git a/src/runtime/virtcontainers/acrn_arch_base_test.go b/src/runtime/virtcontainers/acrn_arch_base_test.go index 3d168f56f9f1..61db4741641b 100644 --- a/src/runtime/virtcontainers/acrn_arch_base_test.go +++ b/src/runtime/virtcontainers/acrn_arch_base_test.go @@ -3,6 +3,9 @@ // SPDX-License-Identifier: Apache-2.0 // +//go:build linux +// +build linux + package virtcontainers import ( diff --git a/src/runtime/virtcontainers/container_linux_test.go b/src/runtime/virtcontainers/container_linux_test.go new file mode 100644 index 000000000000..4e35648141cd --- /dev/null +++ b/src/runtime/virtcontainers/container_linux_test.go @@ -0,0 +1,302 @@ +// Copyright (c) 2017 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "strings" + "syscall" + "testing" + + "github.com/kata-containers/kata-containers/src/runtime/pkg/device/config" + "github.com/kata-containers/kata-containers/src/runtime/pkg/device/manager" + ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" + "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist" + "github.com/stretchr/testify/assert" +) + +func TestUnmountHostMountsRemoveBindHostPath(t *testing.T) { + if tc.NotValid(ktu.NeedRoot()) { + t.Skip(testDisabledAsNonRoot) + } + + createFakeMountDir := func(t *testing.T, dir, prefix string) string { + name, err := os.MkdirTemp(dir, "test-mnt-"+prefix+"-") + if err != nil { + t.Fatal(err) + } + return name + } + + createFakeMountFile := func(t *testing.T, dir, prefix string) string { + f, err := os.CreateTemp(dir, "test-mnt-"+prefix+"-") + if err != nil { + t.Fatal(err) + } + f.Close() + return f.Name() + } + + doUnmountCheck := func(s *Sandbox, src, dest, hostPath, nonEmptyHostpath, devPath string) { + mounts := []Mount{ + { + Source: src, + Destination: dest, + HostPath: hostPath, + Type: "bind", + }, + { + Source: src, + Destination: dest, + HostPath: nonEmptyHostpath, + Type: "bind", + }, + { + Source: src, + Destination: dest, + HostPath: devPath, + Type: "dev", + }, + } + + c := Container{ + mounts: mounts, + ctx: context.Background(), + id: "fooabr", + sandbox: s, + } + + if err := bindMount(c.ctx, src, hostPath, false, "private"); err != nil { + t.Fatal(err) + } + defer syscall.Unmount(hostPath, 0) + if err := bindMount(c.ctx, src, nonEmptyHostpath, false, "private"); err != nil { + t.Fatal(err) + } + defer syscall.Unmount(nonEmptyHostpath, 0) + if err := bindMount(c.ctx, src, devPath, false, "private"); err != nil { + t.Fatal(err) + } + defer syscall.Unmount(devPath, 0) + + err := c.unmountHostMounts(c.ctx) + if err != nil { + t.Fatal(err) + } + + for _, path := range [3]string{src, dest, devPath} { + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + t.Fatalf("path %s should not be removed", path) + } else { + t.Fatal(err) + } + } + } + + if _, err := os.Stat(hostPath); err == nil { + t.Fatal("empty host-path should be removed") + } else if !os.IsNotExist(err) { + t.Fatal(err) + } + + if _, err := os.Stat(nonEmptyHostpath); err != nil { + if os.IsNotExist(err) { + t.Fatal("non-empty host-path should not be removed") + } else { + t.Fatal(err) + } + } + } + + src := createFakeMountDir(t, testDir, "src") + dest := createFakeMountDir(t, testDir, "dest") + hostPath := createFakeMountDir(t, testDir, "host-path") + nonEmptyHostpath := createFakeMountDir(t, testDir, "non-empty-host-path") + devPath := createFakeMountDir(t, testDir, "dev-hostpath") + // create sandbox for mounting into + sandbox := &Sandbox{ + ctx: context.Background(), + id: "foobar", + config: &SandboxConfig{}, + } + + fsShare, err := NewFilesystemShare(sandbox) + if err != nil { + t.Fatal(err) + } + sandbox.fsShare = fsShare + + createFakeMountDir(t, nonEmptyHostpath, "nop") + doUnmountCheck(sandbox, src, dest, hostPath, nonEmptyHostpath, devPath) + + src = createFakeMountFile(t, testDir, "src") + dest = createFakeMountFile(t, testDir, "dest") + hostPath = createFakeMountFile(t, testDir, "host-path") + nonEmptyHostpath = createFakeMountFile(t, testDir, "non-empty-host-path") + devPath = createFakeMountFile(t, testDir, "dev-host-path") + f, err := os.OpenFile(nonEmptyHostpath, os.O_WRONLY, os.FileMode(0640)) + if err != nil { + t.Fatal(err) + } + f.WriteString("nop\n") + f.Close() + doUnmountCheck(sandbox, src, dest, hostPath, nonEmptyHostpath, devPath) +} + +func testSetupFakeRootfs(t *testing.T) (testRawFile, loopDev, mntDir string, err error) { + assert := assert.New(t) + if tc.NotValid(ktu.NeedRoot()) { + t.Skip(testDisabledAsNonRoot) + } + + tmpDir := t.TempDir() + + testRawFile = filepath.Join(tmpDir, "raw.img") + _, err = os.Stat(testRawFile) + assert.True(os.IsNotExist(err)) + + output, err := exec.Command("losetup", "-f").CombinedOutput() + assert.NoError(err) + loopDev = strings.TrimSpace(string(output[:])) + + _, err = exec.Command("fallocate", "-l", "256K", testRawFile).CombinedOutput() + assert.NoError(err) + + _, err = exec.Command("mkfs.ext4", "-F", testRawFile).CombinedOutput() + assert.NoError(err) + + _, err = exec.Command("losetup", loopDev, testRawFile).CombinedOutput() + assert.NoError(err) + + mntDir = filepath.Join(tmpDir, "rootfs") + err = os.Mkdir(mntDir, DirMode) + assert.NoError(err) + + err = syscall.Mount(loopDev, mntDir, "ext4", uintptr(0), "") + assert.NoError(err) + return +} + +func cleanupFakeRootfsSetup(testRawFile, loopDev, mntDir string) { + // unmount loop device + if mntDir != "" { + syscall.Unmount(mntDir, 0) + } + + // detach loop device + if loopDev != "" { + exec.Command("losetup", "-d", loopDev).CombinedOutput() + } + + if _, err := os.Stat(testRawFile); err == nil { + tmpDir := filepath.Dir(testRawFile) + os.RemoveAll(tmpDir) + } +} + +func TestContainerAddDriveDir(t *testing.T) { + assert := assert.New(t) + if tc.NotValid(ktu.NeedRoot()) { + t.Skip(testDisabledAsNonRoot) + } + + testRawFile, loopDev, fakeRootfs, err := testSetupFakeRootfs(t) + + defer cleanupFakeRootfsSetup(testRawFile, loopDev, fakeRootfs) + + assert.NoError(err) + + sandbox := &Sandbox{ + ctx: context.Background(), + id: testSandboxID, + devManager: manager.NewDeviceManager(config.VirtioSCSI, false, "", nil), + hypervisor: &mockHypervisor{}, + agent: &mockAgent{}, + config: &SandboxConfig{ + HypervisorConfig: HypervisorConfig{ + DisableBlockDeviceUse: false, + }, + }, + } + + sandbox.store, err = persist.GetDriver() + assert.NoError(err) + assert.NotNil(sandbox.store) + + defer sandbox.store.Destroy(sandbox.id) + + contID := "100" + container := Container{ + sandbox: sandbox, + id: contID, + rootFs: RootFs{Target: fakeRootfs, Mounted: true}, + } + + // Make the checkStorageDriver func variable point to a fake Check function + savedFunc := checkStorageDriver + checkStorageDriver = func(major, minor int) (bool, error) { + return true, nil + } + + defer func() { + checkStorageDriver = savedFunc + }() + + container.state.Fstype = "" + + err = container.hotplugDrive(sandbox.ctx) + assert.NoError(err) + + assert.NotEmpty(container.state.Fstype) +} + +func TestContainerRootfsPath(t *testing.T) { + + testRawFile, loopDev, fakeRootfs, err := testSetupFakeRootfs(t) + defer cleanupFakeRootfsSetup(testRawFile, loopDev, fakeRootfs) + assert.Nil(t, err) + + truecheckstoragedriver := checkStorageDriver + checkStorageDriver = func(major, minor int) (bool, error) { + return true, nil + } + defer func() { + checkStorageDriver = truecheckstoragedriver + }() + + sandbox := &Sandbox{ + ctx: context.Background(), + id: "rootfstestsandbox", + agent: &mockAgent{}, + hypervisor: &mockHypervisor{}, + config: &SandboxConfig{ + HypervisorConfig: HypervisorConfig{ + DisableBlockDeviceUse: false, + }, + }, + } + + container := Container{ + id: "rootfstestcontainerid", + sandbox: sandbox, + rootFs: RootFs{Target: fakeRootfs, Mounted: true}, + rootfsSuffix: "rootfs", + } + + container.hotplugDrive(sandbox.ctx) + assert.Empty(t, container.rootfsSuffix) + + // Reset the value to test the other case + container.rootFs = RootFs{Target: fakeRootfs + "/rootfs", Mounted: true} + container.rootfsSuffix = "rootfs" + + container.hotplugDrive(sandbox.ctx) + assert.Equal(t, container.rootfsSuffix, "rootfs") +} diff --git a/src/runtime/virtcontainers/container_test.go b/src/runtime/virtcontainers/container_test.go index 7a165ce9fc3b..0115fb011d30 100644 --- a/src/runtime/virtcontainers/container_test.go +++ b/src/runtime/virtcontainers/container_test.go @@ -8,9 +8,7 @@ package virtcontainers import ( "context" "os" - "os/exec" "path/filepath" - "strings" "syscall" "testing" @@ -18,8 +16,6 @@ import ( "github.com/kata-containers/kata-containers/src/runtime/pkg/device/config" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/drivers" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/manager" - ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" - "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/stretchr/testify/assert" ) @@ -124,286 +120,6 @@ func TestContainerRemoveDrive(t *testing.T) { assert.Nil(t, err, "remove drive should succeed") } -func TestUnmountHostMountsRemoveBindHostPath(t *testing.T) { - if tc.NotValid(ktu.NeedRoot()) { - t.Skip(testDisabledAsNonRoot) - } - - createFakeMountDir := func(t *testing.T, dir, prefix string) string { - name, err := os.MkdirTemp(dir, "test-mnt-"+prefix+"-") - if err != nil { - t.Fatal(err) - } - return name - } - - createFakeMountFile := func(t *testing.T, dir, prefix string) string { - f, err := os.CreateTemp(dir, "test-mnt-"+prefix+"-") - if err != nil { - t.Fatal(err) - } - f.Close() - return f.Name() - } - - doUnmountCheck := func(s *Sandbox, src, dest, hostPath, nonEmptyHostpath, devPath string) { - mounts := []Mount{ - { - Source: src, - Destination: dest, - HostPath: hostPath, - Type: "bind", - }, - { - Source: src, - Destination: dest, - HostPath: nonEmptyHostpath, - Type: "bind", - }, - { - Source: src, - Destination: dest, - HostPath: devPath, - Type: "dev", - }, - } - - c := Container{ - mounts: mounts, - ctx: context.Background(), - id: "fooabr", - sandbox: s, - } - - if err := bindMount(c.ctx, src, hostPath, false, "private"); err != nil { - t.Fatal(err) - } - defer syscall.Unmount(hostPath, 0) - if err := bindMount(c.ctx, src, nonEmptyHostpath, false, "private"); err != nil { - t.Fatal(err) - } - defer syscall.Unmount(nonEmptyHostpath, 0) - if err := bindMount(c.ctx, src, devPath, false, "private"); err != nil { - t.Fatal(err) - } - defer syscall.Unmount(devPath, 0) - - err := c.unmountHostMounts(c.ctx) - if err != nil { - t.Fatal(err) - } - - for _, path := range [3]string{src, dest, devPath} { - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - t.Fatalf("path %s should not be removed", path) - } else { - t.Fatal(err) - } - } - } - - if _, err := os.Stat(hostPath); err == nil { - t.Fatal("empty host-path should be removed") - } else if !os.IsNotExist(err) { - t.Fatal(err) - } - - if _, err := os.Stat(nonEmptyHostpath); err != nil { - if os.IsNotExist(err) { - t.Fatal("non-empty host-path should not be removed") - } else { - t.Fatal(err) - } - } - } - - src := createFakeMountDir(t, testDir, "src") - dest := createFakeMountDir(t, testDir, "dest") - hostPath := createFakeMountDir(t, testDir, "host-path") - nonEmptyHostpath := createFakeMountDir(t, testDir, "non-empty-host-path") - devPath := createFakeMountDir(t, testDir, "dev-hostpath") - // create sandbox for mounting into - sandbox := &Sandbox{ - ctx: context.Background(), - id: "foobar", - config: &SandboxConfig{}, - } - - fsShare, err := NewFilesystemShare(sandbox) - if err != nil { - t.Fatal(err) - } - sandbox.fsShare = fsShare - - createFakeMountDir(t, nonEmptyHostpath, "nop") - doUnmountCheck(sandbox, src, dest, hostPath, nonEmptyHostpath, devPath) - - src = createFakeMountFile(t, testDir, "src") - dest = createFakeMountFile(t, testDir, "dest") - hostPath = createFakeMountFile(t, testDir, "host-path") - nonEmptyHostpath = createFakeMountFile(t, testDir, "non-empty-host-path") - devPath = createFakeMountFile(t, testDir, "dev-host-path") - f, err := os.OpenFile(nonEmptyHostpath, os.O_WRONLY, os.FileMode(0640)) - if err != nil { - t.Fatal(err) - } - f.WriteString("nop\n") - f.Close() - doUnmountCheck(sandbox, src, dest, hostPath, nonEmptyHostpath, devPath) -} - -func testSetupFakeRootfs(t *testing.T) (testRawFile, loopDev, mntDir string, err error) { - assert := assert.New(t) - if tc.NotValid(ktu.NeedRoot()) { - t.Skip(testDisabledAsNonRoot) - } - - tmpDir := t.TempDir() - - testRawFile = filepath.Join(tmpDir, "raw.img") - _, err = os.Stat(testRawFile) - assert.True(os.IsNotExist(err)) - - output, err := exec.Command("losetup", "-f").CombinedOutput() - assert.NoError(err) - loopDev = strings.TrimSpace(string(output[:])) - - _, err = exec.Command("fallocate", "-l", "256K", testRawFile).CombinedOutput() - assert.NoError(err) - - _, err = exec.Command("mkfs.ext4", "-F", testRawFile).CombinedOutput() - assert.NoError(err) - - _, err = exec.Command("losetup", loopDev, testRawFile).CombinedOutput() - assert.NoError(err) - - mntDir = filepath.Join(tmpDir, "rootfs") - err = os.Mkdir(mntDir, DirMode) - assert.NoError(err) - - err = syscall.Mount(loopDev, mntDir, "ext4", uintptr(0), "") - assert.NoError(err) - return -} - -func cleanupFakeRootfsSetup(testRawFile, loopDev, mntDir string) { - // unmount loop device - if mntDir != "" { - syscall.Unmount(mntDir, 0) - } - - // detach loop device - if loopDev != "" { - exec.Command("losetup", "-d", loopDev).CombinedOutput() - } - - if _, err := os.Stat(testRawFile); err == nil { - tmpDir := filepath.Dir(testRawFile) - os.RemoveAll(tmpDir) - } -} - -func TestContainerAddDriveDir(t *testing.T) { - assert := assert.New(t) - if tc.NotValid(ktu.NeedRoot()) { - t.Skip(testDisabledAsNonRoot) - } - - testRawFile, loopDev, fakeRootfs, err := testSetupFakeRootfs(t) - - defer cleanupFakeRootfsSetup(testRawFile, loopDev, fakeRootfs) - - assert.NoError(err) - - sandbox := &Sandbox{ - ctx: context.Background(), - id: testSandboxID, - devManager: manager.NewDeviceManager(config.VirtioSCSI, false, "", nil), - hypervisor: &mockHypervisor{}, - agent: &mockAgent{}, - config: &SandboxConfig{ - HypervisorConfig: HypervisorConfig{ - DisableBlockDeviceUse: false, - }, - }, - } - - sandbox.store, err = persist.GetDriver() - assert.NoError(err) - assert.NotNil(sandbox.store) - - defer sandbox.store.Destroy(sandbox.id) - - contID := "100" - container := Container{ - sandbox: sandbox, - id: contID, - rootFs: RootFs{Target: fakeRootfs, Mounted: true}, - } - - // Make the checkStorageDriver func variable point to a fake Check function - savedFunc := checkStorageDriver - checkStorageDriver = func(major, minor int) (bool, error) { - return true, nil - } - - defer func() { - checkStorageDriver = savedFunc - }() - - container.state.Fstype = "" - - err = container.hotplugDrive(sandbox.ctx) - assert.NoError(err) - - assert.NotEmpty(container.state.Fstype) -} - -func TestContainerRootfsPath(t *testing.T) { - - testRawFile, loopDev, fakeRootfs, err := testSetupFakeRootfs(t) - defer cleanupFakeRootfsSetup(testRawFile, loopDev, fakeRootfs) - assert.Nil(t, err) - - truecheckstoragedriver := checkStorageDriver - checkStorageDriver = func(major, minor int) (bool, error) { - return true, nil - } - defer func() { - checkStorageDriver = truecheckstoragedriver - }() - - sandbox := &Sandbox{ - ctx: context.Background(), - id: "rootfstestsandbox", - agent: &mockAgent{}, - hypervisor: &mockHypervisor{}, - config: &SandboxConfig{ - HypervisorConfig: HypervisorConfig{ - DisableBlockDeviceUse: false, - }, - }, - } - - container := Container{ - id: "rootfstestcontainerid", - sandbox: sandbox, - rootFs: RootFs{Target: fakeRootfs, Mounted: true}, - rootfsSuffix: "rootfs", - } - - container.hotplugDrive(sandbox.ctx) - assert.Empty(t, container.rootfsSuffix) - - // Reset the value to test the other case - container.rootFs = RootFs{Target: fakeRootfs + "/rootfs", Mounted: true} - container.rootfsSuffix = "rootfs" - - container.hotplugDrive(sandbox.ctx) - assert.Equal(t, container.rootfsSuffix, "rootfs") -} - func TestCheckSandboxRunningEmptyCmdFailure(t *testing.T) { c := &Container{} err := c.checkSandboxRunning("") diff --git a/src/runtime/virtcontainers/hypervisor_linux_test.go b/src/runtime/virtcontainers/hypervisor_linux_test.go new file mode 100644 index 000000000000..7aead27f1b33 --- /dev/null +++ b/src/runtime/virtcontainers/hypervisor_linux_test.go @@ -0,0 +1,30 @@ +// Copyright (c) 2016 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import ( + "testing" + + ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" + "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" + "github.com/stretchr/testify/assert" +) + +func TestGenerateVMSocket(t *testing.T) { + assert := assert.New(t) + + if tc.NotValid(ktu.NeedRoot()) { + t.Skip(testDisabledAsNonRoot) + } + s, err := generateVMSocket("a", "") + assert.NoError(err) + vsock, ok := s.(types.VSock) + assert.True(ok) + defer assert.NoError(vsock.VhostFd.Close()) + assert.NotZero(vsock.VhostFd) + assert.NotZero(vsock.ContextID) + assert.NotZero(vsock.Port) +} diff --git a/src/runtime/virtcontainers/hypervisor_test.go b/src/runtime/virtcontainers/hypervisor_test.go index 6e2fb540ba9d..e540aea48112 100644 --- a/src/runtime/virtcontainers/hypervisor_test.go +++ b/src/runtime/virtcontainers/hypervisor_test.go @@ -10,7 +10,6 @@ import ( "os" "testing" - ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/stretchr/testify/assert" ) @@ -299,22 +298,6 @@ func genericTestRunningOnVMM(t *testing.T, data []testNestedVMMData) { } } -func TestGenerateVMSocket(t *testing.T) { - assert := assert.New(t) - - if tc.NotValid(ktu.NeedRoot()) { - t.Skip(testDisabledAsNonRoot) - } - s, err := generateVMSocket("a", "") - assert.NoError(err) - vsock, ok := s.(types.VSock) - assert.True(ok) - defer assert.NoError(vsock.VhostFd.Close()) - assert.NotZero(vsock.VhostFd) - assert.NotZero(vsock.ContextID) - assert.NotZero(vsock.Port) -} - func TestAssetPath(t *testing.T) { assert := assert.New(t) diff --git a/src/runtime/virtcontainers/kata_agent_linux_test.go b/src/runtime/virtcontainers/kata_agent_linux_test.go new file mode 100644 index 000000000000..05c2d3cd76d6 --- /dev/null +++ b/src/runtime/virtcontainers/kata_agent_linux_test.go @@ -0,0 +1,79 @@ +// Copyright (c) 2018 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import ( + "fmt" + "os" + "path" + "runtime" + "strings" + "syscall" + "testing" + + specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/stretchr/testify/assert" + + "code.cloudfoundry.org/bytefmt" +) + +func TestHandleHugepages(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("Test disabled as requires root user") + } + + assert := assert.New(t) + + dir := t.TempDir() + + k := kataAgent{} + var formattedSizes []string + var mounts []specs.Mount + var hugepageLimits []specs.LinuxHugepageLimit + + // On s390x, hugepage sizes must be set at boot and cannot be created ad hoc. Use any that + // are present (default is 1M, can only be changed on LPAR). See + // https://www.ibm.com/docs/en/linuxonibm/pdf/lku5dd05.pdf, p. 345 for more information. + if runtime.GOARCH == "s390x" { + dirs, err := os.ReadDir(sysHugepagesDir) + assert.Nil(err) + for _, dir := range dirs { + formattedSizes = append(formattedSizes, strings.TrimPrefix(dir.Name(), "hugepages-")) + } + } else { + formattedSizes = []string{"1G", "2M"} + } + + for _, formattedSize := range formattedSizes { + bytes, err := bytefmt.ToBytes(formattedSize) + assert.Nil(err) + hugepageLimits = append(hugepageLimits, specs.LinuxHugepageLimit{ + Pagesize: formattedSize, + Limit: 1_000_000 * bytes, + }) + + target := path.Join(dir, fmt.Sprintf("hugepages-%s", formattedSize)) + err = os.MkdirAll(target, 0777) + assert.NoError(err, "Unable to create dir %s", target) + + err = syscall.Mount("nodev", target, "hugetlbfs", uintptr(0), fmt.Sprintf("pagesize=%s", formattedSize)) + assert.NoError(err, "Unable to mount %s", target) + + defer syscall.Unmount(target, 0) + defer os.RemoveAll(target) + mount := specs.Mount{ + Type: KataLocalDevType, + Source: target, + } + mounts = append(mounts, mount) + } + + hugepages, err := k.handleHugepages(mounts, hugepageLimits) + + assert.NoError(err, "Unable to handle hugepages %v", hugepageLimits) + assert.NotNil(hugepages) + assert.Equal(len(hugepages), len(formattedSizes)) +} diff --git a/src/runtime/virtcontainers/kata_agent_test.go b/src/runtime/virtcontainers/kata_agent_test.go index 885fd8acc781..3b95b07799af 100644 --- a/src/runtime/virtcontainers/kata_agent_test.go +++ b/src/runtime/virtcontainers/kata_agent_test.go @@ -13,7 +13,6 @@ import ( "path" "path/filepath" "reflect" - "runtime" "strings" "syscall" "testing" @@ -21,11 +20,11 @@ import ( specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" - "code.cloudfoundry.org/bytefmt" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/api" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/config" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/drivers" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/manager" + volume "github.com/kata-containers/kata-containers/src/runtime/pkg/direct-volume" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist" pbTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols" @@ -1148,62 +1147,3 @@ func TestKataAgentDirs(t *testing.T) { expected := "/rafs/123/lowerdir" assert.Equal(rafsMountPath(cid), expected) } - -func TestHandleHugepages(t *testing.T) { - if os.Getuid() != 0 { - t.Skip("Test disabled as requires root user") - } - - assert := assert.New(t) - - dir := t.TempDir() - - k := kataAgent{} - var formattedSizes []string - var mounts []specs.Mount - var hugepageLimits []specs.LinuxHugepageLimit - - // On s390x, hugepage sizes must be set at boot and cannot be created ad hoc. Use any that - // are present (default is 1M, can only be changed on LPAR). See - // https://www.ibm.com/docs/en/linuxonibm/pdf/lku5dd05.pdf, p. 345 for more information. - if runtime.GOARCH == "s390x" { - dirs, err := os.ReadDir(sysHugepagesDir) - assert.Nil(err) - for _, dir := range dirs { - formattedSizes = append(formattedSizes, strings.TrimPrefix(dir.Name(), "hugepages-")) - } - } else { - formattedSizes = []string{"1G", "2M"} - } - - for _, formattedSize := range formattedSizes { - bytes, err := bytefmt.ToBytes(formattedSize) - assert.Nil(err) - hugepageLimits = append(hugepageLimits, specs.LinuxHugepageLimit{ - Pagesize: formattedSize, - Limit: 1_000_000 * bytes, - }) - - target := path.Join(dir, fmt.Sprintf("hugepages-%s", formattedSize)) - err = os.MkdirAll(target, 0777) - assert.NoError(err, "Unable to create dir %s", target) - - err = syscall.Mount("nodev", target, "hugetlbfs", uintptr(0), fmt.Sprintf("pagesize=%s", formattedSize)) - assert.NoError(err, "Unable to mount %s", target) - - defer syscall.Unmount(target, 0) - defer os.RemoveAll(target) - mount := specs.Mount{ - Type: KataLocalDevType, - Source: target, - } - mounts = append(mounts, mount) - } - - hugepages, err := k.handleHugepages(mounts, hugepageLimits) - - assert.NoError(err, "Unable to handle hugepages %v", hugepageLimits) - assert.NotNil(hugepages) - assert.Equal(len(hugepages), len(formattedSizes)) - -} diff --git a/src/runtime/virtcontainers/sandbox_linux_test.go b/src/runtime/virtcontainers/sandbox_linux_test.go new file mode 100644 index 000000000000..f08ac6d4ed2f --- /dev/null +++ b/src/runtime/virtcontainers/sandbox_linux_test.go @@ -0,0 +1,117 @@ +// Copyright (c) 2016 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/kata-containers/kata-containers/src/runtime/pkg/device/config" + "github.com/kata-containers/kata-containers/src/runtime/pkg/device/drivers" + "github.com/kata-containers/kata-containers/src/runtime/pkg/device/manager" + ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" + + "github.com/stretchr/testify/assert" + "golang.org/x/sys/unix" +) + +func TestSandboxAttachDevicesVhostUserBlk(t *testing.T) { + rootEnabled := true + tc := ktu.NewTestConstraint(false) + if tc.NotValid(ktu.NeedRoot()) { + rootEnabled = false + } + + tmpDir := t.TempDir() + os.RemoveAll(tmpDir) + dm := manager.NewDeviceManager(config.VirtioSCSI, true, tmpDir, nil) + + vhostUserDevNodePath := filepath.Join(tmpDir, "/block/devices/") + vhostUserSockPath := filepath.Join(tmpDir, "/block/sockets/") + deviceNodePath := filepath.Join(vhostUserDevNodePath, "vhostblk0") + deviceSockPath := filepath.Join(vhostUserSockPath, "vhostblk0") + + err := os.MkdirAll(vhostUserDevNodePath, dirMode) + assert.Nil(t, err) + err = os.MkdirAll(vhostUserSockPath, dirMode) + assert.Nil(t, err) + _, err = os.Create(deviceSockPath) + assert.Nil(t, err) + + // mknod requires root privilege, call mock function for non-root to + // get VhostUserBlk device type. + if rootEnabled == true { + + err = unix.Mknod(deviceNodePath, unix.S_IFBLK, int(unix.Mkdev(config.VhostUserBlkMajor, 0))) + assert.Nil(t, err) + } else { + savedFunc := config.GetVhostUserNodeStatFunc + + _, err = os.Create(deviceNodePath) + assert.Nil(t, err) + + config.GetVhostUserNodeStatFunc = func(devNodePath string, + devNodeStat *unix.Stat_t) error { + if deviceNodePath != devNodePath { + return fmt.Errorf("mock GetVhostUserNodeStatFunc error") + } + + devNodeStat.Rdev = unix.Mkdev(config.VhostUserBlkMajor, 0) + return nil + } + + defer func() { + config.GetVhostUserNodeStatFunc = savedFunc + }() + } + + path := "/dev/vda" + deviceInfo := config.DeviceInfo{ + HostPath: deviceNodePath, + ContainerPath: path, + DevType: "b", + Major: config.VhostUserBlkMajor, + Minor: 0, + } + + device, err := dm.NewDevice(deviceInfo) + assert.Nil(t, err) + _, ok := device.(*drivers.VhostUserBlkDevice) + assert.True(t, ok) + + c := &Container{ + id: "100", + devices: []ContainerDevice{ + { + ID: device.DeviceID(), + ContainerPath: path, + }, + }, + } + + containers := map[string]*Container{} + containers[c.id] = c + + sandbox := Sandbox{ + id: "100", + containers: containers, + hypervisor: &mockHypervisor{}, + devManager: dm, + ctx: context.Background(), + config: &SandboxConfig{}, + } + + containers[c.id].sandbox = &sandbox + + err = containers[c.id].attachDevices(context.Background()) + assert.Nil(t, err, "Error while attaching vhost-user-blk devices %s", err) + + err = containers[c.id].detachDevices(context.Background()) + assert.Nil(t, err, "Error while detaching vhost-user-blk devices %s", err) +} diff --git a/src/runtime/virtcontainers/sandbox_test.go b/src/runtime/virtcontainers/sandbox_test.go index 3d5154eaeabb..37c489427721 100644 --- a/src/runtime/virtcontainers/sandbox_test.go +++ b/src/runtime/virtcontainers/sandbox_test.go @@ -28,7 +28,6 @@ import ( "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" - "golang.org/x/sys/unix" ) // dirMode is the permission bits used for creating a directory @@ -583,100 +582,6 @@ func TestSandboxAttachDevicesVFIO(t *testing.T) { assert.Nil(t, err, "Error while detaching devices %s", err) } -func TestSandboxAttachDevicesVhostUserBlk(t *testing.T) { - rootEnabled := true - tc := ktu.NewTestConstraint(false) - if tc.NotValid(ktu.NeedRoot()) { - rootEnabled = false - } - - tmpDir := t.TempDir() - os.RemoveAll(tmpDir) - dm := manager.NewDeviceManager(config.VirtioSCSI, true, tmpDir, nil) - - vhostUserDevNodePath := filepath.Join(tmpDir, "/block/devices/") - vhostUserSockPath := filepath.Join(tmpDir, "/block/sockets/") - deviceNodePath := filepath.Join(vhostUserDevNodePath, "vhostblk0") - deviceSockPath := filepath.Join(vhostUserSockPath, "vhostblk0") - - err := os.MkdirAll(vhostUserDevNodePath, dirMode) - assert.Nil(t, err) - err = os.MkdirAll(vhostUserSockPath, dirMode) - assert.Nil(t, err) - _, err = os.Create(deviceSockPath) - assert.Nil(t, err) - - // mknod requires root privilege, call mock function for non-root to - // get VhostUserBlk device type. - if rootEnabled == true { - err = unix.Mknod(deviceNodePath, unix.S_IFBLK, int(unix.Mkdev(config.VhostUserBlkMajor, 0))) - assert.Nil(t, err) - } else { - savedFunc := config.GetVhostUserNodeStatFunc - - _, err = os.Create(deviceNodePath) - assert.Nil(t, err) - - config.GetVhostUserNodeStatFunc = func(devNodePath string, - devNodeStat *unix.Stat_t) error { - if deviceNodePath != devNodePath { - return fmt.Errorf("mock GetVhostUserNodeStatFunc error") - } - - devNodeStat.Rdev = unix.Mkdev(config.VhostUserBlkMajor, 0) - return nil - } - - defer func() { - config.GetVhostUserNodeStatFunc = savedFunc - }() - } - - path := "/dev/vda" - deviceInfo := config.DeviceInfo{ - HostPath: deviceNodePath, - ContainerPath: path, - DevType: "b", - Major: config.VhostUserBlkMajor, - Minor: 0, - } - - device, err := dm.NewDevice(deviceInfo) - assert.Nil(t, err) - _, ok := device.(*drivers.VhostUserBlkDevice) - assert.True(t, ok) - - c := &Container{ - id: "100", - devices: []ContainerDevice{ - { - ID: device.DeviceID(), - ContainerPath: path, - }, - }, - } - - containers := map[string]*Container{} - containers[c.id] = c - - sandbox := Sandbox{ - id: "100", - containers: containers, - hypervisor: &mockHypervisor{}, - devManager: dm, - ctx: context.Background(), - config: &SandboxConfig{}, - } - - containers[c.id].sandbox = &sandbox - - err = containers[c.id].attachDevices(context.Background()) - assert.Nil(t, err, "Error while attaching vhost-user-blk devices %s", err) - - err = containers[c.id].detachDevices(context.Background()) - assert.Nil(t, err, "Error while detaching vhost-user-blk devices %s", err) -} - var assetContent = []byte("FakeAsset fake asset FAKE ASSET") var assetContentHash = "92549f8d2018a95a294d28a65e795ed7d1a9d150009a28cea108ae10101178676f04ab82a6950d0099e4924f9c5e41dcba8ece56b75fc8b4e0a7492cb2a8c880" var assetContentWrongHash = "92549f8d2018a95a294d28a65e795ed7d1a9d150009a28cea108ae10101178676f04ab82a6950d0099e4924f9c5e41dcba8ece56b75fc8b4e0a7492cb2a8c881" diff --git a/src/runtime/virtcontainers/virtcontainers_darwin_test.go b/src/runtime/virtcontainers/virtcontainers_darwin_test.go new file mode 100644 index 000000000000..9c9bb263c691 --- /dev/null +++ b/src/runtime/virtcontainers/virtcontainers_darwin_test.go @@ -0,0 +1,16 @@ +// Copyright (c) 2023 Apple Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import "os" + +// cleanUp removes any stale sandbox/container state that can affect +// the next test to run. +func cleanUp() { + os.RemoveAll(testDir) + os.MkdirAll(testDir, DirMode) + setup() +} diff --git a/src/runtime/virtcontainers/virtcontainers_linux_test.go b/src/runtime/virtcontainers/virtcontainers_linux_test.go new file mode 100644 index 000000000000..52c9462c62b5 --- /dev/null +++ b/src/runtime/virtcontainers/virtcontainers_linux_test.go @@ -0,0 +1,21 @@ +// Copyright (c) 2017 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import ( + "os" + "syscall" +) + +// cleanUp Removes any stale sandbox/container state that can affect +// the next test to run. +func cleanUp() { + syscall.Unmount(GetSharePath(testSandboxID), syscall.MNT_DETACH|UmountNoFollow) + os.RemoveAll(testDir) + os.MkdirAll(testDir, DirMode) + + setup() +} diff --git a/src/runtime/virtcontainers/virtcontainers_test.go b/src/runtime/virtcontainers/virtcontainers_test.go index b7117000ce99..0a269b8b9315 100644 --- a/src/runtime/virtcontainers/virtcontainers_test.go +++ b/src/runtime/virtcontainers/virtcontainers_test.go @@ -12,7 +12,6 @@ import ( "os" "os/exec" "path/filepath" - "syscall" "testing" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/fs" @@ -54,16 +53,6 @@ var testVirtiofsdPath = "" var testHyperstartCtlSocket = "" var testHyperstartTtySocket = "" -// cleanUp Removes any stale sandbox/container state that can affect -// the next test to run. -func cleanUp() { - syscall.Unmount(GetSharePath(testSandboxID), syscall.MNT_DETACH|UmountNoFollow) - os.RemoveAll(testDir) - os.MkdirAll(testDir, DirMode) - - setup() -} - func setup() { os.Mkdir(filepath.Join(testDir, testBundle), DirMode) diff --git a/src/runtime/virtcontainers/vm_linux_test.go b/src/runtime/virtcontainers/vm_linux_test.go new file mode 100644 index 000000000000..1ba589f02d25 --- /dev/null +++ b/src/runtime/virtcontainers/vm_linux_test.go @@ -0,0 +1,36 @@ +// Copyright (c) 2018 HyperHQ Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +package virtcontainers + +import ( + "testing" + + "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" + "github.com/stretchr/testify/assert" +) + +func TestVMConfigGrpc(t *testing.T) { + assert := assert.New(t) + config := VMConfig{ + HypervisorType: QemuHypervisor, + HypervisorConfig: newQemuConfig(), + AgentConfig: KataAgentConfig{ + LongLiveConn: true, + Debug: false, + Trace: false, + EnableDebugConsole: false, + ContainerPipeSize: 0, + KernelModules: []string{}}, + } + + p, err := config.ToGrpc() + assert.Nil(err) + + config2, err := GrpcToVMConfig(p) + assert.Nil(err) + + assert.True(utils.DeepCompare(config, *config2)) +} diff --git a/src/runtime/virtcontainers/vm_test.go b/src/runtime/virtcontainers/vm_test.go index 0d50a69def8f..f37cd9715561 100644 --- a/src/runtime/virtcontainers/vm_test.go +++ b/src/runtime/virtcontainers/vm_test.go @@ -11,7 +11,6 @@ import ( "path/filepath" "testing" - "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" "github.com/stretchr/testify/assert" ) @@ -85,44 +84,3 @@ func TestNewVM(t *testing.T) { _, err = NewVM(ctx, config) assert.Nil(err) } - -func TestVMConfigValid(t *testing.T) { - assert := assert.New(t) - - config := VMConfig{} - - err := config.Valid() - assert.Error(err) - - testDir := t.TempDir() - - config.HypervisorConfig = HypervisorConfig{ - KernelPath: testDir, - InitrdPath: testDir, - } - err = config.Valid() - assert.Nil(err) -} - -func TestVMConfigGrpc(t *testing.T) { - assert := assert.New(t) - config := VMConfig{ - HypervisorType: QemuHypervisor, - HypervisorConfig: newQemuConfig(), - AgentConfig: KataAgentConfig{ - LongLiveConn: true, - Debug: false, - Trace: false, - EnableDebugConsole: false, - ContainerPipeSize: 0, - KernelModules: []string{}}, - } - - p, err := config.ToGrpc() - assert.Nil(err) - - config2, err := GrpcToVMConfig(p) - assert.Nil(err) - - assert.True(utils.DeepCompare(config, *config2)) -}