
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 :|