mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-23 05:58:04 +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
|
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 {
|
type CPUProperties struct {
|
||||||
Node int `json:"node-id"`
|
Node int `json:"node-id"`
|
||||||
Socket int `json:"socket-id"`
|
Socket int `json:"socket-id"`
|
||||||
@ -178,6 +178,28 @@ type MemoryDevices struct {
|
|||||||
Type string `json:"type"`
|
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) {
|
func (q *QMP) readLoop(fromVMCh chan<- []byte) {
|
||||||
scanner := bufio.NewScanner(q.conn)
|
scanner := bufio.NewScanner(q.conn)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@ -1033,6 +1055,54 @@ func (q *QMP) ExecQueryMemoryDevices(ctx context.Context) ([]MemoryDevices, erro
|
|||||||
return memoryDevices, nil
|
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
|
// ExecHotplugMemory adds size of MiB memory to the guest
|
||||||
func (q *QMP) ExecHotplugMemory(ctx context.Context, qomtype, id, mempath string, size int) error {
|
func (q *QMP) ExecHotplugMemory(ctx context.Context, qomtype, id, mempath string, size int) error {
|
||||||
args := map[string]interface{}{
|
args := map[string]interface{}{
|
||||||
|
@ -1096,6 +1096,80 @@ func TestQMPExecuteQueryMemoryDevices(t *testing.T) {
|
|||||||
<-disconnectedCh
|
<-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
|
// Checks that migrate capabilities can be set
|
||||||
func TestExecSetMigrationCaps(t *testing.T) {
|
func TestExecSetMigrationCaps(t *testing.T) {
|
||||||
connectedCh := make(chan *QMPVersion)
|
connectedCh := make(chan *QMPVersion)
|
||||||
|
Loading…
Reference in New Issue
Block a user