From b16291cfabb128994d3dd59e2f32f4a9418732e0 Mon Sep 17 00:00:00 2001 From: Clare Chen Date: Tue, 28 Aug 2018 22:18:51 -0400 Subject: [PATCH] qemu/qmp: support query-memory-devices qmp command. Implement query qemu memory devices function and testcase. Signed-off-by: Clare Chen --- qemu/qmp.go | 40 ++++++++++++++++++++++++++++++++++++++++ qemu/qmp_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/qemu/qmp.go b/qemu/qmp.go index 58b8924fda..addf4b2fa6 100644 --- a/qemu/qmp.go +++ b/qemu/qmp.go @@ -160,6 +160,24 @@ type HotpluggableCPU struct { QOMPath string `json:"qom-path"` } +// MemoryDevicesData cotains the data describes a memory device +type MemoryDevicesData struct { + Slot int `json:"slot"` + Node int `json:"node"` + Addr uint64 `json:"addr"` + Memdev string `json:"memdev"` + ID string `json:"id"` + Hotpluggable bool `json:"hotpluggable"` + Hotplugged bool `json:"hotplugged"` + Size uint64 `json:"size"` +} + +// MemoryDevices represents memory devices of vm +type MemoryDevices struct { + Data MemoryDevicesData `json:"data"` + Type string `json:"type"` +} + func (q *QMP) readLoop(fromVMCh chan<- []byte) { scanner := bufio.NewScanner(q.conn) for scanner.Scan() { @@ -989,6 +1007,28 @@ func (q *QMP) ExecSetMigrateArguments(ctx context.Context, url string) error { return q.executeCommand(ctx, "migrate", args, nil) } +// ExecQueryMemoryDevices returns a slice with the list of memory devices +func (q *QMP) ExecQueryMemoryDevices(ctx context.Context) ([]MemoryDevices, error) { + response, err := q.executeCommandWithResponse(ctx, "query-memory-devices", 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 memoryDevices []MemoryDevices + // convert json to []MemoryDevices + if err = json.Unmarshal(data, &memoryDevices); err != nil { + return nil, fmt.Errorf("unable to convert json to memory devices: %v", err) + } + + return memoryDevices, nil +} + // ExecHotplugMemory adds size of MiB memory to the guest func (q *QMP) ExecHotplugMemory(ctx context.Context, qomtype, id, mempath string, size int) error { args := map[string]interface{}{ diff --git a/qemu/qmp_test.go b/qemu/qmp_test.go index 7d0b40ec2f..07c6126fe5 100644 --- a/qemu/qmp_test.go +++ b/qemu/qmp_test.go @@ -1055,6 +1055,42 @@ func TestQMPExecuteQueryHotpluggableCPUs(t *testing.T) { <-disconnectedCh } +// Checks that memory devices are listed correctly +func TestQMPExecuteQueryMemoryDevices(t *testing.T) { + connectedCh := make(chan *QMPVersion) + disconnectedCh := make(chan struct{}) + buf := newQMPTestCommandBuffer(t) + memoryDevices := MemoryDevices{ + Type: "dimm", + Data: MemoryDevicesData{ + Slot: 1, + Node: 0, + Addr: 1234, + Memdev: "dimm1", + ID: "mem1", + Hotpluggable: true, + Hotplugged: false, + Size: 1234, + }, + } + buf.AddCommand("query-memory-devices", nil, "return", []interface{}{memoryDevices}) + cfg := QMPConfig{Logger: qmpTestLogger{}} + q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh) + checkVersion(t, connectedCh) + memDevices, err := q.ExecQueryMemoryDevices(context.Background()) + if err != nil { + t.Fatalf("Unexpected error: %v\n", err) + } + if len(memDevices) != 1 { + t.Fatalf("Expected memory devices length equals to 1\n") + } + if reflect.DeepEqual(memDevices[0], memoryDevices) == false { + t.Fatalf("Expected %v equals to %v\n", memDevices[0], memoryDevices) + } + q.Shutdown() + <-disconnectedCh +} + // Checks that migrate capabilities can be set func TestExecSetMigrationCaps(t *testing.T) { connectedCh := make(chan *QMPVersion)