Skip to content

Commit a18f9ba

Browse files
committed
pillar/qmp: do several attempts to retrieve valid QEMU status
QEMU status is very crucial to EVE and any error or unexpected status leads to QEMU process is being stopped. There is an issue in the 3rd QMP library: digitalocean/go-qemu#210 And in order to be on a safe side and avoid these kind of problems in the future repeat status qeury several times. Signed-off-by: Roman Penyaev <[email protected]>
1 parent 7c9f216 commit a18f9ba

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

pkg/pillar/hypervisor/qmp.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7+
"errors"
78
"fmt"
89
"github.com/digitalocean/go-qemu/qmp"
910
"github.com/lf-edge/eve/pkg/pillar/types"
@@ -102,7 +103,21 @@ func getQemuStatus(socket string) (types.SwState, error) {
102103
"preconfig": types.PAUSED,
103104
}
104105

105-
if raw, err := execRawCmd(socket, `{ "execute": "query-status" }`); err == nil {
106+
// We do several retries, because correct QEMU status is very crucial to EVE
107+
// and if for some reason (https://github.com/digitalocean/go-qemu/pull/210)
108+
// the status is unexpected, EVE stops QEMU and game over.
109+
var errs error
110+
state := types.UNKNOWN
111+
for attempt := 1; attempt <= 3; attempt++ {
112+
raw, err := execRawCmd(socket, `{ "execute": "query-status" }`)
113+
if err != nil {
114+
err = fmt.Errorf("[attempt %d] qmp status failed for QMP socket '%s': err: '%v'; (JSON response: '%s')",
115+
attempt, socket, err, raw)
116+
errs = errors.Join(errs, err)
117+
time.Sleep(time.Second)
118+
continue
119+
}
120+
106121
var result struct {
107122
ID string `json:"id"`
108123
Return struct {
@@ -114,18 +129,27 @@ func getQemuStatus(socket string) (types.SwState, error) {
114129
dec := json.NewDecoder(bytes.NewReader(raw))
115130
dec.DisallowUnknownFields()
116131
err = dec.Decode(&result)
117-
var matched bool
118-
var state types.SwState
119132
if err != nil {
120-
err = fmt.Errorf("%v; (JSON received: '%s')", err, raw)
121-
} else if state, matched = qmpStatusMap[result.Return.Status]; !matched {
122-
err = fmt.Errorf("unknown QMP status '%s' for QMP socket '%s'; (JSON response: '%s')",
123-
result.Return.Status, socket, raw)
133+
err = fmt.Errorf("[attempt %d] failed to parse QMP status response for QMP socket '%s': err: '%v'; (JSON response: '%s')",
134+
attempt, socket, err, raw)
135+
errs = errors.Join(errs, err)
136+
time.Sleep(time.Second)
137+
continue
124138
}
125-
return state, err
126-
} else {
127-
return types.UNKNOWN, err
139+
var matched bool
140+
if state, matched = qmpStatusMap[result.Return.Status]; !matched {
141+
err = fmt.Errorf("[attempt %d] unknown QMP status '%s' for QMP socket '%s'; (JSON response: '%s')",
142+
attempt, result.Return.Status, socket, raw)
143+
errs = errors.Join(errs, err)
144+
time.Sleep(time.Second)
145+
continue
146+
}
147+
148+
// Success
149+
break
128150
}
151+
152+
return state, errs
129153
}
130154

131155
func qmpEventHandler(listenerSocket, executorSocket string) {

0 commit comments

Comments
 (0)