qmp: add ExecuteQueryMigration

It sends query-migrate qmp command to check migration status.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
Peng Tao 2018-09-18 16:14:32 +08:00
parent c2d92fe208
commit 56f645eac6
2 changed files with 110 additions and 0 deletions

View File

@ -200,6 +200,46 @@ type CPUInfoFast struct {
Props CPUProperties `json:"props"`
}
// MigrationRAM represents migration ram status
type MigrationRAM struct {
Total int64 `json:"total"`
Remaining int64 `json:"remaining"`
Transferred int64 `json:"transferred"`
TotalTime int64 `json:"total-time"`
SetupTime int64 `json:"setup-time"`
ExpectedDowntime int64 `json:"expected-downtime"`
Duplicate int64 `json:"duplicate"`
Normal int64 `json:"normal"`
NormalBytes int64 `json:"normal-bytes"`
DirtySyncCount int64 `json:"dirty-sync-count"`
}
// MigrationDisk represents migration disk status
type MigrationDisk struct {
Total int64 `json:"total"`
Remaining int64 `json:"remaining"`
Transferred int64 `json:"transferred"`
}
// MigrationXbzrleCache represents migration XbzrleCache status
type MigrationXbzrleCache struct {
CacheSize int64 `json:"cache-size"`
Bytes int64 `json:"bytes"`
Pages int64 `json:"pages"`
CacheMiss int64 `json:"cache-miss"`
CacheMissRate int64 `json:"cache-miss-rate"`
Overflow int64 `json:"overflow"`
}
// MigrationStatus represents migration status of a vm
type MigrationStatus struct {
Status string `json:"status"`
Capabilities []map[string]interface{} `json:"capabilities,omitempty"`
RAM MigrationRAM `json:"ram,omitempty"`
Disk MigrationDisk `json:"disk,omitempty"`
XbzrleCache MigrationXbzrleCache `json:"xbzrle-cache,omitempty"`
}
func (q *QMP) readLoop(fromVMCh chan<- []byte) {
scanner := bufio.NewScanner(q.conn)
for scanner.Scan() {
@ -1206,3 +1246,23 @@ func (q *QMP) ExecuteVirtSerialPortAdd(ctx context.Context, id, name, chardev st
return q.executeCommand(ctx, "device_add", args, nil)
}
// ExecuteQueryMigration queries migration progress.
func (q *QMP) ExecuteQueryMigration(ctx context.Context) (MigrationStatus, error) {
response, err := q.executeCommandWithResponse(ctx, "query-migrate", nil, nil, nil)
if err != nil {
return MigrationStatus{}, err
}
data, err := json.Marshal(response)
if err != nil {
return MigrationStatus{}, fmt.Errorf("Unable to extract migrate status information: %v", err)
}
var status MigrationStatus
if err = json.Unmarshal(data, &status); err != nil {
return MigrationStatus{}, fmt.Errorf("Unable to convert migrate status information: %v", err)
}
return status, nil
}

View File

@ -1295,3 +1295,53 @@ func TestExecuteVirtSerialPortAdd(t *testing.T) {
q.Shutdown()
<-disconnectedCh
}
// Checks migration status
func TestExecuteQueryMigration(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
status := MigrationStatus{
Status: "completed",
RAM: MigrationRAM{
Total: 100,
Remaining: 101,
Transferred: 101,
TotalTime: 101,
SetupTime: 101,
ExpectedDowntime: 101,
Duplicate: 101,
Normal: 101,
NormalBytes: 101,
DirtySyncCount: 101,
},
Disk: MigrationDisk{
Total: 200,
Remaining: 200,
Transferred: 200,
},
XbzrleCache: MigrationXbzrleCache{
CacheSize: 300,
Bytes: 300,
Pages: 300,
CacheMiss: 300,
CacheMissRate: 300,
Overflow: 300,
},
}
caps := map[string]interface{}{"foo": true}
status.Capabilities = append(status.Capabilities, caps)
buf.AddCommand("query-migrate", nil, "return", interface{}(status))
cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
checkVersion(t, connectedCh)
s, err := q.ExecuteQueryMigration(context.Background())
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if !reflect.DeepEqual(s, status) {
t.Fatalf("expected %v\n got %v", status, s)
}
q.Shutdown()
<-disconnectedCh
}