qmp: support command 'query-qmp-schema'

The upper hyervisor manager application maybe need to wait some
QMP event to control boot sequence, but the event we wanted maybe
not exist in some older version, so we need query all QMP ABI and
check the event is supported or not.

related: kata-containers/runtime#1918

Signed-off-by: Ning Bo <ning.bo9@zte.com.cn>
This commit is contained in:
Ning Bo 2019-08-01 09:05:27 +08:00
parent e0505242c0
commit 79e0d5333d
2 changed files with 71 additions and 0 deletions

View File

@ -84,6 +84,9 @@ type QMPConfig struct {
// logger is used by the qmpStart function and all the go routines
// it spawns to log information.
Logger QMPLog
// specify the capacity of buffer used by receive QMP response.
MaxCapacity int
}
type qmpEventFilter struct {
@ -242,8 +245,19 @@ type MigrationStatus struct {
XbzrleCache MigrationXbzrleCache `json:"xbzrle-cache,omitempty"`
}
// SchemaInfo represents all QMP wire ABI
type SchemaInfo struct {
MetaType string `json:"meta-type"`
Name string `json:"name"`
}
func (q *QMP) readLoop(fromVMCh chan<- []byte) {
scanner := bufio.NewScanner(q.conn)
if q.cfg.MaxCapacity > 0 {
buffer := make([]byte, q.cfg.MaxCapacity)
scanner.Buffer(buffer, q.cfg.MaxCapacity)
}
for scanner.Scan() {
line := scanner.Bytes()
if q.cfg.Logger.V(1) {
@ -260,6 +274,7 @@ func (q *QMP) readLoop(fromVMCh chan<- []byte) {
fromVMCh <- sendLine
}
q.cfg.Logger.Infof("sanner return error: %v", scanner.Err())
close(fromVMCh)
}
@ -1509,3 +1524,24 @@ func (q *QMP) ExecuteMigrationIncoming(ctx context.Context, uri string) error {
}
return q.executeCommand(ctx, "migrate-incoming", args, nil)
}
// ExecQueryQmpSchema query all QMP wire ABI and returns a slice
func (q *QMP) ExecQueryQmpSchema(ctx context.Context) ([]SchemaInfo, error) {
response, err := q.executeCommandWithResponse(ctx, "query-qmp-schema", nil, nil, nil)
if err != nil {
return nil, err
}
// convert response to json
data, err := json.Marshal(response)
if err != nil {
return nil, fmt.Errorf("unable to extract memory devices information: %v", err)
}
var schemaInfo []SchemaInfo
if err = json.Unmarshal(data, &schemaInfo); err != nil {
return nil, fmt.Errorf("unable to convert json to schemaInfo: %v", err)
}
return schemaInfo, nil
}

View File

@ -1588,3 +1588,38 @@ func TestMainLoopEventBeforeGreeting(t *testing.T) {
q.Shutdown()
<-disconnectedCh
}
func TestQMPExecQueryQmpSchema(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
schemaInfo := []SchemaInfo{
{
MetaType: "command",
Name: "object-add",
},
{
MetaType: "event",
Name: "VSOCK_RUNNING",
},
}
buf.AddCommand("query-qmp-schema", nil, "return", schemaInfo)
cfg := QMPConfig{
Logger: qmpTestLogger{},
MaxCapacity: 1024,
}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
checkVersion(t, connectedCh)
info, err := q.ExecQueryQmpSchema(context.Background())
if err != nil {
t.Fatalf("Unexpected error: %v\n", err)
}
if len(schemaInfo) != 2 {
t.Fatalf("Expected schema infos length equals to 2\n")
}
if reflect.DeepEqual(info, schemaInfo) == false {
t.Fatalf("Expected %v equals to %v\n", info, schemaInfo)
}
q.Shutdown()
<-disconnectedCh
}