mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-28 03:42:09 +00:00
qmp: add "query-cpus" support
Add "query-cpus" and "query-cpus-fast" to query CPU information from qemu Signed-off-by: Wei Zhang <zhangwei555@huawei.com>
This commit is contained in:
parent
9905ae92c5
commit
1130aab85e
72
qemu/qmp.go
72
qemu/qmp.go
@ -144,7 +144,7 @@ type QMPVersion struct {
|
||||
Capabilities []string
|
||||
}
|
||||
|
||||
// CPUProperties contains the properties to be used for hotplugging a CPU instance
|
||||
// CPUProperties contains the properties of a CPU instance
|
||||
type CPUProperties struct {
|
||||
Node int `json:"node-id"`
|
||||
Socket int `json:"socket-id"`
|
||||
@ -178,6 +178,28 @@ type MemoryDevices struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// CPUInfo represents information about each virtual CPU
|
||||
type CPUInfo struct {
|
||||
CPU int `json:"CPU"`
|
||||
Current bool `json:"current"`
|
||||
Halted bool `json:"halted"`
|
||||
QomPath string `json:"qom_path"`
|
||||
Arch string `json:"arch"`
|
||||
Pc int `json:"pc"`
|
||||
ThreadID int `json:"thread_id"`
|
||||
Props CPUProperties `json:"props"`
|
||||
}
|
||||
|
||||
// CPUInfoFast represents information about each virtual CPU
|
||||
type CPUInfoFast struct {
|
||||
CPUIndex int `json:"cpu-index"`
|
||||
QomPath string `json:"qom-path"`
|
||||
Arch string `json:"arch"`
|
||||
ThreadID int `json:"thread-id"`
|
||||
Target string `json:"target"`
|
||||
Props CPUProperties `json:"props"`
|
||||
}
|
||||
|
||||
func (q *QMP) readLoop(fromVMCh chan<- []byte) {
|
||||
scanner := bufio.NewScanner(q.conn)
|
||||
for scanner.Scan() {
|
||||
@ -1033,6 +1055,54 @@ func (q *QMP) ExecQueryMemoryDevices(ctx context.Context) ([]MemoryDevices, erro
|
||||
return memoryDevices, nil
|
||||
}
|
||||
|
||||
// ExecQueryCpus returns a slice with the list of `CpuInfo`
|
||||
// Since qemu 2.12, we have `query-cpus-fast` as a better choice in production
|
||||
// we can still choose `ExecQueryCpus` for compatibility though not recommended.
|
||||
func (q *QMP) ExecQueryCpus(ctx context.Context) ([]CPUInfo, error) {
|
||||
response, err := q.executeCommandWithResponse(ctx, "query-cpus", 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 cpuInfo []CPUInfo
|
||||
// convert json to []CPUInfo
|
||||
if err = json.Unmarshal(data, &cpuInfo); err != nil {
|
||||
return nil, fmt.Errorf("unable to convert json to CPUInfo: %v", err)
|
||||
}
|
||||
|
||||
return cpuInfo, nil
|
||||
}
|
||||
|
||||
// ExecQueryCpusFast returns a slice with the list of `CpuInfoFast`
|
||||
// This is introduced since 2.12, it does not incur a performance penalty and
|
||||
// should be used in production instead of query-cpus.
|
||||
func (q *QMP) ExecQueryCpusFast(ctx context.Context) ([]CPUInfoFast, error) {
|
||||
response, err := q.executeCommandWithResponse(ctx, "query-cpus-fast", 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 cpuInfoFast []CPUInfoFast
|
||||
// convert json to []CPUInfoFast
|
||||
if err = json.Unmarshal(data, &cpuInfoFast); err != nil {
|
||||
return nil, fmt.Errorf("unable to convert json to CPUInfoFast: %v", err)
|
||||
}
|
||||
|
||||
return cpuInfoFast, 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{}{
|
||||
|
@ -1096,6 +1096,80 @@ func TestQMPExecuteQueryMemoryDevices(t *testing.T) {
|
||||
<-disconnectedCh
|
||||
}
|
||||
|
||||
// Checks that cpus are listed correctly
|
||||
func TestQMPExecuteQueryCpus(t *testing.T) {
|
||||
connectedCh := make(chan *QMPVersion)
|
||||
disconnectedCh := make(chan struct{})
|
||||
buf := newQMPTestCommandBuffer(t)
|
||||
cpuInfo := CPUInfo{
|
||||
CPU: 1,
|
||||
Current: false,
|
||||
Halted: false,
|
||||
Arch: "x86_64",
|
||||
QomPath: "/tmp/testQom",
|
||||
Pc: 123456,
|
||||
ThreadID: 123457,
|
||||
Props: CPUProperties{
|
||||
Node: 0,
|
||||
Socket: 1,
|
||||
Core: 1,
|
||||
Thread: 1966,
|
||||
},
|
||||
}
|
||||
buf.AddCommand("query-cpus", nil, "return", []interface{}{cpuInfo})
|
||||
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||
checkVersion(t, connectedCh)
|
||||
cpus, err := q.ExecQueryCpus(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v\n", err)
|
||||
}
|
||||
if len(cpus) != 1 {
|
||||
t.Fatalf("Expected memory devices length equals to 1\n")
|
||||
}
|
||||
if reflect.DeepEqual(cpus[0], cpuInfo) == false {
|
||||
t.Fatalf("Expected %v equals to %v\n", cpus[0], cpuInfo)
|
||||
}
|
||||
q.Shutdown()
|
||||
<-disconnectedCh
|
||||
}
|
||||
|
||||
// Checks that cpus are listed correctly
|
||||
func TestQMPExecuteQueryCpusFast(t *testing.T) {
|
||||
connectedCh := make(chan *QMPVersion)
|
||||
disconnectedCh := make(chan struct{})
|
||||
buf := newQMPTestCommandBuffer(t)
|
||||
cpuInfoFast := CPUInfoFast{
|
||||
CPUIndex: 1,
|
||||
Arch: "x86",
|
||||
Target: "x86_64",
|
||||
QomPath: "/tmp/testQom",
|
||||
ThreadID: 123457,
|
||||
Props: CPUProperties{
|
||||
Node: 0,
|
||||
Socket: 1,
|
||||
Core: 1,
|
||||
Thread: 1966,
|
||||
},
|
||||
}
|
||||
buf.AddCommand("query-cpus-fast", nil, "return", []interface{}{cpuInfoFast})
|
||||
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||
checkVersion(t, connectedCh)
|
||||
cpus, err := q.ExecQueryCpusFast(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v\n", err)
|
||||
}
|
||||
if len(cpus) != 1 {
|
||||
t.Fatalf("Expected memory devices length equals to 1\n")
|
||||
}
|
||||
if reflect.DeepEqual(cpus[0], cpuInfoFast) == false {
|
||||
t.Fatalf("Expected %v equals to %v\n", cpus[0], cpuInfoFast)
|
||||
}
|
||||
q.Shutdown()
|
||||
<-disconnectedCh
|
||||
}
|
||||
|
||||
// Checks that migrate capabilities can be set
|
||||
func TestExecSetMigrationCaps(t *testing.T) {
|
||||
connectedCh := make(chan *QMPVersion)
|
||||
|
Loading…
Reference in New Issue
Block a user