From: Daniel P. Berrange berra...@redhat.com
Start a QEMU process using
$QEMU -S -no-user-config -nodefaults \
-nographic -M none -qmp unix:/some/path,server,nowait
and talk QMP over stdio to discover what capabilities the
binary supports. This works for QEMU 1.2.0 or later and
for older QEMU automatically fallback to the old approach
of parsing -help and related command line args.
Signed-off-by: Daniel P. Berrange berra...@redhat.com
---
src/qemu/qemu_capabilities.c | 419 +++
src/qemu/qemu_capabilities.h | 5 +-
src/qemu/qemu_driver.c | 2 +-
3 files changed, 385 insertions(+), 41 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index f0442ee..c977e25 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -35,6 +35,7 @@
#include command.h
#include bitmap.h
#include virnodesuspend.h
+#include qemu_monitor.h
#include sys/stat.h
#include unistd.h
@@ -189,6 +190,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
struct _qemuCaps {
virObject object;
+bool usedQMP;
+
char *binary;
time_t mtime;
@@ -210,6 +213,7 @@ struct _qemuCaps {
struct _qemuCapsCache {
virMutex lock;
virHashTablePtr binaries;
+char *libDir;
};
@@ -1286,6 +1290,7 @@ static struct qemuCapsStringFlags
qemuCapsObjectPropsVirtioNet[] = {
};
static struct qemuCapsStringFlags qemuCapsObjectPropsPciAssign[] = {
+{ rombar, QEMU_CAPS_PCI_ROMBAR },
{ configfd, QEMU_CAPS_PCI_CONFIGFD },
{ bootindex, QEMU_CAPS_PCI_BOOTINDEX },
};
@@ -1866,6 +1871,10 @@ qemuCapsProbeQMPCommands(qemuCapsPtr caps,
qemuCapsSet(caps, QEMU_CAPS_BLOCKJOB_ASYNC);
else if (STREQ(name, dump-guest-memory))
qemuCapsSet(caps, QEMU_CAPS_DUMP_GUEST_MEMORY);
+else if (STREQ(name, query-spice))
+qemuCapsSet(caps, QEMU_CAPS_SPICE);
+else if (STREQ(name, query-kvm))
+qemuCapsSet(caps, QEMU_CAPS_KVM);
VIR_FREE(name);
}
VIR_FREE(commands);
@@ -1898,11 +1907,117 @@ qemuCapsProbeQMPEvents(qemuCapsPtr caps,
}
+static int
+qemuCapsProbeQMPObjects(qemuCapsPtr caps,
+qemuMonitorPtr mon)
+{
+int nvalues;
+char **values;
+size_t i;
+
+if ((nvalues = qemuMonitorGetObjectTypes(mon, values)) 0)
+return -1;
+qemuCapsProcessStringFlags(caps,
+ ARRAY_CARDINALITY(qemuCapsObjectTypes),
+ qemuCapsObjectTypes,
+ nvalues, values);
+qemuCapsFreeStringList(nvalues, values);
+
+for (i = 0 ; i ARRAY_CARDINALITY(qemuCapsObjectProps); i++) {
+const char *type = qemuCapsObjectProps[i].type;
+if ((nvalues = qemuMonitorGetObjectProps(mon,
+ type,
+ values)) 0)
+return -1;
+qemuCapsProcessStringFlags(caps,
+ qemuCapsObjectProps[i].nprops,
+ qemuCapsObjectProps[i].props,
+ nvalues, values);
+qemuCapsFreeStringList(nvalues, values);
+}
+
+/* Prefer -chardev spicevmc (detected earlier) over -device spicevmc */
+if (qemuCapsGet(caps, QEMU_CAPS_CHARDEV_SPICEVMC))
+qemuCapsClear(caps, QEMU_CAPS_DEVICE_SPICEVMC);
+
+return 0;
+}
+
+
+static int
+qemuCapsProbeQMPMachineTypes(qemuCapsPtr caps,
+ qemuMonitorPtr mon)
+{
+qemuMonitorMachineInfoPtr *machines = NULL;
+int nmachines = 0;
+int ret = -1;
+size_t i;
+
+if ((nmachines = qemuMonitorGetMachines(mon, machines)) 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(caps-machineTypes, nmachines) 0) {
+virReportOOMError();
+goto cleanup;
+}
+if (VIR_ALLOC_N(caps-machineAliases, nmachines) 0) {
+virReportOOMError();
+goto cleanup;
+}
+
+for (i = 0 ; i nmachines ; i++) {
+if (machines[i]-alias) {
+if (!(caps-machineAliases[i] = strdup(machines[i]-name))) {
+virReportOOMError();
+goto cleanup;
+}
+if (!(caps-machineTypes[i] = strdup(machines[i]-alias))) {
+virReportOOMError();
+goto cleanup;
+}
+} else {
+if (!(caps-machineTypes[i] = strdup(machines[i]-name))) {
+virReportOOMError();
+goto cleanup;
+}
+}
+}
+
+ret = 0;
+
+cleanup:
+for (i = 0 ; i nmachines ; i++)
+qemuMonitorMachineInfoFree(machines[i]);
+VIR_FREE(machines);
+return ret;
+}
+
+
+static int
+qemuCapsProbeQMPCPUDefinitions(qemuCapsPtr caps,
+ qemuMonitorPtr mon)
+{
+int ncpuDefinitions;
+char **cpuDefinitions;
+
+if ((ncpuDefinitions =