On 4/9/19 6:18 PM, Daniel Henrique Barboza wrote:
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(a)gmail.com>
---
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;
Oh, we don't query for qemu capabilities in ProcessLaunch. Maybe it
doesn't matter right now because there is no decission to be made when
building the cmd line, but nevertheless this must be done in
virQEMUCapsInitQMPMonitor() or in one of the function it's calling.
Michal