diff --git a/virtcontainers/acrn.go b/virtcontainers/acrn.go index c308055b41..a7faed7cf9 100644 --- a/virtcontainers/acrn.go +++ b/virtcontainers/acrn.go @@ -370,7 +370,7 @@ func (a *acrn) startSandbox(timeoutSecs int) error { a.Logger().WithField("default-kernel-parameters", formatted).Debug() } - vmPath := filepath.Join(store.RunVMStoragePath, a.id) + vmPath := filepath.Join(store.RunVMStoragePath(), a.id) err := os.MkdirAll(vmPath, store.DirMode) if err != nil { return err @@ -574,7 +574,7 @@ func (a *acrn) getSandboxConsole(id string) (string, error) { span, _ := a.trace("getSandboxConsole") defer span.Finish() - return utils.BuildSocketPath(store.RunVMStoragePath, id, acrnConsoleSocket) + return utils.BuildSocketPath(store.RunVMStoragePath(), id, acrnConsoleSocket) } func (a *acrn) saveSandbox() error { diff --git a/virtcontainers/acrn_test.go b/virtcontainers/acrn_test.go index 912dbb6d1e..a755439da0 100644 --- a/virtcontainers/acrn_test.go +++ b/virtcontainers/acrn_test.go @@ -199,7 +199,7 @@ func TestAcrnGetSandboxConsole(t *testing.T) { ctx: context.Background(), } sandboxID := "testSandboxID" - expected := filepath.Join(store.RunVMStoragePath, sandboxID, consoleSocket) + expected := filepath.Join(store.RunVMStoragePath(), sandboxID, consoleSocket) result, err := a.getSandboxConsole(sandboxID) assert.NoError(err) diff --git a/virtcontainers/api.go b/virtcontainers/api.go index 97b0f44aa1..7541823ad7 100644 --- a/virtcontainers/api.go +++ b/virtcontainers/api.go @@ -307,7 +307,7 @@ func ListSandbox(ctx context.Context) ([]SandboxStatus, error) { span, ctx := trace(ctx, "ListSandbox") defer span.Finish() - dir, err := os.Open(store.ConfigStoragePath) + dir, err := os.Open(store.ConfigStoragePath()) if err != nil { if os.IsNotExist(err) { // No sandbox directory is not an error diff --git a/virtcontainers/container.go b/virtcontainers/container.go index cbe979386d..4b9f97ae28 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -1103,7 +1103,7 @@ func (c *Container) stop(force bool) error { return err } - if err := bindUnmountContainerRootfs(c.ctx, kataHostSharedDir, c.sandbox.id, c.id); err != nil && !force { + if err := bindUnmountContainerRootfs(c.ctx, kataHostSharedDir(), c.sandbox.id, c.id); err != nil && !force { return err } @@ -1350,7 +1350,7 @@ func (c *Container) plugDevice(devicePath string) error { if c.checkBlockDeviceSupport() && stat.Mode&unix.S_IFBLK == unix.S_IFBLK { b, err := c.sandbox.devManager.NewDevice(config.DeviceInfo{ HostPath: devicePath, - ContainerPath: filepath.Join(kataGuestSharedDir, c.id), + ContainerPath: filepath.Join(kataGuestSharedDir(), c.id), DevType: "b", Major: int64(unix.Major(stat.Rdev)), Minor: int64(unix.Minor(stat.Rdev)), diff --git a/virtcontainers/hypervisor.go b/virtcontainers/hypervisor.go index acae8b82ee..e910f21864 100644 --- a/virtcontainers/hypervisor.go +++ b/virtcontainers/hypervisor.go @@ -688,7 +688,7 @@ func generateVMSocket(id string, useVsock bool) (interface{}, error) { }, nil } - path, err := utils.BuildSocketPath(filepath.Join(store.RunVMStoragePath, id), defaultSocketName) + path, err := utils.BuildSocketPath(filepath.Join(store.RunVMStoragePath(), id), defaultSocketName) if err != nil { return nil, err } diff --git a/virtcontainers/kata_agent.go b/virtcontainers/kata_agent.go index 26b4ae6726..064011bbf3 100644 --- a/virtcontainers/kata_agent.go +++ b/virtcontainers/kata_agent.go @@ -23,6 +23,7 @@ import ( aTypes "github.com/kata-containers/agent/pkg/types" kataclient "github.com/kata-containers/agent/protocols/client" "github.com/kata-containers/agent/protocols/grpc" + "github.com/kata-containers/runtime/pkg/rootless" "github.com/kata-containers/runtime/virtcontainers/device/config" persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations" @@ -56,10 +57,10 @@ var ( defaultRequestTimeout = 60 * time.Second errorMissingProxy = errors.New("Missing proxy pointer") errorMissingOCISpec = errors.New("Missing OCI specification") - kataHostSharedDir = "/run/kata-containers/shared/sandboxes/" - kataGuestSharedDir = "/run/kata-containers/shared/containers/" + defaultKataHostSharedDir = "/run/kata-containers/shared/sandboxes/" + defaultKataGuestSharedDir = "/run/kata-containers/shared/containers/" mountGuest9pTag = "kataShared" - kataGuestSandboxDir = "/run/kata-containers/sandbox/" + defaultKataGuestSandboxDir = "/run/kata-containers/sandbox/" type9pFs = "9p" typeVirtioFS = "virtio_fs" typeVirtioFSNoCache = "none" @@ -71,11 +72,11 @@ var ( kataNvdimmDevType = "nvdimm" kataVirtioFSDevType = "virtio-fs" sharedDir9pOptions = []string{"trans=virtio,version=9p2000.L,cache=mmap", "nodev"} - sharedDirVirtioFSOptions = []string{"default_permissions,allow_other,rootmode=040000,user_id=0,group_id=0,tag=" + mountGuest9pTag, "nodev"} + sharedDirVirtioFSOptions = []string{"default_permissions,allow_other,rootmode=040000,user_id=0,group_id=0,dax,tag=" + mountGuest9pTag, "nodev"} sharedDirVirtioFSDaxOptions = "dax" shmDir = "shm" kataEphemeralDevType = "ephemeral" - ephemeralPath = filepath.Join(kataGuestSandboxDir, kataEphemeralDevType) + defaultEphemeralPath = filepath.Join(defaultKataGuestSandboxDir, kataEphemeralDevType) grpcMaxDataSize = int64(1024 * 1024) localDirOptions = []string{"mode=0777"} maxHostnameLen = 64 @@ -124,6 +125,40 @@ const ( grpcStopTracingRequest = "grpc.StopTracingRequest" ) +// The function is declared this way for mocking in unit tests +var kataHostSharedDir = func() string { + if rootless.IsRootless() { + // filepath.Join removes trailing slashes, but it is necessary for mounting + return filepath.Join(rootless.GetRootlessDir(), defaultKataHostSharedDir) + "/" + } + return defaultKataHostSharedDir +} + +// The function is declared this way for mocking in unit tests +var kataGuestSharedDir = func() string { + if rootless.IsRootless() { + // filepath.Join removes trailing slashes, but it is necessary for mounting + return filepath.Join(rootless.GetRootlessDir(), defaultKataGuestSharedDir) + "/" + } + return defaultKataGuestSharedDir +} + +// The function is declared this way for mocking in unit tests +var kataGuestSandboxDir = func() string { + if rootless.IsRootless() { + // filepath.Join removes trailing slashes, but it is necessary for mounting + return filepath.Join(rootless.GetRootlessDir(), defaultKataGuestSandboxDir) + "/" + } + return defaultKataGuestSandboxDir +} + +func ephemeralPath() string { + if rootless.IsRootless() { + return filepath.Join(kataGuestSandboxDir(), kataEphemeralDevType) + } + return defaultEphemeralPath +} + // KataAgentConfig is a structure storing information needed // to reach the Kata Containers agent. type KataAgentConfig struct { @@ -182,11 +217,11 @@ func (k *kataAgent) Logger() *logrus.Entry { } func (k *kataAgent) getVMPath(id string) string { - return filepath.Join(store.RunVMStoragePath, id) + return filepath.Join(store.RunVMStoragePath(), id) } func (k *kataAgent) getSharePath(id string) string { - return filepath.Join(kataHostSharedDir, id) + return filepath.Join(kataHostSharedDir(), id) } // KataAgentSetDefaultTraceConfigOptions validates agent trace options and @@ -838,7 +873,7 @@ func setupStorages(sandbox *Sandbox) []*grpc.Storage { sharedVolume := &grpc.Storage{ Driver: kataVirtioFSDevType, Source: "none", - MountPoint: kataGuestSharedDir, + MountPoint: kataGuestSharedDir(), Fstype: typeVirtioFS, Options: sharedDirVirtioFSOptions, } @@ -850,7 +885,7 @@ func setupStorages(sandbox *Sandbox) []*grpc.Storage { sharedVolume := &grpc.Storage{ Driver: kata9pDevType, Source: mountGuest9pTag, - MountPoint: kataGuestSharedDir, + MountPoint: kataGuestSharedDir(), Fstype: type9pFs, Options: sharedDir9pOptions, } @@ -860,7 +895,7 @@ func setupStorages(sandbox *Sandbox) []*grpc.Storage { } if sandbox.shmSize > 0 { - path := filepath.Join(kataGuestSandboxDir, shmDir) + path := filepath.Join(kataGuestSandboxDir(), shmDir) shmSizeOption := fmt.Sprintf("size=%d", sandbox.shmSize) shmStorage := &grpc.Storage{ @@ -970,7 +1005,7 @@ func (k *kataAgent) replaceOCIMountsForStorages(spec *specs.Spec, volumeStorages // Create a temporary location to mount the Storage. Mounting to the correct location // will be handled by the OCI mount structure. filename := fmt.Sprintf("%s-%s", uuid.Generate().String(), filepath.Base(m.Destination)) - path := filepath.Join(kataGuestSharedDir, filename) + path := filepath.Join(kataGuestSharedDir(), filename) k.Logger().Debugf("Replacing OCI mount source (%s) with %s", m.Source, path) ociMounts[index].Source = path @@ -1052,7 +1087,7 @@ func (k *kataAgent) handleShm(grpcSpec *grpc.Spec, sandbox *Sandbox) { if sandbox.shmSize > 0 { grpcSpec.Mounts[idx].Type = "bind" grpcSpec.Mounts[idx].Options = []string{"rbind"} - grpcSpec.Mounts[idx].Source = filepath.Join(kataGuestSandboxDir, shmDir) + grpcSpec.Mounts[idx].Source = filepath.Join(kataGuestSandboxDir(), shmDir) k.Logger().WithField("shm-size", sandbox.shmSize).Info("Using sandbox shm") } else { sizeOption := fmt.Sprintf("size=%d", DefaultShmSize) @@ -1121,7 +1156,7 @@ func (k *kataAgent) rollbackFailingContainerCreation(c *Container) { k.Logger().WithError(err2).Error("rollback failed unmountHostMounts()") } - if err2 := bindUnmountContainerRootfs(k.ctx, kataHostSharedDir, c.sandbox.id, c.id); err2 != nil { + if err2 := bindUnmountContainerRootfs(k.ctx, kataHostSharedDir(), c.sandbox.id, c.id); err2 != nil { k.Logger().WithError(err2).Error("rollback failed bindUnmountContainerRootfs()") } } @@ -1189,7 +1224,7 @@ func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPat // (kataGuestSharedDir) is already mounted in the // guest. We only need to mount the rootfs from // the host and it will show up in the guest. - if err := bindMountContainerRootfs(k.ctx, kataHostSharedDir, sandbox.id, c.id, c.rootFs.Target, false); err != nil { + if err := bindMountContainerRootfs(k.ctx, kataHostSharedDir(), sandbox.id, c.id, c.rootFs.Target, false); err != nil { return nil, err } @@ -1215,7 +1250,7 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process, var rootfs *grpc.Storage // This is the guest absolute root path for that container. - rootPathParent := filepath.Join(kataGuestSharedDir, c.id) + rootPathParent := filepath.Join(kataGuestSharedDir(), c.id) rootPath := filepath.Join(rootPathParent, c.rootfsSuffix) // In case the container creation fails, the following defer statement @@ -1242,7 +1277,7 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process, } // Handle container mounts - newMounts, ignoredMounts, err := c.mountSharedDirMounts(kataHostSharedDir, kataGuestSharedDir) + newMounts, ignoredMounts, err := c.mountSharedDirMounts(kataHostSharedDir(), kataGuestSharedDir()) if err != nil { return nil, err } @@ -1345,7 +1380,7 @@ func (k *kataAgent) handleEphemeralStorage(mounts []specs.Mount) []*grpc.Storage for idx, mnt := range mounts { if mnt.Type == KataEphemeralDevType { // Set the mount source path to a path that resides inside the VM - mounts[idx].Source = filepath.Join(ephemeralPath, filepath.Base(mnt.Source)) + mounts[idx].Source = filepath.Join(ephemeralPath(), filepath.Base(mnt.Source)) // Set the mount type to "bind" mounts[idx].Type = "bind" @@ -1374,7 +1409,7 @@ func (k *kataAgent) handleLocalStorage(mounts []specs.Mount, sandboxID string, r // We rely on the fact that the first container in the VM has the same ID as the sandbox ID. // In Kubernetes, this is usually the pause container and we depend on it existing for // local directories to work. - mounts[idx].Source = filepath.Join(kataGuestSharedDir, sandboxID, rootfsSuffix, KataLocalDevType, filepath.Base(mnt.Source)) + mounts[idx].Source = filepath.Join(kataGuestSharedDir(), sandboxID, rootfsSuffix, KataLocalDevType, filepath.Base(mnt.Source)) // Create a storage struct so that the kata agent is able to create the // directory inside the VM. diff --git a/virtcontainers/kata_agent_test.go b/virtcontainers/kata_agent_test.go index 0376823281..b25e06c143 100644 --- a/virtcontainers/kata_agent_test.go +++ b/virtcontainers/kata_agent_test.go @@ -6,6 +6,7 @@ package virtcontainers import ( + "bufio" "context" "fmt" "io/ioutil" @@ -25,6 +26,7 @@ import ( aTypes "github.com/kata-containers/agent/pkg/types" pb "github.com/kata-containers/agent/protocols/grpc" + "github.com/kata-containers/runtime/pkg/rootless" "github.com/kata-containers/runtime/virtcontainers/device/api" "github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/drivers" @@ -359,7 +361,7 @@ func TestHandleEphemeralStorage(t *testing.T) { epheStorages := k.handleEphemeralStorage(ociMounts) epheMountPoint := epheStorages[0].GetMountPoint() - expected := filepath.Join(ephemeralPath, filepath.Base(mountSource)) + expected := filepath.Join(ephemeralPath(), filepath.Base(mountSource)) assert.Equal(t, epheMountPoint, expected, "Ephemeral mount point didn't match: got %s, expecting %s", epheMountPoint, expected) } @@ -384,7 +386,7 @@ func TestHandleLocalStorage(t *testing.T) { assert.Equal(t, len(localStorages), 1) localMountPoint := localStorages[0].GetMountPoint() - expected := filepath.Join(kataGuestSharedDir, sandboxID, rootfsSuffix, KataLocalDevType, filepath.Base(mountSource)) + expected := filepath.Join(kataGuestSharedDir(), sandboxID, rootfsSuffix, KataLocalDevType, filepath.Base(mountSource)) assert.Equal(t, localMountPoint, expected) } @@ -531,7 +533,7 @@ func TestHandleShm(t *testing.T) { assert.NotEmpty(g.Mounts[0].Destination) assert.Equal(g.Mounts[0].Destination, "/dev/shm") assert.Equal(g.Mounts[0].Type, "bind") - assert.NotEmpty(g.Mounts[0].Source, filepath.Join(kataGuestSharedDir, shmDir)) + assert.NotEmpty(g.Mounts[0].Source, filepath.Join(kataGuestSharedDir(), shmDir)) assert.Equal(g.Mounts[0].Options, []string{"rbind"}) sandbox.shmSize = 0 @@ -896,7 +898,10 @@ func TestKataCleanupSandbox(t *testing.T) { assert := assert.New(t) kataHostSharedDirSaved := kataHostSharedDir - kataHostSharedDir, _ = ioutil.TempDir("", "kata-cleanup") + kataHostSharedDir = func() string { + td, _ := ioutil.TempDir("", "kata-cleanup") + return td + } defer func() { kataHostSharedDir = kataHostSharedDirSaved }() @@ -904,7 +909,7 @@ func TestKataCleanupSandbox(t *testing.T) { s := Sandbox{ id: "testFoo", } - dir := path.Join(kataHostSharedDir, s.id) + dir := path.Join(kataHostSharedDir(), s.id) err := os.MkdirAll(dir, 0777) assert.Nil(err) @@ -1110,3 +1115,29 @@ func TestKataAgentSetDefaultTraceConfigOptions(t *testing.T) { } } } + +func TestKataAgentDirs(t *testing.T) { + assert := assert.New(t) + + uidmapFile, err := os.OpenFile("/proc/self/uid_map", os.O_RDONLY, 0) + assert.NoError(err) + + line, err := bufio.NewReader(uidmapFile).ReadBytes('\n') + assert.NoError(err) + + uidmap := strings.Fields(string(line)) + expectedRootless := (uidmap[0] == "0" && uidmap[1] != "0") + assert.Equal(expectedRootless, rootless.IsRootless()) + + if expectedRootless { + assert.Equal(kataHostSharedDir(), os.Getenv("XDG_RUNTIME_DIR")+defaultKataHostSharedDir) + assert.Equal(kataGuestSharedDir(), os.Getenv("XDG_RUNTIME_DIR")+defaultKataGuestSharedDir) + assert.Equal(kataGuestSandboxDir(), os.Getenv("XDG_RUNTIME_DIR")+defaultKataGuestSandboxDir) + assert.Equal(ephemeralPath(), os.Getenv("XDG_RUNTIME_DIR")+defaultEphemeralPath) + } else { + assert.Equal(kataHostSharedDir(), defaultKataHostSharedDir) + assert.Equal(kataGuestSharedDir(), defaultKataGuestSharedDir) + assert.Equal(kataGuestSandboxDir(), defaultKataGuestSandboxDir) + assert.Equal(ephemeralPath(), defaultEphemeralPath) + } +} diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index 2ef9eda937..60ae2cd23d 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -338,7 +338,7 @@ func (q *qemu) memoryTopology() (govmmQemu.Memory, error) { } func (q *qemu) qmpSocketPath(id string) (string, error) { - return utils.BuildSocketPath(store.RunVMStoragePath, id, qmpSocket) + return utils.BuildSocketPath(store.RunVMStoragePath(), id, qmpSocket) } func (q *qemu) getQemuMachine() (govmmQemu.Machine, error) { @@ -582,7 +582,7 @@ func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNa VGA: "none", GlobalParam: "kvm-pit.lost_tick_policy=discard", Bios: firmwarePath, - PidFile: filepath.Join(store.RunVMStoragePath, q.id, "pid"), + PidFile: filepath.Join(store.RunVMStoragePath(), q.id, "pid"), } if ioThread != nil { @@ -604,14 +604,14 @@ func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNa } func (q *qemu) vhostFSSocketPath(id string) (string, error) { - return utils.BuildSocketPath(store.RunVMStoragePath, id, vhostFSSocket) + return utils.BuildSocketPath(store.RunVMStoragePath(), id, vhostFSSocket) } func (q *qemu) virtiofsdArgs(sockPath string) []string { // The daemon will terminate when the vhost-user socket // connection with QEMU closes. Therefore we do not keep track // of this child process after returning from this function. - sourcePath := filepath.Join(kataHostSharedDir, q.id) + sourcePath := filepath.Join(kataHostSharedDir(), q.id) args := []string{ "-o", "vhost_user_socket=" + sockPath, "-o", "source=" + sourcePath, @@ -732,7 +732,7 @@ func (q *qemu) startSandbox(timeout int) error { q.fds = []*os.File{} }() - vmPath := filepath.Join(store.RunVMStoragePath, q.id) + vmPath := filepath.Join(store.RunVMStoragePath(), q.id) err := os.MkdirAll(vmPath, store.DirMode) if err != nil { return err @@ -908,7 +908,7 @@ func (q *qemu) stopSandbox() error { func (q *qemu) cleanupVM() error { // cleanup vm path - dir := filepath.Join(store.RunVMStoragePath, q.id) + dir := filepath.Join(store.RunVMStoragePath(), q.id) // If it's a symlink, remove both dir and the target. // This can happen when vm template links a sandbox to a vm. @@ -1623,7 +1623,7 @@ func (q *qemu) getSandboxConsole(id string) (string, error) { span, _ := q.trace("getSandboxConsole") defer span.Finish() - return utils.BuildSocketPath(store.RunVMStoragePath, id, consoleSocket) + return utils.BuildSocketPath(store.RunVMStoragePath(), id, consoleSocket) } func (q *qemu) saveSandbox() error { diff --git a/virtcontainers/qemu_test.go b/virtcontainers/qemu_test.go index c64af10af1..759cabe209 100644 --- a/virtcontainers/qemu_test.go +++ b/virtcontainers/qemu_test.go @@ -289,7 +289,7 @@ func TestQemuGetSandboxConsole(t *testing.T) { ctx: context.Background(), } sandboxID := "testSandboxID" - expected := filepath.Join(store.RunVMStoragePath, sandboxID, consoleSocket) + expected := filepath.Join(store.RunVMStoragePath(), sandboxID, consoleSocket) result, err := q.getSandboxConsole(sandboxID) assert.NoError(err) @@ -496,7 +496,9 @@ func TestQemuVirtiofsdArgs(t *testing.T) { } savedKataHostSharedDir := kataHostSharedDir - kataHostSharedDir = "test-share-dir" + kataHostSharedDir = func() string { + return "test-share-dir" + } defer func() { kataHostSharedDir = savedKataHostSharedDir }() diff --git a/virtcontainers/sandbox_test.go b/virtcontainers/sandbox_test.go index 9402b96f72..807f3e9104 100644 --- a/virtcontainers/sandbox_test.go +++ b/virtcontainers/sandbox_test.go @@ -1423,8 +1423,8 @@ func checkSandboxRemains() error { if err = checkDirNotExist(sandboxDirState); err != nil { return fmt.Errorf("%s still exists", sandboxDirState) } - if err = checkDirNotExist(path.Join(kataHostSharedDir, testSandboxID)); err != nil { - return fmt.Errorf("%s still exists", path.Join(kataHostSharedDir, testSandboxID)) + if err = checkDirNotExist(path.Join(kataHostSharedDir(), testSandboxID)); err != nil { + return fmt.Errorf("%s still exists", path.Join(kataHostSharedDir(), testSandboxID)) } if _, err = globalSandboxList.lookupSandbox(testSandboxID); err == nil { return fmt.Errorf("globalSandboxList for %s stil exists", testSandboxID) diff --git a/virtcontainers/store/filesystem_backend.go b/virtcontainers/store/filesystem_backend.go index 2f90477ae3..82b0642053 100644 --- a/virtcontainers/store/filesystem_backend.go +++ b/virtcontainers/store/filesystem_backend.go @@ -14,6 +14,7 @@ import ( "path/filepath" "syscall" + "github.com/kata-containers/runtime/pkg/rootless" "github.com/kata-containers/runtime/virtcontainers/pkg/uuid" opentracing "github.com/opentracing/opentracing-go" "github.com/sirupsen/logrus" @@ -65,15 +66,36 @@ const VMPathSuffix = "vm" // ConfigStoragePath is the sandbox configuration directory. // It will contain one config.json file for each created sandbox. -var ConfigStoragePath = filepath.Join("/var/lib", StoragePathSuffix, SandboxPathSuffix) +// The function is declared this way for mocking in unit tests +var ConfigStoragePath = func() string { + path := filepath.Join("/var/lib", StoragePathSuffix, SandboxPathSuffix) + if rootless.IsRootless() { + return filepath.Join(rootless.GetRootlessDir(), path) + } + return path +} // RunStoragePath is the sandbox runtime directory. // It will contain one state.json and one lock file for each created sandbox. -var RunStoragePath = filepath.Join("/run", StoragePathSuffix, SandboxPathSuffix) +// The function is declared this way for mocking in unit tests +var RunStoragePath = func() string { + path := filepath.Join("/run", StoragePathSuffix, SandboxPathSuffix) + if rootless.IsRootless() { + return filepath.Join(rootless.GetRootlessDir(), path) + } + return path +} // RunVMStoragePath is the vm directory. // It will contain all guest vm sockets and shared mountpoints. -var RunVMStoragePath = filepath.Join("/run", StoragePathSuffix, VMPathSuffix) +// The function is declared this way for mocking in unit tests +var RunVMStoragePath = func() string { + path := filepath.Join("/run", StoragePathSuffix, VMPathSuffix) + if rootless.IsRootless() { + return filepath.Join(rootless.GetRootlessDir(), path) + } + return path +} func itemToFile(item Item) (string, error) { switch item { diff --git a/virtcontainers/store/manager_test.go b/virtcontainers/store/manager_test.go index 0a15ffc6fb..06708d0f4b 100644 --- a/virtcontainers/store/manager_test.go +++ b/virtcontainers/store/manager_test.go @@ -112,17 +112,24 @@ func TestMain(m *testing.M) { panic(err) } + ConfigStoragePathSaved := ConfigStoragePath + RunStoragePathSaved := RunStoragePath // allow the tests to run without affecting the host system. - ConfigStoragePath = filepath.Join(testDir, StoragePathSuffix, "config") - RunStoragePath = filepath.Join(testDir, StoragePathSuffix, "run") + ConfigStoragePath = func() string { return filepath.Join(testDir, StoragePathSuffix, "config") } + RunStoragePath = func() string { return filepath.Join(testDir, StoragePathSuffix, "run") } + + defer func() { + ConfigStoragePath = ConfigStoragePathSaved + RunStoragePath = RunStoragePathSaved + }() // set now that ConfigStoragePath has been overridden. - sandboxDirConfig = filepath.Join(ConfigStoragePath, testSandboxID) - sandboxFileConfig = filepath.Join(ConfigStoragePath, testSandboxID, ConfigurationFile) - sandboxDirState = filepath.Join(RunStoragePath, testSandboxID) - sandboxDirLock = filepath.Join(RunStoragePath, testSandboxID) - sandboxFileState = filepath.Join(RunStoragePath, testSandboxID, StateFile) - sandboxFileLock = filepath.Join(RunStoragePath, testSandboxID, LockFile) + sandboxDirConfig = filepath.Join(ConfigStoragePath(), testSandboxID) + sandboxFileConfig = filepath.Join(ConfigStoragePath(), testSandboxID, ConfigurationFile) + sandboxDirState = filepath.Join(RunStoragePath(), testSandboxID) + sandboxDirLock = filepath.Join(RunStoragePath(), testSandboxID) + sandboxFileState = filepath.Join(RunStoragePath(), testSandboxID, StateFile) + sandboxFileLock = filepath.Join(RunStoragePath(), testSandboxID, LockFile) ret := m.Run() diff --git a/virtcontainers/store/vc.go b/virtcontainers/store/vc.go index 10e729ef04..9b456043f8 100644 --- a/virtcontainers/store/vc.go +++ b/virtcontainers/store/vc.go @@ -233,13 +233,14 @@ func (s *VCStore) Unlock(token string) error { // SandboxConfigurationRoot returns a virtcontainers sandbox configuration root URL. // This will hold across host reboot persistent data about a sandbox configuration. // It should look like file:///var/lib/vc/sbs// +// Or for rootless: file:///var/lib/vc/sbs// func SandboxConfigurationRoot(id string) string { - return filesystemScheme + "://" + filepath.Join(ConfigStoragePath, id) + return filesystemScheme + "://" + filepath.Join(ConfigStoragePath(), id) } // SandboxConfigurationRootPath returns a virtcontainers sandbox configuration root path. func SandboxConfigurationRootPath(id string) string { - return filepath.Join(ConfigStoragePath, id) + return filepath.Join(ConfigStoragePath(), id) } // SandboxConfigurationItemPath returns a virtcontainers sandbox configuration item path. @@ -253,20 +254,21 @@ func SandboxConfigurationItemPath(id string, item Item) (string, error) { return "", err } - return filepath.Join(ConfigStoragePath, id, itemFile), nil + return filepath.Join(ConfigStoragePath(), id, itemFile), nil } // SandboxRuntimeRoot returns a virtcontainers sandbox runtime root URL. // This will hold data related to a sandbox run-time state that will not // be persistent across host reboots. // It should look like file:///run/vc/sbs// +// or if rootless: file:///run/vc/sbs// func SandboxRuntimeRoot(id string) string { - return filesystemScheme + "://" + filepath.Join(RunStoragePath, id) + return filesystemScheme + "://" + filepath.Join(RunStoragePath(), id) } // SandboxRuntimeRootPath returns a virtcontainers sandbox runtime root path. func SandboxRuntimeRootPath(id string) string { - return filepath.Join(RunStoragePath, id) + return filepath.Join(RunStoragePath(), id) } // SandboxRuntimeItemPath returns a virtcontainers sandbox runtime item path. @@ -280,32 +282,34 @@ func SandboxRuntimeItemPath(id string, item Item) (string, error) { return "", err } - return filepath.Join(RunStoragePath, id, itemFile), nil + return filepath.Join(RunStoragePath(), id, itemFile), nil } // ContainerConfigurationRoot returns a virtcontainers container configuration root URL. // This will hold across host reboot persistent data about a container configuration. // It should look like file:///var/lib/vc/sbs// +// Or if rootless file:///var/lib/vc/sbs// func ContainerConfigurationRoot(sandboxID, containerID string) string { - return filesystemScheme + "://" + filepath.Join(ConfigStoragePath, sandboxID, containerID) + return filesystemScheme + "://" + filepath.Join(ConfigStoragePath(), sandboxID, containerID) } // ContainerConfigurationRootPath returns a virtcontainers container configuration root path. func ContainerConfigurationRootPath(sandboxID, containerID string) string { - return filepath.Join(ConfigStoragePath, sandboxID, containerID) + return filepath.Join(ConfigStoragePath(), sandboxID, containerID) } // ContainerRuntimeRoot returns a virtcontainers container runtime root URL. // This will hold data related to a container run-time state that will not // be persistent across host reboots. // It should look like file:///run/vc/sbs/// +// Or for rootless file:///run/vc/sbs/// func ContainerRuntimeRoot(sandboxID, containerID string) string { - return filesystemScheme + "://" + filepath.Join(RunStoragePath, sandboxID, containerID) + return filesystemScheme + "://" + filepath.Join(RunStoragePath(), sandboxID, containerID) } // ContainerRuntimeRootPath returns a virtcontainers container runtime root path. func ContainerRuntimeRootPath(sandboxID, containerID string) string { - return filepath.Join(RunStoragePath, sandboxID, containerID) + return filepath.Join(RunStoragePath(), sandboxID, containerID) } // VCSandboxStoreExists returns true if a sandbox store already exists. diff --git a/virtcontainers/store/vc_test.go b/virtcontainers/store/vc_test.go index 63449249bd..754b0f210b 100644 --- a/virtcontainers/store/vc_test.go +++ b/virtcontainers/store/vc_test.go @@ -14,7 +14,7 @@ import ( ) func TestStoreVCRoots(t *testing.T) { - rootURL := filesystemScheme + "://" + ConfigStoragePath + rootURL := filesystemScheme + "://" + ConfigStoragePath() sandboxID := "sandbox" containerID := "container" sConfigRoot := rootURL + "/" + sandboxID diff --git a/virtcontainers/virtcontainers_test.go b/virtcontainers/virtcontainers_test.go index 21c499d524..7b0ccbda68 100644 --- a/virtcontainers/virtcontainers_test.go +++ b/virtcontainers/virtcontainers_test.go @@ -126,18 +126,25 @@ func TestMain(m *testing.M) { setupAcrn() + ConfigStoragePathSaved := store.ConfigStoragePath + RunStoragePathSaved := store.RunStoragePath // allow the tests to run without affecting the host system. - store.ConfigStoragePath = filepath.Join(testDir, store.StoragePathSuffix, "config") - store.RunStoragePath = filepath.Join(testDir, store.StoragePathSuffix, "run") + store.ConfigStoragePath = func() string { return filepath.Join(testDir, store.StoragePathSuffix, "config") } + store.RunStoragePath = func() string { return filepath.Join(testDir, store.StoragePathSuffix, "run") } fs.TestSetRunStoragePath(filepath.Join(testDir, "vc", "sbs")) + defer func() { + store.ConfigStoragePath = ConfigStoragePathSaved + store.RunStoragePath = RunStoragePathSaved + }() + // set now that configStoragePath has been overridden. - sandboxDirConfig = filepath.Join(store.ConfigStoragePath, testSandboxID) - sandboxFileConfig = filepath.Join(store.ConfigStoragePath, testSandboxID, store.ConfigurationFile) - sandboxDirState = filepath.Join(store.RunStoragePath, testSandboxID) - sandboxDirLock = filepath.Join(store.RunStoragePath, testSandboxID) - sandboxFileState = filepath.Join(store.RunStoragePath, testSandboxID, store.StateFile) - sandboxFileLock = filepath.Join(store.RunStoragePath, testSandboxID, store.LockFile) + sandboxDirConfig = filepath.Join(store.ConfigStoragePath(), testSandboxID) + sandboxFileConfig = filepath.Join(store.ConfigStoragePath(), testSandboxID, store.ConfigurationFile) + sandboxDirState = filepath.Join(store.RunStoragePath(), testSandboxID) + sandboxDirLock = filepath.Join(store.RunStoragePath(), testSandboxID) + sandboxFileState = filepath.Join(store.RunStoragePath(), testSandboxID, store.StateFile) + sandboxFileLock = filepath.Join(store.RunStoragePath(), testSandboxID, store.LockFile) testHyperstartCtlSocket = filepath.Join(testDir, "test_hyper.sock") testHyperstartTtySocket = filepath.Join(testDir, "test_tty.sock") diff --git a/virtcontainers/vm.go b/virtcontainers/vm.go index af24cca72d..77f85450cb 100644 --- a/virtcontainers/vm.go +++ b/virtcontainers/vm.go @@ -286,7 +286,7 @@ func NewVMFromGrpc(ctx context.Context, v *pb.GrpcVM, config VMConfig) (*VM, err } func buildVMSharePath(id string) string { - return filepath.Join(store.RunVMStoragePath, id, "shared") + return filepath.Join(store.RunVMStoragePath(), id, "shared") } func (v *VM) logger() logrus.FieldLogger {