mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-21 10:51:05 +00:00
Merge pull request #69 from BetaXOi/output-qmp-err
qmp: Output error detail when execute QMP command failed
This commit is contained in:
commit
908b6aab14
29
qemu/qmp.go
29
qemu/qmp.go
@ -313,7 +313,7 @@ func (q *QMP) finaliseCommandWithResponse(cmdEl *list.Element, cmdQueue *list.Li
|
|||||||
if succeeded {
|
if succeeded {
|
||||||
cmd.res <- qmpResult{response: response}
|
cmd.res <- qmpResult{response: response}
|
||||||
} else {
|
} else {
|
||||||
cmd.res <- qmpResult{err: fmt.Errorf("QMP command failed")}
|
cmd.res <- qmpResult{err: fmt.Errorf("QMP command failed: %v", response)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cmdQueue.Len() > 0 {
|
if cmdQueue.Len() > 0 {
|
||||||
@ -325,6 +325,23 @@ func (q *QMP) finaliseCommand(cmdEl *list.Element, cmdQueue *list.List, succeede
|
|||||||
q.finaliseCommandWithResponse(cmdEl, cmdQueue, succeeded, nil)
|
q.finaliseCommandWithResponse(cmdEl, cmdQueue, succeeded, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *QMP) errorDesc(errorData interface{}) (string, error) {
|
||||||
|
// convert error to json
|
||||||
|
data, err := json.Marshal(errorData)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Unable to extract error information: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// see: https://github.com/qemu/qemu/blob/stable-2.12/qapi/qmp-dispatch.c#L125
|
||||||
|
var qmpErr map[string]string
|
||||||
|
// convert json to qmpError
|
||||||
|
if err = json.Unmarshal(data, &qmpErr); err != nil {
|
||||||
|
return "", fmt.Errorf("Unable to convert json to qmpError: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return qmpErr["desc"], nil
|
||||||
|
}
|
||||||
|
|
||||||
func (q *QMP) processQMPInput(line []byte, cmdQueue *list.List) {
|
func (q *QMP) processQMPInput(line []byte, cmdQueue *list.List) {
|
||||||
var vmData map[string]interface{}
|
var vmData map[string]interface{}
|
||||||
err := json.Unmarshal(line, &vmData)
|
err := json.Unmarshal(line, &vmData)
|
||||||
@ -339,7 +356,7 @@ func (q *QMP) processQMPInput(line []byte, cmdQueue *list.List) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response, succeeded := vmData["return"]
|
response, succeeded := vmData["return"]
|
||||||
_, failed := vmData["error"]
|
errData, failed := vmData["error"]
|
||||||
|
|
||||||
if !succeeded && !failed {
|
if !succeeded && !failed {
|
||||||
return
|
return
|
||||||
@ -353,6 +370,14 @@ func (q *QMP) processQMPInput(line []byte, cmdQueue *list.List) {
|
|||||||
}
|
}
|
||||||
cmd := cmdEl.Value.(*qmpCommand)
|
cmd := cmdEl.Value.(*qmpCommand)
|
||||||
if failed || cmd.filter == nil {
|
if failed || cmd.filter == nil {
|
||||||
|
if errData != nil {
|
||||||
|
desc, err := q.errorDesc(errData)
|
||||||
|
if err != nil {
|
||||||
|
q.cfg.Logger.Infof("Get error description failed: %v", err)
|
||||||
|
} else {
|
||||||
|
response = desc
|
||||||
|
}
|
||||||
|
}
|
||||||
q.finaliseCommandWithResponse(cmdEl, cmdQueue, succeeded, response)
|
q.finaliseCommandWithResponse(cmdEl, cmdQueue, succeeded, response)
|
||||||
} else {
|
} else {
|
||||||
cmd.resultReceived = true
|
cmd.resultReceived = true
|
||||||
|
@ -1403,3 +1403,86 @@ func TestExecuteBalloon(t *testing.T) {
|
|||||||
q.Shutdown()
|
q.Shutdown()
|
||||||
<-disconnectedCh
|
<-disconnectedCh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestErrorDesc(t *testing.T) {
|
||||||
|
errDesc := "Somthing err messages"
|
||||||
|
errData := map[string]string{
|
||||||
|
"class": "GenericError",
|
||||||
|
"desc": errDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCh := make(chan *QMPVersion)
|
||||||
|
disconnectedCh := make(chan struct{})
|
||||||
|
buf := newQMPTestCommandBuffer(t)
|
||||||
|
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||||
|
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||||
|
checkVersion(t, connectedCh)
|
||||||
|
|
||||||
|
desc, err := q.errorDesc(errData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error '%v'", err)
|
||||||
|
}
|
||||||
|
if desc != errDesc {
|
||||||
|
t.Fatalf("expected '%v'\n got '%v'", errDesc, desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
q.Shutdown()
|
||||||
|
<-disconnectedCh
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExecCommandFailed(t *testing.T) {
|
||||||
|
errDesc := "unable to map backing store for guest RAM: Cannot allocate memory"
|
||||||
|
errData := map[string]string{
|
||||||
|
"class": "GenericError",
|
||||||
|
"desc": errDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCh := make(chan *QMPVersion)
|
||||||
|
disconnectedCh := make(chan struct{})
|
||||||
|
buf := newQMPTestCommandBuffer(t)
|
||||||
|
buf.AddCommand("object-add", nil, "error", errData)
|
||||||
|
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||||
|
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||||
|
checkVersion(t, connectedCh)
|
||||||
|
|
||||||
|
_, err := q.executeCommandWithResponse(context.Background(), "object-add", nil, nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error but got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedString := "QMP command failed: " + errDesc
|
||||||
|
if err.Error() != expectedString {
|
||||||
|
t.Fatalf("expected '%v' but got '%v'", expectedString, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
q.Shutdown()
|
||||||
|
<-disconnectedCh
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExecCommandFailedWithInnerError(t *testing.T) {
|
||||||
|
errData := map[string]string{
|
||||||
|
"class": "GenericError",
|
||||||
|
"descFieldInvalid": "Invalid",
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCh := make(chan *QMPVersion)
|
||||||
|
disconnectedCh := make(chan struct{})
|
||||||
|
buf := newQMPTestCommandBuffer(t)
|
||||||
|
buf.AddCommand("object-add", nil, "error", errData)
|
||||||
|
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||||
|
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||||
|
checkVersion(t, connectedCh)
|
||||||
|
|
||||||
|
_, err := q.executeCommandWithResponse(context.Background(), "object-add", nil, nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error but got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedString := "QMP command failed: "
|
||||||
|
if err.Error() != expectedString {
|
||||||
|
t.Fatalf("expected '%v' but got '%v'", expectedString, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
q.Shutdown()
|
||||||
|
<-disconnectedCh
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user