diff --git a/pkg/disk/disk.go b/pkg/disk/disk.go index 1af5ee06d..3ee51dbeb 100644 --- a/pkg/disk/disk.go +++ b/pkg/disk/disk.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io/fs" + "os" "path" limaStore "github.com/lima-vm/lima/pkg/store" @@ -121,7 +122,15 @@ func (m *userDataDiskManager) createLimaDisk() error { func (m *userDataDiskManager) attachPersistentDiskToLimaDisk() error { limaPath := fmt.Sprintf("%s/_disks/%s/datadisk", m.finch.LimaHomePath(), diskName) if !m.persistentDiskExists() { - err := m.fs.Rename(limaPath, m.finch.UserDataDiskPath(m.homeDir)) + disksDir := path.Dir(m.finch.UserDataDiskPath(m.homeDir)) + _, err := m.fs.Stat(disksDir) + if os.IsNotExist(err) { + err := m.fs.MkdirAll(disksDir, 0o755) + if err != nil { + return fmt.Errorf("could not create persistent disk directory: %w", err) + } + } + err = m.fs.Rename(limaPath, m.finch.UserDataDiskPath(m.homeDir)) if err != nil { return err } diff --git a/pkg/disk/disk_test.go b/pkg/disk/disk_test.go index a7c89b73e..4dcf2a501 100644 --- a/pkg/disk/disk_test.go +++ b/pkg/disk/disk_test.go @@ -58,6 +58,7 @@ func TestUserDataDiskManager_InitializeUserDataDisk(t *testing.T) { cmd.EXPECT().Run().Return(nil) dfs.EXPECT().Stat(finch.UserDataDiskPath(homeDir)).Return(nil, fs.ErrNotExist) + dfs.EXPECT().Stat(path.Dir(finch.UserDataDiskPath(homeDir))).Return(nil, nil) dfs.EXPECT().Rename(limaPath, finch.UserDataDiskPath(homeDir)).Return(nil) dfs.EXPECT().Stat(limaPath).Return(nil, fs.ErrNotExist) @@ -89,6 +90,7 @@ func TestUserDataDiskManager_InitializeUserDataDisk(t *testing.T) { dfs.EXPECT().ReadlinkIfPossible(limaPath).Return("", nil) dfs.EXPECT().Stat(finch.UserDataDiskPath(homeDir)).Return(nil, fs.ErrNotExist) + dfs.EXPECT().Stat(path.Dir(finch.UserDataDiskPath(homeDir))).Return(nil, nil) dfs.EXPECT().Rename(limaPath, finch.UserDataDiskPath(homeDir)).Return(nil) dfs.EXPECT().Stat(limaPath).Return(nil, fs.ErrNotExist) diff --git a/pkg/path/finch.go b/pkg/path/finch.go index b5472ed06..ff8d0013f 100644 --- a/pkg/path/finch.go +++ b/pkg/path/finch.go @@ -5,6 +5,7 @@ package path import ( + "crypto/sha256" "fmt" "github.com/runfinch/finch/pkg/system" @@ -20,8 +21,8 @@ func (Finch) ConfigFilePath(homeDir string) string { // UserDataDiskPath returns the path to the permanent storage location of the Finch // user data disk. -func (Finch) UserDataDiskPath(homeDir string) string { - return fmt.Sprintf("%s/.finch/.datadisk", homeDir) +func (w Finch) UserDataDiskPath(homeDir string) string { + return fmt.Sprintf("%s/.finch/.disks/%s", homeDir, w.generatePathSum()) } // LimaHomePath returns the path that should be set to LIMA_HOME for Finch. @@ -29,6 +30,11 @@ func (w Finch) LimaHomePath() string { return fmt.Sprintf("%s/lima/data", w) } +// LimaInstancePath returns the path to the Lima instance of the Finch VM. +func (w Finch) LimaInstancePath() string { + return fmt.Sprintf("%s/lima/data/finch", w) +} + // LimactlPath returns the limactl path. func (w Finch) LimactlPath() string { return fmt.Sprintf("%s/lima/bin/limactl", w) @@ -60,6 +66,11 @@ func (w Finch) LimaSSHPrivateKeyPath() string { return fmt.Sprintf("%s/lima/data/_config/user", w) } +func (w Finch) generatePathSum() string { + sum := sha256.Sum256([]byte(w.LimaInstancePath())) + return fmt.Sprintf("%x", sum[:8]) +} + // FinchFinderDeps provides all the dependencies FindFinch needs to find Finch. // //go:generate mockgen -copyright_file=../../copyright_header -destination=../mocks/finch_finder_deps.go -package=mocks -mock_names FinchFinderDeps=FinchFinderDeps . FinchFinderDeps diff --git a/pkg/path/finch_test.go b/pkg/path/finch_test.go index c1cb2d5d4..f37b5a55c 100644 --- a/pkg/path/finch_test.go +++ b/pkg/path/finch_test.go @@ -27,7 +27,7 @@ func TestFinch_UserDataDiskPath(t *testing.T) { t.Parallel() res := mockFinch.UserDataDiskPath("homeDir") - assert.Equal(t, res, "homeDir/.finch/.datadisk") + assert.Equal(t, res, fmt.Sprintf("homeDir/.finch/.disks/%s", mockFinch.generatePathSum())) } func TestFinch_LimaHomePath(t *testing.T) { @@ -37,6 +37,13 @@ func TestFinch_LimaHomePath(t *testing.T) { assert.Equal(t, res, "mock_finch/lima/data") } +func TestFinch_LimaInstancePath(t *testing.T) { + t.Parallel() + + res := mockFinch.LimaInstancePath() + assert.Equal(t, res, "mock_finch/lima/data/finch") +} + func TestFinch_LimactlPath(t *testing.T) { t.Parallel()