qemu: Add function to list hotpluggable CPUs

ExecuteQueryHotpluggableCPUs returns the list of hotpluggable CPUs

Signed-off-by: Julio Montes <julio.montes@intel.com>
This commit is contained in:
Julio Montes 2017-12-07 13:27:52 -06:00
parent 8c428ed722
commit b8ddd24400
2 changed files with 75 additions and 5 deletions

38
qmp.go
View File

@ -140,6 +140,22 @@ type QMPVersion struct {
Capabilities []string
}
// CPUProperties contains the properties to be used for hotplugging a CPU instance
type CPUProperties struct {
Node int `json:"node-id"`
Socket int `json:"socket-id"`
Core int `json:"core-id"`
Thread int `json:"thread-id"`
}
// HotpluggableCPU represents a hotpluggable CPU
type HotpluggableCPU struct {
Type string `json:"type"`
VcpusCount int `json:"vcpus-count"`
Properties CPUProperties `json:"props"`
QOMPath string `json:"qom-path"`
}
func (q *QMP) readLoop(fromVMCh chan<- []byte) {
scanner := bufio.NewScanner(q.conn)
for scanner.Scan() {
@ -751,3 +767,25 @@ func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID,
}
return q.executeCommand(ctx, "device_add", args, nil)
}
// ExecuteQueryHotpluggableCPUs returns a slice with the list of hotpluggable CPUs
func (q *QMP) ExecuteQueryHotpluggableCPUs(ctx context.Context) ([]HotpluggableCPU, error) {
response, err := q.executeCommandWithResponse(ctx, "query-hotpluggable-cpus", 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 CPU information: %v", err)
}
var cpus []HotpluggableCPU
// convert json to []HotpluggableCPU
if err = json.Unmarshal(data, &cpus); err != nil {
return nil, fmt.Errorf("Unable to convert json to hotpluggable CPU: %v", err)
}
return cpus, nil
}

View File

@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"log"
"reflect"
"sync"
"testing"
"time"
@ -75,7 +76,7 @@ type qmpTestEvent struct {
type qmpTestResult struct {
result string
data map[string]interface{}
data interface{}
}
type qmpTestCommandBuffer struct {
@ -132,11 +133,8 @@ func (b *qmpTestCommandBuffer) startEventLoop(wg *sync.WaitGroup) {
}
func (b *qmpTestCommandBuffer) AddCommand(name string, args map[string]interface{},
result string, data map[string]interface{}) {
result string, data interface{}) {
b.cmds = append(b.cmds, qmpTestCommand{name, args})
if data == nil {
data = make(map[string]interface{})
}
b.results = append(b.results, qmpTestResult{result, data})
}
@ -832,3 +830,37 @@ func TestQMPCPUDeviceAdd(t *testing.T) {
q.Shutdown()
<-disconnectedCh
}
// Checks that hotpluggable CPUs are listed correctly
func TestQMPExecuteQueryHotpluggableCPUs(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
hotCPU := HotpluggableCPU{
Type: "host-x86",
VcpusCount: 5,
Properties: CPUProperties{
Node: 1,
Socket: 3,
Core: 2,
Thread: 4,
},
QOMPath: "/abc/123/rgb",
}
buf.AddCommand("query-hotpluggable-cpus", nil, "return", []interface{}{hotCPU})
cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
checkVersion(t, connectedCh)
hotCPUs, err := q.ExecuteQueryHotpluggableCPUs(context.Background())
if err != nil {
t.Fatalf("Unexpected error: %v\n", err)
}
if len(hotCPUs) != 1 {
t.Fatalf("Expected hot CPUs length equals to 1\n")
}
if reflect.DeepEqual(hotCPUs[0], hotCPU) == false {
t.Fatalf("Expected %v equals to %v\n", hotCPUs[0], hotCPU)
}
q.Shutdown()
<-disconnectedCh
}