The new QMP API query-current-machine reports VM capabilities that can vary depending on the VM configuration, in contrast to most QEMU caps that can be set once during libvirtd init as exposed in qemu_capabilities.c. As such, to properly set the runtime capabilities exposed by this API, we must query them at VM launch time. To do that, a new function called qemuProcessSetCurrentMachineCaps is called in qemuProcessLaunch. A new struct called qemuMonitorCurrentMachineInfo was created to host the output of the API (which contains only the wakeup-suspend-support flag for now, but can be expanded in the future). This struct is populated by qemuMonitorGetCurrentMachineInfo, which does the heavy work - executes query-current-machine, parses the result and populates the qemuMonitorCurrentMachineInfo struct. qemuProcessSetCurrentMachineCaps can then read the structure and set the capabilities accordingly. Signed-off-by: Daniel Henrique Barboza <danielhb413@xxxxxxxxx> --- src/qemu/qemu_monitor.c | 17 ++++++++++++ src/qemu/qemu_monitor.h | 11 ++++++++ src/qemu/qemu_monitor_json.c | 53 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 ++++ src/qemu/qemu_process.c | 36 ++++++++++++++++++++++++ 5 files changed, 122 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index babcbde878..d4222f0bcc 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4472,3 +4472,20 @@ qemuMonitorGetPRManagerInfo(qemuMonitorPtr mon, virHashFree(info); return ret; } + +int +qemuMonitorGetCurrentMachineInfo(qemuMonitorPtr mon, + qemuMonitorCurrentMachineInfoPtr info) +{ + int ret = -1; + + QEMU_CHECK_MONITOR(mon); + + if (qemuMonitorJSONGetCurrentMachineInfo(mon, info) < 0) + goto cleanup; + + ret = 0; + + cleanup: + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 086195ff98..fcd5a022b5 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1220,4 +1220,15 @@ struct _qemuMonitorPRManagerInfo { int qemuMonitorGetPRManagerInfo(qemuMonitorPtr mon, virHashTablePtr *retinfo); +struct _qemuMonitorCurrentMachineInfo { + bool wakeupSuspendSupport; +}; + +typedef struct _qemuMonitorCurrentMachineInfo qemuMonitorCurrentMachineInfo; +typedef qemuMonitorCurrentMachineInfo *qemuMonitorCurrentMachineInfoPtr; + +int +qemuMonitorGetCurrentMachineInfo(qemuMonitorPtr mon, + qemuMonitorCurrentMachineInfoPtr info); + #endif /* LIBVIRT_QEMU_MONITOR_H */ diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8e6c3ccd63..c6a2a59e6b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8449,3 +8449,56 @@ qemuMonitorJSONGetPRManagerInfo(qemuMonitorPtr mon, return ret; } + +static int +qemuMonitorJSONExtractCurrentMachineInfo(virJSONValuePtr reply, + qemuMonitorCurrentMachineInfoPtr info) +{ + virJSONValuePtr data; + int ret = -1; + + data = virJSONValueObjectGetObject(reply, "return"); + if (!data) + goto malformed; + + if (virJSONValueObjectGetBoolean(data, "wakeup-suspend-support", + &info->wakeupSuspendSupport) < 0) { + goto malformed; + } + + ret = 0; + + out: + return ret; + + malformed: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed qemu-current-machine reply")); + goto out; +} + +int +qemuMonitorJSONGetCurrentMachineInfo(qemuMonitorPtr mon, + qemuMonitorCurrentMachineInfoPtr info) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-current-machine", + NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + goto cleanup; + + if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0) + goto cleanup; + + ret = qemuMonitorJSONExtractCurrentMachineInfo(reply, info); + + cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index c10513da15..746b7072ca 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -576,4 +576,9 @@ int qemuMonitorJSONGetPRManagerInfo(qemuMonitorPtr mon, virHashTablePtr info) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int +qemuMonitorJSONGetCurrentMachineInfo(qemuMonitorPtr mon, + qemuMonitorCurrentMachineInfoPtr info) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif /* LIBVIRT_QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 47d8ca2ff1..b60c1ecfbe 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6461,6 +6461,39 @@ qemuProcessSetupDiskThrottlingBlockdev(virQEMUDriverPtr driver, return ret; } +static int +qemuProcessSetCurrentMachineCaps(virQEMUDriverPtr driver, + virDomainObjPtr vm, + qemuDomainAsyncJob asyncJob) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + qemuMonitorCurrentMachineInfoPtr info; + int ret = -1; + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CURRENT_MACHINE)) + return 0; + + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + return -1; + + if (VIR_ALLOC(info) < 0) + return -1; + + ret = qemuMonitorGetCurrentMachineInfo(priv->mon, info); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + ret = -1; + + if (ret < 0) + goto cleanup; + + if (info->wakeupSuspendSupport) + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_PM_WAKEUP_SUPPORT); + + cleanup: + VIR_FREE(info); + return ret; +} /** * qemuProcessLaunch: @@ -6778,6 +6811,9 @@ qemuProcessLaunch(virConnectPtr conn, if (qemuProcessSetupDiskThrottlingBlockdev(driver, vm, asyncJob) < 0) goto cleanup; + if (qemuProcessSetCurrentMachineCaps(driver, vm, asyncJob) < 0) + goto cleanup; + /* Since CPUs were not started yet, the balloon could not return the memory * to the host and thus cur_balloon needs to be updated so that GetXMLdesc * and friends return the correct size in case they can't grab the job */ -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list