The qemu developers have made it clear that modern qemu will no
longer guarantee human monitor command stability; furthermore,
some features, such as async events, are only supported via qmp.
If we are compiled without support for handling JSON, we cannot
expect to sanely interact with modern qemu.
However, things must continue to build on RHEL 5, where qemu
is stuck at 0.10, and where yajl is not available.
Another benefit of this patch: future additions of new monitor
commands need only focus on qemu_monitor_json.c, instead of
also wasting time with qemu_monitor_text.c.
* src/qemu/qemu_capabilities.c (qemuCapsComputeCmdFlags): Report
error if yajl is missing but qemu requires qmp.
(qemuCapsParseHelpStr): Propagate error.
(qemuCapsExtractVersionInfo): Update caller.
* tests/qemuhelptest.c (testHelpStrParsing): Likewise.
---
Tested on Fedora 16, RHEL 6.2, and RHEL 5.8.
src/qemu/qemu_capabilities.c | 33 ++++++++++++++++++++++++++++-----
src/qemu/qemu_capabilities.h | 3 ++-
tests/qemuhelptest.c | 2 +-
3 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c4bad6f..13a9cb0 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -982,12 +982,13 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps)
}
-static void
+static int
qemuCapsComputeCmdFlags(const char *help,
unsigned int version,
unsigned int is_kvm,
unsigned int kvm_version,
- virBitmapPtr flags)
+ virBitmapPtr flags,
+ bool check_yajl ATTRIBUTE_UNUSED)
{
const char *p;
const char *fsdev;
@@ -1184,6 +1185,23 @@ qemuCapsComputeCmdFlags(const char *help,
qemuCapsSet(flags, QEMU_CAPS_MONITOR_JSON);
qemuCapsSet(flags, QEMU_CAPS_NETDEV);
}
+#else
+ /* Starting with qemu 0.15 and newer, upstream qemu no longer
+ * promised to keep the human interface stable, but request that
+ * we use QMP (the JSON interface) for everything. If the user
+ * forgot to include YAJL libraries when building their own
+ * libvirt but is targetting a newer qemu, we are better off
+ * telling them to recompile (the spec file includes the
+ * dependency, so distros won't hit this). */
+ if (version >= 15000 ||
+ (version >= 12000 && strstr(help, "libvirt"))) {
+ if (check_yajl) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this qemu binary requires compilation with
yajl"));
+ return -1;
+ }
+ qemuCapsSet(flags, QEMU_CAPS_NETDEV);
+ }
#endif
if (version >= 13000)
@@ -1204,6 +1222,7 @@ qemuCapsComputeCmdFlags(const char *help,
if (version >= 11000)
qemuCapsSet(flags, QEMU_CAPS_CPU_HOST);
+ return 0;
}
/* We parse the output of 'qemu -help' to get the QEMU
@@ -1235,7 +1254,8 @@ int qemuCapsParseHelpStr(const char *qemu,
virBitmapPtr flags,
unsigned int *version,
unsigned int *is_kvm,
- unsigned int *kvm_version)
+ unsigned int *kvm_version,
+ bool check_yajl)
{
unsigned major, minor, micro;
const char *p = help;
@@ -1291,7 +1311,9 @@ int qemuCapsParseHelpStr(const char *qemu,
*version = (major * 1000 * 1000) + (minor * 1000) + micro;
- qemuCapsComputeCmdFlags(help, *version, *is_kvm, *kvm_version, flags);
+ if (qemuCapsComputeCmdFlags(help, *version, *is_kvm, *kvm_version,
+ flags, check_yajl) < 0)
+ goto cleanup;
strflags = virBitmapString(flags);
VIR_DEBUG("Version %u.%u.%u, cooked version %u, flags %s",
@@ -1314,6 +1336,7 @@ fail:
_("cannot parse %s version number in '%s'"),
qemu, p ? p : help);
+cleanup:
VIR_FREE(p);
return -1;
@@ -1455,7 +1478,7 @@ int qemuCapsExtractVersionInfo(const char *qemu, const char *arch,
if (!(flags = qemuCapsNew()) ||
qemuCapsParseHelpStr(qemu, help, flags,
- &version, &is_kvm, &kvm_version) == -1)
+ &version, &is_kvm, &kvm_version, true) == -1)
goto cleanup;
/* Currently only x86_64 and i686 support PCI-multibus. */
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 8b009f9..18d6bc8 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -162,7 +162,8 @@ int qemuCapsParseHelpStr(const char *qemu,
virBitmapPtr qemuCaps,
unsigned int *version,
unsigned int *is_kvm,
- unsigned int *kvm_version);
+ unsigned int *kvm_version,
+ bool check_yajl);
int qemuCapsParseDeviceStr(const char *str,
virBitmapPtr qemuCaps);
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index 5ad55bc..370cd0d 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -53,7 +53,7 @@ static int testHelpStrParsing(const void *data)
goto cleanup;
if (qemuCapsParseHelpStr("QEMU", help, flags,
- &version, &is_kvm, &kvm_version) == -1)
+ &version, &is_kvm, &kvm_version, false) == -1)
goto cleanup;
# ifndef HAVE_YAJL
--
1.7.7.6