[libvirt] [PATCH 1.1/3] qemu: Fallback to HMP when savevm QMP command is not found
Daniel P. Berrange
berrange at redhat.com
Thu Mar 3 15:03:59 UTC 2011
On Fri, Feb 25, 2011 at 07:04:08PM +0100, Jiri Denemark wrote:
> qemu driver in libvirt gained support for creating domain snapshots
> almost a year ago in libvirt 0.8.0. Since then we enabled QMP support
> for qemu >= 0.13.0 but a QMP equivalent of savevm command is not
> implemented in current qemu (0.14.0) so the domain snapshot support is
> not very useful.
>
> This patch detects when the appropriate QMP command is not implemented
> and tries to use human-monitor-command (aka HMP passthrough) to run
> savevm HMP command.
> ---
> src/qemu/qemu_monitor_json.c | 144 +++++++++++++++++++++++++++++++++--------
> 1 files changed, 116 insertions(+), 28 deletions(-)
>
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index e6903a1..6dd7980 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -675,6 +675,65 @@ static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValueP
> }
>
>
> +static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_FMT_PRINTF(3, 4)
> +qemuMonitorJSONHumanCommand(qemuMonitorPtr mon,
> + char **reply_str,
> + const char *fmt, ...)
> +{
> + virJSONValuePtr cmd = NULL;
> + virJSONValuePtr reply = NULL;
> + virJSONValuePtr obj;
> + char *cmd_str = NULL;
> + va_list ap;
> + int ret = -1;
> +
> + va_start(ap, fmt);
> + if (virVasprintf(&cmd_str, fmt, ap) < 0) {
> + virReportOOMError();
> + goto cleanup;
> + }
This is a little dodgy because it doesn't take care of any data
escaping of special characters in the args.
> @@ -2389,6 +2448,47 @@ int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon,
> return ret;
> }
>
> +
> +static int
> +qemuMonitorJSONCreateSnapshotHMP(qemuMonitorPtr mon, const char *name)
> +{
> + char *reply = NULL;
> + int ret = -1;
> +
> + if (qemuMonitorJSONHumanCommand(mon, &reply, "savevm \"%s\"", name) < 0) {
> + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
> + _("failed to take snapshot using HMP command"));
> + goto cleanup;
> + }
> +
> + if (strstr(reply, "Error while creating snapshot")) {
> + qemuReportError(VIR_ERR_OPERATION_FAILED,
> + _("failed to take snapshot: %s"), reply);
> + goto cleanup;
> + }
> + else if (strstr(reply, "No block device can accept snapshots")) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("this domain does not have a device to"
> + " take snapshots"));
> + goto cleanup;
> + }
> + else if (strstr(reply, "Could not open VM state file")) {
> + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply);
> + goto cleanup;
> + }
> + else if (strstr(reply, "Error")
> + && strstr(reply, "while writing VM")) {
> + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply);
> + goto cleanup;
> + }
> +
> + ret = 0;
> +
> +cleanup:
> + VIR_FREE(reply);
> + return ret;
> +}
Could we re-factor the qemuMonitorTextCreateSnapshot() command so
that the code which generates the command string & the code which
checks the reply are separate callback methods. Then, this JSON
code could do something like
static int
qemuMonitorJSONCreateSnapshotHMP(qemuMonitorPtr mon, const char *name)
{
if (!(cmdstr = qemuMonitorTextMakeCreateSnapshotCommand(...)))
return -1;
reply = qemuMonitorJSONHumanCommand(cmdstr)
VIR_FREE(cmdstr);
if (!reply)
return -1;
if (qemuMonitorTextCheckCreateSnapshotReply(reply) < 0)
return -1;
return 0;
}
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list