The qemu guest agent allows to online and offline CPUs from the perspective of
the guest. This patch adds helpers that call 'guest-get-vcpus' and
'guest-set-vcpus' guest agent functions and convert the data for internal
libvirt usage.
---
src/qemu/qemu_agent.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 12 +++++
2 files changed, 149 insertions(+)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 8c8c38b..ba2d187 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1455,3 +1455,140 @@ qemuAgentFSTrim(qemuAgentPtr mon,
virJSONValueFree(reply);
return ret;
}
+
+int
+qemuAgentGetVCPUs(qemuAgentPtr mon,
+ qemuAgentCPUInfoPtr *info)
+{
+ int ret = -1;
+ int i;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr data = NULL;
+
+ if (!(cmd = qemuAgentMakeCommand("guest-get-vcpus", NULL)))
+ return -1;
+
+ if (qemuAgentCommand(mon, cmd, &reply,
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0 ||
+ qemuAgentCheckError(cmd, reply) < 0)
+ goto cleanup;
+
+ if (!(data = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest-get-vcpus reply was missing return data"));
+ goto cleanup;
+ }
+
+ if (data->type != VIR_JSON_TYPE_ARRAY) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest-get-vcpus return information was not an
array"));
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(*info, virJSONValueArraySize(data)) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ for (i = 0 ; i < virJSONValueArraySize(data) ; i++) {
+ virJSONValuePtr entry = virJSONValueArrayGet(data, i);
+ qemuAgentCPUInfoPtr in = *info + i;
+
+ if (!entry) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("array element missing in guest-get-vcpus return
"
+ "value"));
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUint(entry, "logical-id",
&in->id) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'logical-id' missing in reply of
guest-get-vcpus"));
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetBoolean(entry, "online", &in->online)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'online' missing in reply of guest-get-vcpus
"));
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetBoolean(entry, "can-offline",
+ &in->offlinable) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'can-offline' missing in reply of
guest-get-vcpus"));
+ goto cleanup;
+ }
+ }
+
+ ret = virJSONValueArraySize(data);
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ virJSONValueFree(data);
+ return ret;
+}
+
+int
+qemuAgentSetVCPUs(qemuAgentPtr mon,
+ qemuAgentCPUInfoPtr info,
+ size_t ninfo)
+{
+ int ret = -1;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr cpus = NULL;
+ virJSONValuePtr cpu = NULL;
+ size_t i;
+
+ /* create the key data array */
+ if (!(cpus = virJSONValueNewArray()))
+ goto no_memory;
+
+ for (i = 0; i < ninfo; i++) {
+ qemuAgentCPUInfoPtr in = &info[i];
+
+ /* create single cpu object */
+ if (!(cpu = virJSONValueNewObject()))
+ goto no_memory;
+
+ if (virJSONValueObjectAppendNumberInt(cpu, "logical-id", in->id)
< 0)
+ goto no_memory;
+
+ if (virJSONValueObjectAppendBoolean(cpu, "online", in->online) <
0)
+ goto no_memory;
+
+ if (virJSONValueArrayAppend(cpus, cpu) < 0)
+ goto no_memory;
+
+ cpu = NULL;
+ }
+
+ if (!(cmd = qemuAgentMakeCommand("guest-set-vcpus",
+ "a:vcpus", cpus,
+ NULL)))
+ goto cleanup;
+
+ if (qemuAgentCommand(mon, cmd, &reply,
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0 ||
+ qemuAgentCheckError(cmd, reply) < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed return value"));
+ }
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ virJSONValueFree(cpu);
+ virJSONValueFree(cpus);
+ return ret;
+
+no_memory:
+ virReportOOMError();
+ goto cleanup;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index ba04e61..79be283 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -82,4 +82,16 @@ int qemuAgentArbitraryCommand(qemuAgentPtr mon,
int timeout);
int qemuAgentFSTrim(qemuAgentPtr mon,
unsigned long long minimum);
+
+
+typedef struct _qemuAgentCPUInfo qemuAgentCPUInfo;
+typedef qemuAgentCPUInfo *qemuAgentCPUInfoPtr;
+struct _qemuAgentCPUInfo {
+ unsigned int id; /* locigal cpu ID */
+ bool online; /* true if the CPU is activated */
+ bool offlinable; /* true if the CPU can be offlined - ignored when setting*/
+};
+
+int qemuAgentGetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr *info);
+int qemuAgentSetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr cpus, size_t ncpus);
#endif /* __QEMU_AGENT_H__ */
--
1.8.1.5