qemuMonitorText{Create,Load,Delete}Snapshot command were refactored so that parts of the code that build qemu commands and the parts that check qemu reply can be used separately from JSON monitor code. Two new functions were created for each of those commands qemuMonitorText*Snapshot{MakeCommand,CheckReply} This patch also fixes escaping of {save,load,del}vm argument. --- src/qemu/qemu_monitor_text.c | 179 ++++++++++++++++++++++++++++++------------ src/qemu/qemu_monitor_text.h | 8 ++ 2 files changed, 135 insertions(+), 52 deletions(-) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 0aed690..0024c5d 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2568,100 +2568,149 @@ cleanup: return ret; } -int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name) + +char * +qemuMonitorTextCreateSnapshotMakeCommand(const char *name) { - char *cmd; - char *reply = NULL; - int ret = -1; + char *cmd = NULL; + char *safename; - if (virAsprintf(&cmd, "savevm \"%s\"", name) < 0) { + if (!(safename = qemuMonitorEscapeArg(name)) || + virAsprintf(&cmd, "savevm \"%s\"", safename) < 0) { virReportOOMError(); - return -1; - } - - if (qemuMonitorCommand(mon, cmd, &reply)) { - qemuReportError(VIR_ERR_OPERATION_FAILED, - _("failed to take snapshot using command '%s'"), cmd); goto cleanup; } +cleanup: + VIR_FREE(safename); + + return cmd; +} + +int +qemuMonitorTextCreateSnapshotCheckReply(const char *reply) +{ if (strstr(reply, "Error while creating snapshot") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, _("Failed to take snapshot: %s"), reply); - goto cleanup; + return -1; } else if (strstr(reply, "No block device can accept snapshots") != NULL) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("this domain does not have a device to take snapshots")); - goto cleanup; + _("this domain does not have a device" + " to take snapshots")); + return -1; } else if (strstr(reply, "Could not open VM state file") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply); - goto cleanup; + return -1; } else if (strstr(reply, "Error") != NULL && strstr(reply, "while writing VM") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply); - goto cleanup; + return -1; } - ret = 0; - -cleanup: - VIR_FREE(cmd); - VIR_FREE(reply); - return ret; + return 0; } -int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name) +int +qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name) { char *cmd; char *reply = NULL; int ret = -1; - if (virAsprintf(&cmd, "loadvm \"%s\"", name) < 0) { - virReportOOMError(); + if (!(cmd = qemuMonitorTextCreateSnapshotMakeCommand(name))) return -1; - } if (qemuMonitorCommand(mon, cmd, &reply)) { qemuReportError(VIR_ERR_OPERATION_FAILED, - _("failed to restore snapshot using command '%s'"), - cmd); + _("failed to take snapshot using command '%s'"), cmd); + goto cleanup; + } + + ret = qemuMonitorTextCreateSnapshotCheckReply(reply); + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + return ret; +} + + +char * +qemuMonitorTextLoadSnapshotMakeCommand(const char *name) +{ + char *cmd = NULL; + char *safename; + + if (!(safename = qemuMonitorEscapeArg(name)) || + virAsprintf(&cmd, "loadvm \"%s\"", safename) < 0) { + virReportOOMError(); goto cleanup; } +cleanup: + VIR_FREE(safename); + + return cmd; +} + +int +qemuMonitorTextLoadSnapshotCheckReply(const char *reply, const char *name) +{ if (strstr(reply, "No block device supports snapshots") != NULL) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("this domain does not have a device to load snapshots")); - goto cleanup; + _("this domain does not have a device" + " to load snapshots")); + return -1; } else if (strstr(reply, "Could not find snapshot") != NULL) { qemuReportError(VIR_ERR_OPERATION_INVALID, - _("the snapshot '%s' does not exist, and was not loaded"), - name); - goto cleanup; + _("the snapshot '%s' does not exist," + " and was not loaded"), name); + return -1; } else if (strstr(reply, "Snapshots not supported on device") != NULL) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", reply); - goto cleanup; + return -1; } else if (strstr(reply, "Could not open VM state file") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply); - goto cleanup; + return -1; } else if (strstr(reply, "Error") != NULL && strstr(reply, "while loading VM state") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply); - goto cleanup; + return -1; } else if (strstr(reply, "Error") != NULL && strstr(reply, "while activating snapshot on") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply); + return -1; + } + + return 0; +} + +int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name) +{ + char *cmd; + char *reply = NULL; + int ret = -1; + + if (!(cmd = qemuMonitorTextLoadSnapshotMakeCommand(name))) + return -1; + + if (qemuMonitorCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to restore snapshot using command '%s'"), + cmd); goto cleanup; } - ret = 0; + ret = qemuMonitorTextLoadSnapshotCheckReply(reply, name); cleanup: VIR_FREE(cmd); @@ -2669,39 +2718,64 @@ cleanup: return ret; } -int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name) + +char * +qemuMonitorTextDeleteSnapshotMakeCommand(const char *name) { - char *cmd; - char *reply = NULL; - int ret = -1; + char *cmd = NULL; + char *safename; - if (virAsprintf(&cmd, "delvm \"%s\"", name) < 0) { + if (!(safename = qemuMonitorEscapeArg(name)) || + virAsprintf(&cmd, "delvm \"%s\"", safename) < 0) { virReportOOMError(); - return -1; - } - if (qemuMonitorCommand(mon, cmd, &reply)) { - qemuReportError(VIR_ERR_OPERATION_FAILED, - _("failed to delete snapshot using command '%s'"), - cmd); goto cleanup; } +cleanup: + VIR_FREE(safename); + + return cmd; +} + +int +qemuMonitorTextDeleteSnapshotCheckReply(const char *reply) +{ if (strstr(reply, "No block device supports snapshots") != NULL) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("this domain does not have a device to delete snapshots")); - goto cleanup; + _("this domain does not have a device" + " to delete snapshots")); + return 1; } else if (strstr(reply, "Snapshots not supported on device") != NULL) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", reply); - goto cleanup; + return 1; } else if (strstr(reply, "Error") != NULL && strstr(reply, "while deleting snapshot") != NULL) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", reply); + return 1; + } + + return 0; +} + +int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name) +{ + char *cmd; + char *reply = NULL; + int ret = -1; + + if (!(cmd = qemuMonitorTextDeleteSnapshotMakeCommand(name))) + return -1; + + if (qemuMonitorCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to delete snapshot using command '%s'"), + cmd); goto cleanup; } - ret = 0; + ret = qemuMonitorTextDeleteSnapshotCheckReply(reply); cleanup: VIR_FREE(cmd); @@ -2709,6 +2783,7 @@ cleanup: return ret; } + int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index b29dbcc..07b6246 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -202,8 +202,16 @@ int qemuMonitorTextSetDrivePassphrase(qemuMonitorPtr mon, const char *passphrase); int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name); +char *qemuMonitorTextCreateSnapshotMakeCommand(const char *name); +int qemuMonitorTextCreateSnapshotCheckReply(const char *reply); + int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name); +char *qemuMonitorTextLoadSnapshotMakeCommand(const char *name); +int qemuMonitorTextLoadSnapshotCheckReply(const char *reply, const char *name); + int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); +char *qemuMonitorTextDeleteSnapshotMakeCommand(const char *name); +int qemuMonitorTextDeleteSnapshotCheckReply(const char *reply); int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); -- 1.7.4.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list