mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-28 11:44:38 +00:00
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:
parent
e0505242c0
commit
79e0d5333d
36
qemu/qmp.go
36
qemu/qmp.go
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user