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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list