qemu: require qmp on new enough qemu

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.
This commit is contained in:
Eric Blake 2012-01-25 21:57:38 -07:00
parent ff88cd5905
commit 6e769ebadb
3 changed files with 32 additions and 7 deletions

View File

@ -982,12 +982,13 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps)
} }
static void static int
qemuCapsComputeCmdFlags(const char *help, qemuCapsComputeCmdFlags(const char *help,
unsigned int version, unsigned int version,
unsigned int is_kvm, unsigned int is_kvm,
unsigned int kvm_version, unsigned int kvm_version,
virBitmapPtr flags) virBitmapPtr flags,
bool check_yajl ATTRIBUTE_UNUSED)
{ {
const char *p; const char *p;
const char *fsdev; const char *fsdev;
@ -1184,6 +1185,24 @@ qemuCapsComputeCmdFlags(const char *help,
qemuCapsSet(flags, QEMU_CAPS_MONITOR_JSON); qemuCapsSet(flags, QEMU_CAPS_MONITOR_JSON);
qemuCapsSet(flags, QEMU_CAPS_NETDEV); qemuCapsSet(flags, QEMU_CAPS_NETDEV);
} }
#else
/* Starting with qemu 0.15 and newer, upstream qemu no longer
* promises to keep the human interface stable, but requests 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 libvirt to be "
"compiled with yajl"));
return -1;
}
qemuCapsSet(flags, QEMU_CAPS_NETDEV);
}
#endif #endif
if (version >= 13000) if (version >= 13000)
@ -1204,6 +1223,7 @@ qemuCapsComputeCmdFlags(const char *help,
if (version >= 11000) if (version >= 11000)
qemuCapsSet(flags, QEMU_CAPS_CPU_HOST); qemuCapsSet(flags, QEMU_CAPS_CPU_HOST);
return 0;
} }
/* We parse the output of 'qemu -help' to get the QEMU /* We parse the output of 'qemu -help' to get the QEMU
@ -1235,7 +1255,8 @@ int qemuCapsParseHelpStr(const char *qemu,
virBitmapPtr flags, virBitmapPtr flags,
unsigned int *version, unsigned int *version,
unsigned int *is_kvm, unsigned int *is_kvm,
unsigned int *kvm_version) unsigned int *kvm_version,
bool check_yajl)
{ {
unsigned major, minor, micro; unsigned major, minor, micro;
const char *p = help; const char *p = help;
@ -1291,7 +1312,9 @@ int qemuCapsParseHelpStr(const char *qemu,
*version = (major * 1000 * 1000) + (minor * 1000) + micro; *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); strflags = virBitmapString(flags);
VIR_DEBUG("Version %u.%u.%u, cooked version %u, flags %s", VIR_DEBUG("Version %u.%u.%u, cooked version %u, flags %s",
@ -1314,6 +1337,7 @@ fail:
_("cannot parse %s version number in '%s'"), _("cannot parse %s version number in '%s'"),
qemu, p ? p : help); qemu, p ? p : help);
cleanup:
VIR_FREE(p); VIR_FREE(p);
return -1; return -1;
@ -1455,7 +1479,7 @@ int qemuCapsExtractVersionInfo(const char *qemu, const char *arch,
if (!(flags = qemuCapsNew()) || if (!(flags = qemuCapsNew()) ||
qemuCapsParseHelpStr(qemu, help, flags, qemuCapsParseHelpStr(qemu, help, flags,
&version, &is_kvm, &kvm_version) == -1) &version, &is_kvm, &kvm_version, true) == -1)
goto cleanup; goto cleanup;
/* Currently only x86_64 and i686 support PCI-multibus. */ /* Currently only x86_64 and i686 support PCI-multibus. */

View File

@ -162,7 +162,8 @@ int qemuCapsParseHelpStr(const char *qemu,
virBitmapPtr qemuCaps, virBitmapPtr qemuCaps,
unsigned int *version, unsigned int *version,
unsigned int *is_kvm, unsigned int *is_kvm,
unsigned int *kvm_version); unsigned int *kvm_version,
bool check_yajl);
int qemuCapsParseDeviceStr(const char *str, int qemuCapsParseDeviceStr(const char *str,
virBitmapPtr qemuCaps); virBitmapPtr qemuCaps);

View File

@ -53,7 +53,7 @@ static int testHelpStrParsing(const void *data)
goto cleanup; goto cleanup;
if (qemuCapsParseHelpStr("QEMU", help, flags, if (qemuCapsParseHelpStr("QEMU", help, flags,
&version, &is_kvm, &kvm_version) == -1) &version, &is_kvm, &kvm_version, false) == -1)
goto cleanup; goto cleanup;
# ifndef HAVE_YAJL # ifndef HAVE_YAJL