From fafc7a8b1a7d45e6b13b88068240f1149cfa9f22 Mon Sep 17 00:00:00 2001 From: Eric Ernst Date: Sat, 11 Jun 2022 10:47:20 +0200 Subject: [PATCH] virtcontainers: tests: Ensure Linux specific tests are just run on Linux Fixes: #5993 Several tests utilize linux'isms like Mounts, bindmounts, vsock etc. Let's ensure that these are still tested on Linux, but that we also skip these tests when on other operating systems (Darwin). This commit just moves tests; there shouldn't be any functional test changes. While the tests still won't be runnable on Darwin/other hosts yet, this is a necessary step forward. Signed-off-by: Eric Ernst Signed-off-by: Danny Canter --- .../virtcontainers/acrn_arch_base_test.go | 3 + .../virtcontainers/container_linux_test.go | 302 ++++++++++++++++++ src/runtime/virtcontainers/container_test.go | 284 ---------------- .../virtcontainers/hypervisor_linux_test.go | 30 ++ src/runtime/virtcontainers/hypervisor_test.go | 17 - .../virtcontainers/kata_agent_linux_test.go | 79 +++++ src/runtime/virtcontainers/kata_agent_test.go | 62 +--- .../virtcontainers/sandbox_linux_test.go | 117 +++++++ src/runtime/virtcontainers/sandbox_test.go | 95 ------ .../virtcontainers_darwin_test.go | 16 + .../virtcontainers_linux_test.go | 21 ++ .../virtcontainers/virtcontainers_test.go | 11 - src/runtime/virtcontainers/vm_linux_test.go | 36 +++ src/runtime/virtcontainers/vm_test.go | 42 --- 14 files changed, 605 insertions(+), 510 deletions(-) create mode 100644 src/runtime/virtcontainers/container_linux_test.go create mode 100644 src/runtime/virtcontainers/hypervisor_linux_test.go create mode 100644 src/runtime/virtcontainers/kata_agent_linux_test.go create mode 100644 src/runtime/virtcontainers/sandbox_linux_test.go create mode 100644 src/runtime/virtcontainers/virtcontainers_darwin_test.go create mode 100644 src/runtime/virtcontainers/virtcontainers_linux_test.go create mode 100644 src/runtime/virtcontainers/vm_linux_test.go diff --git a/src/runtime/virtcontainers/acrn_arch_base_test.go b/src/runtime/virtcontainers/acrn_arch_base_test.go index 3d168f56f9..61db474164 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 0000000000..4e35648141 --- /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 7a165ce9fc..0115fb011d 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 0000000000..7aead27f1b --- /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 6e2fb540ba..e540aea481 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 0000000000..05c2d3cd76 --- /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 885fd8acc7..3b95b07799 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 0000000000..f08ac6d4ed --- /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 59ed24c1aa..53a6294f5b 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 0000000000..9c9bb263c6 --- /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 0000000000..52c9462c62 --- /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 b7117000ce..0a269b8b93 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 0000000000..1ba589f02d --- /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 0d50a69def..f37cd97155 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)) -}