Skip to content

Commit ae7f485

Browse files
committed
supermin: wait for virtiofsd sockets to appear
Add code to wait for virtiofsd sockets to appear.
1 parent d3c2306 commit ae7f485

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

pkg/progress/export_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type (
1212

1313
var (
1414
NewSyncedWriter = newSyncedWriter
15+
WaitForFiles = waitForFiles
1516
)
1617

1718
func MockOsStdout(w io.Writer) (restore func()) {

pkg/progress/supermin.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func superminPrepare(prepareDir, export string) error {
124124
"osbuild", "osbuild-depsolve-dnf", "osbuild-lvm2", "osbuild-luks2", "osbuild-ostree",
125125
// lvm
126126
"lvm2",
127-
// target"
127+
// target dir
128128
"-o", prepareDir,
129129
)
130130
if err != nil {
@@ -151,7 +151,26 @@ func superminBuild(prepareDir, buildDir string) error {
151151
return nil
152152
}
153153

154-
func setupVirtiofsd(tmpDir, outputDir, storeDir string) (func(), error) {
154+
func waitForFiles(maxWait time.Duration, paths ...string) error {
155+
start := time.Now()
156+
for {
157+
var missingPaths []string
158+
for _, path := range paths {
159+
if _, err := os.Stat(path); err != nil {
160+
missingPaths = append(missingPaths, path)
161+
}
162+
}
163+
if len(missingPaths) == 0 {
164+
return nil
165+
}
166+
if time.Since(start) >= maxWait {
167+
return fmt.Errorf("files missing after %v: %v", maxWait, missingPaths)
168+
}
169+
time.Sleep(100 * time.Millisecond)
170+
}
171+
}
172+
173+
func setupVirtiofsd(tmpDir, outputDir, storeDir string) (cleanup func(), err error) {
155174
var cmds []*exec.Cmd
156175
var cleanupFunc = func() {
157176
for _, cmd := range cmds {
@@ -160,14 +179,22 @@ func setupVirtiofsd(tmpDir, outputDir, storeDir string) (func(), error) {
160179
}
161180
}
162181
}
182+
defer func() {
183+
if err != nil {
184+
cleanupFunc()
185+
}
186+
}()
163187

188+
var socketPaths []string
164189
for _, mnt := range []struct {
165190
path, tag string
166191
}{
167192
{outputDir, "output"},
168193
{storeDir, "store"},
169194
} {
170195
socketPath := filepath.Join(tmpDir, fmt.Sprintf("vfsd_%s.sock", mnt.tag))
196+
socketPaths = append(socketPaths, socketPath)
197+
171198
var args []string
172199
// run virtiofsd in user namespace if non-root to make
173200
// chown() and friends inside the VM work
@@ -193,13 +220,13 @@ func setupVirtiofsd(tmpDir, outputDir, storeDir string) (func(), error) {
193220
cmd.Stdout = os.Stdout
194221
cmd.Stderr = os.Stderr
195222
if err := cmd.Start(); err != nil {
196-
cleanupFunc()
197223
return nil, err
198224
}
199225
cmds = append(cmds, cmd)
200226
}
201-
// XXX: wait for socket to appear
202-
time.Sleep(2 * time.Second)
227+
if err := waitForFiles(10*time.Second, socketPaths...); err != nil {
228+
return nil, fmt.Errorf("expected socket did not appear: %w", err)
229+
}
203230

204231
return cleanupFunc, nil
205232
}

pkg/progress/supermin_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package progress_test
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
"time"
9+
10+
"github.com/stretchr/testify/assert"
11+
12+
"github.com/osbuild/image-builder-cli/pkg/progress"
13+
)
14+
15+
func TestWaitForFilesFile(t *testing.T) {
16+
tmpdir := t.TempDir()
17+
18+
// trivial case, no file appears, we error
19+
start := time.Now()
20+
canary1 := filepath.Join(tmpdir, "f1.txt")
21+
err := progress.WaitForFiles(200*time.Millisecond, canary1)
22+
assert.EqualError(t, err, fmt.Sprintf("files missing after 200ms: [%s]", canary1))
23+
// ensure we waited untilthe timeout
24+
assert.True(t, time.Since(start) >= 200*time.Millisecond)
25+
26+
// trivial case, file is already there before we wait
27+
err = os.WriteFile(canary1, nil, 0644)
28+
assert.NoError(t, err)
29+
// use an absurd high time to ensure test timeouts if we would
30+
// wait a long time here
31+
err = progress.WaitForFiles(1*time.Hour, canary1)
32+
assert.NoError(t, err)
33+
34+
// new file appears after 100ms
35+
canary2 := filepath.Join(tmpdir, "f2.txt")
36+
start = time.Now()
37+
go func() {
38+
time.Sleep(100 * time.Millisecond)
39+
err := os.WriteFile(canary2, nil, 0644)
40+
assert.NoError(t, err)
41+
}()
42+
err = progress.WaitForFiles(1*time.Hour, canary1, canary2)
43+
assert.NoError(t, err)
44+
assert.True(t, time.Since(start) >= 100*time.Millisecond)
45+
// it should take 100-200msec to get the file but to avoid
46+
// races in heavy loaded CI VMs we are conservative here
47+
assert.True(t, time.Since(start) <= time.Second)
48+
}

0 commit comments

Comments
 (0)