Skip to content

Commit 77d181a

Browse files
authored
Merge pull request #4421 from ashwat287/Issue4418
fix: Remove premature return after closing sparse diff file so Convert executes.
2 parents 598e0e8 + 65b6485 commit 77d181a

File tree

3 files changed

+160
-10
lines changed

3 files changed

+160
-10
lines changed

pkg/driverutil/disk.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,23 @@ func EnsureDisk(ctx context.Context, instDir, diskSize string, diskImageFormat i
3838
if err != nil {
3939
return err
4040
}
41+
destDisk := baseDisk
4142
if isBaseDiskISO {
42-
// Create an empty data volume (sparse)
43+
destDisk = diffDisk
44+
45+
// Create an empty data volume for the diff disk
4346
diffDiskF, err := os.Create(diffDisk)
4447
if err != nil {
4548
return err
4649
}
4750

48-
err = diskUtil.MakeSparse(ctx, diffDiskF, 0)
49-
if err != nil {
50-
diffDiskF.Close()
51-
return fmt.Errorf("failed to create sparse diff disk %q: %w", diffDisk, err)
51+
if err = diffDiskF.Close(); err != nil {
52+
return err
5253
}
53-
return diffDiskF.Close()
5454
}
5555
// Check whether to use ASIF format
5656

57-
if err = diskUtil.Convert(ctx, diskImageFormat, baseDisk, diffDisk, &diskSizeInBytes, false); err != nil {
57+
if err = diskUtil.Convert(ctx, diskImageFormat, destDisk, diffDisk, &diskSizeInBytes, false); err != nil {
5858
return fmt.Errorf("failed to convert %q to a disk %q: %w", baseDisk, diffDisk, err)
5959
}
6060
return err

pkg/driverutil/disk_test.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// SPDX-FileCopyrightText: Copyright The Lima Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package driverutil
5+
6+
import (
7+
"crypto/sha256"
8+
"encoding/hex"
9+
"os"
10+
"path/filepath"
11+
"runtime"
12+
"strings"
13+
"testing"
14+
15+
"github.com/lima-vm/go-qcow2reader"
16+
"github.com/lima-vm/go-qcow2reader/image"
17+
"gotest.tools/v3/assert"
18+
19+
"github.com/lima-vm/lima/v2/pkg/iso9660util"
20+
"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
21+
"github.com/lima-vm/lima/v2/pkg/osutil"
22+
)
23+
24+
const (
25+
typeRAW = image.Type("raw")
26+
typeASIF = image.Type("asif")
27+
)
28+
29+
func writeMinimalISO(t *testing.T, path string) {
30+
t.Helper()
31+
entries := []iso9660util.Entry{
32+
{Path: "/hello.txt", Reader: strings.NewReader("hello world")},
33+
}
34+
assert.NilError(t, iso9660util.Write(path, "TESTISO", entries))
35+
}
36+
37+
func writeNonISO(t *testing.T, path string) {
38+
t.Helper()
39+
size := 64 * 1024
40+
buf := make([]byte, size)
41+
copy(buf[0x8001:], "XXXXX")
42+
assert.NilError(t, os.WriteFile(path, buf, 0o644))
43+
}
44+
45+
func sha256File(t *testing.T, path string) string {
46+
t.Helper()
47+
b, err := os.ReadFile(path)
48+
assert.NilError(t, err)
49+
sum := sha256.Sum256(b)
50+
return hex.EncodeToString(sum[:])
51+
}
52+
53+
func detectImageType(t *testing.T, path string) image.Type {
54+
t.Helper()
55+
f, err := os.Open(path)
56+
assert.NilError(t, err)
57+
defer f.Close()
58+
img, err := qcow2reader.Open(f)
59+
assert.NilError(t, err)
60+
return img.Type()
61+
}
62+
63+
func checkDisk(t *testing.T, diff string, expectedType image.Type) {
64+
t.Helper()
65+
fi, err := os.Stat(diff)
66+
assert.NilError(t, err)
67+
assert.Assert(t, fi.Size() > 0)
68+
assert.Equal(t, detectImageType(t, diff), expectedType)
69+
}
70+
71+
func isMacOS26OrHigher() bool {
72+
if runtime.GOOS != "darwin" {
73+
return false
74+
}
75+
version, err := osutil.ProductVersion()
76+
if err != nil {
77+
return false
78+
}
79+
return version.Major >= 26
80+
}
81+
82+
func TestEnsureDisk_WithISOBaseImage(t *testing.T) {
83+
instDir := t.TempDir()
84+
base := filepath.Join(instDir, filenames.BaseDisk)
85+
diff := filepath.Join(instDir, filenames.DiffDisk)
86+
87+
writeMinimalISO(t, base)
88+
isISO, err := iso9660util.IsISO9660(base)
89+
assert.NilError(t, err)
90+
assert.Assert(t, isISO)
91+
baseHashBefore := sha256File(t, base)
92+
93+
formats := []image.Type{typeRAW}
94+
if isMacOS26OrHigher() {
95+
formats = append(formats, typeASIF)
96+
}
97+
98+
for _, format := range formats {
99+
assert.NilError(t, EnsureDisk(t.Context(), instDir, "2MiB", format))
100+
isISO, err = iso9660util.IsISO9660(base)
101+
assert.NilError(t, err)
102+
assert.Assert(t, isISO)
103+
assert.Equal(t, baseHashBefore, sha256File(t, base))
104+
checkDisk(t, diff, format)
105+
assert.NilError(t, os.Remove(diff))
106+
}
107+
}
108+
109+
func TestEnsureDisk_WithNonISOBaseImage(t *testing.T) {
110+
instDir := t.TempDir()
111+
base := filepath.Join(instDir, filenames.BaseDisk)
112+
diff := filepath.Join(instDir, filenames.DiffDisk)
113+
114+
writeNonISO(t, base)
115+
isISO, err := iso9660util.IsISO9660(base)
116+
assert.NilError(t, err)
117+
assert.Assert(t, !isISO)
118+
119+
formats := []image.Type{typeRAW}
120+
if isMacOS26OrHigher() {
121+
formats = append(formats, typeASIF)
122+
}
123+
124+
for _, format := range formats {
125+
assert.NilError(t, EnsureDisk(t.Context(), instDir, "2MiB", format))
126+
checkDisk(t, diff, format)
127+
assert.NilError(t, os.Remove(diff))
128+
}
129+
}
130+
131+
func TestEnsureDisk_ExistingDiffDisk(t *testing.T) {
132+
instDir := t.TempDir()
133+
base := filepath.Join(instDir, filenames.BaseDisk)
134+
diff := filepath.Join(instDir, filenames.DiffDisk)
135+
136+
writeNonISO(t, base)
137+
138+
formats := []image.Type{typeRAW}
139+
if isMacOS26OrHigher() {
140+
formats = append(formats, typeASIF)
141+
}
142+
143+
for _, format := range formats {
144+
assert.NilError(t, os.WriteFile(diff, []byte("preexisting"), 0o644))
145+
origHash := sha256File(t, diff)
146+
assert.NilError(t, EnsureDisk(t.Context(), instDir, "2MiB", format))
147+
assert.Equal(t, sha256File(t, diff), origHash)
148+
assert.NilError(t, os.Remove(diff))
149+
}
150+
}

pkg/imgutil/nativeimgutil/nativeimgutil.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ func convertTo(destType image.Type, source, dest string, size *int64, allowSourc
6262
logrus.Infof("Converting %q (%s) to a %s disk %q", source, srcImg.Type(), destType, dest)
6363
switch t := srcImg.Type(); t {
6464
case raw.Type:
65-
if err = srcF.Close(); err != nil {
66-
return err
67-
}
6865
if destType == raw.Type {
66+
if err = srcF.Close(); err != nil {
67+
return err
68+
}
6969
return convertRawToRaw(source, dest, size)
7070
}
7171
case qcow2.Type:

0 commit comments

Comments
 (0)