Wait for real guest vsock health before opencode
Make vm create wait for the guest-side vsock /healthz endpoint instead of only waiting for the host socket path, so the wait_vsock_agent stage reflects actual guest readiness. Start banger-vsock-agent earlier in the Alpine OpenRC graph and report later /ports failures as guest-service waits rather than vsock-agent waits, which makes the progress output match what the guest is really doing. Validate with go test ./..., a rebuilt managed alpine image, and a fresh vm create --image alpine --name alp --nat that now progresses through wait_vsock_agent -> wait_guest_ready -> wait_opencode -> ready.
This commit is contained in:
parent
a166068fab
commit
092d848620
5 changed files with 157 additions and 4 deletions
|
|
@ -415,6 +415,86 @@ func TestPingVMAliasReturnsAliveForHealthyVM(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestWaitForGuestVSockAgentRetriesUntilHealthy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
socketPath := filepath.Join(t.TempDir(), "fc.vsock")
|
||||
listener, err := net.Listen("unix", socketPath)
|
||||
if err != nil {
|
||||
skipIfSocketRestricted(t, err)
|
||||
t.Fatalf("listen vsock: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_ = listener.Close()
|
||||
_ = os.Remove(socketPath)
|
||||
})
|
||||
|
||||
serverDone := make(chan error, 1)
|
||||
go func() {
|
||||
for attempt := 0; attempt < 2; attempt++ {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
serverDone <- err
|
||||
return
|
||||
}
|
||||
|
||||
buf := make([]byte, 512)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
_ = conn.Close()
|
||||
serverDone <- err
|
||||
return
|
||||
}
|
||||
if got := string(buf[:n]); got != "CONNECT 42070\n" {
|
||||
_ = conn.Close()
|
||||
serverDone <- fmt.Errorf("unexpected connect message %q", got)
|
||||
return
|
||||
}
|
||||
if _, err := conn.Write([]byte("OK 1\n")); err != nil {
|
||||
_ = conn.Close()
|
||||
serverDone <- err
|
||||
return
|
||||
}
|
||||
|
||||
if attempt == 0 {
|
||||
_ = conn.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
reqBuf := make([]byte, 0, 512)
|
||||
for {
|
||||
n, err = conn.Read(buf)
|
||||
if err != nil {
|
||||
_ = conn.Close()
|
||||
serverDone <- err
|
||||
return
|
||||
}
|
||||
reqBuf = append(reqBuf, buf[:n]...)
|
||||
if strings.Contains(string(reqBuf), "\r\n\r\n") {
|
||||
break
|
||||
}
|
||||
}
|
||||
if got := string(reqBuf); !strings.Contains(got, "GET /healthz HTTP/1.1\r\n") {
|
||||
_ = conn.Close()
|
||||
serverDone <- fmt.Errorf("unexpected health payload %q", got)
|
||||
return
|
||||
}
|
||||
_, err = conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 15\r\n\r\n{\"status\":\"ok\"}"))
|
||||
_ = conn.Close()
|
||||
serverDone <- err
|
||||
return
|
||||
}
|
||||
serverDone <- errors.New("health probe did not retry")
|
||||
}()
|
||||
|
||||
if err := waitForGuestVSockAgent(context.Background(), nil, socketPath, time.Second); err != nil {
|
||||
t.Fatalf("waitForGuestVSockAgent: %v", err)
|
||||
}
|
||||
if err := <-serverDone; err != nil {
|
||||
t.Fatalf("server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthVMReturnsFalseForStoppedVM(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue