From 42c52d53c31a6309a0ae086aedd4396fbb0d48db Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 27 Aug 2011 08:16:04 -0600 Subject: [PATCH] snapshot: expose --running and --paused in virsh Pretty straight-forward exposure of new flags. For most commands, we let the API reject mutually exclusive flags; but for save-image-edit, we do the sanity check ourselves to avoid looping on flag failure if the edit cycle is ever enhanced to allow the user to retry an edit to fix up an xml validation error. * tools/virsh.c (cmdManagedSave, cmdRestore, cmdSave) (cmdSaveImageDefine, cmdSaveImageEdit): Add new flags. * tools/virsh.pod (managedsave, restore, save, save-image-define) (save-image-edit): Document them. --- tools/virsh.c | 65 ++++++++++++++++++++++++++++++++++++++++++++----- tools/virsh.pod | 44 ++++++++++++++++++++++++++++++--- 2 files changed, 99 insertions(+), 10 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 924d31bcf9..ba2f22b17b 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1641,6 +1641,8 @@ static const vshCmdOptDef opts_save[] = { {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to save the data")}, {"xml", VSH_OT_STRING, 0, N_("filename containing updated XML for the target")}, + {"running", VSH_OT_BOOL, 0, N_("set domain to be running on restore")}, + {"paused", VSH_OT_BOOL, 0, N_("set domain to be paused on restore")}, {NULL, 0, 0, NULL} }; @@ -1663,6 +1665,10 @@ cmdSave(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "bypass-cache")) flags |= VIR_DOMAIN_SAVE_BYPASS_CACHE; + if (vshCommandOptBool(cmd, "running")) + flags |= VIR_DOMAIN_SAVE_RUNNING; + if (vshCommandOptBool(cmd, "paused")) + flags |= VIR_DOMAIN_SAVE_PAUSED; if (vshCommandOptString(cmd, "xml", &xmlfile) < 0) { vshError(ctl, "%s", _("malformed xml argument")); @@ -1750,6 +1756,8 @@ static const vshCmdOptDef opts_save_image_define[] = { {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to modify")}, {"xml", VSH_OT_STRING, VSH_OFLAG_REQ, N_("filename containing updated XML for the target")}, + {"running", VSH_OT_BOOL, 0, N_("set domain to be running on restore")}, + {"paused", VSH_OT_BOOL, 0, N_("set domain to be paused on restore")}, {NULL, 0, 0, NULL} }; @@ -1760,6 +1768,12 @@ cmdSaveImageDefine(vshControl *ctl, const vshCmd *cmd) bool ret = false; const char *xmlfile = NULL; char *xml = NULL; + unsigned int flags = 0; + + if (vshCommandOptBool(cmd, "running")) + flags |= VIR_DOMAIN_SAVE_RUNNING; + if (vshCommandOptBool(cmd, "paused")) + flags |= VIR_DOMAIN_SAVE_PAUSED; if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -1799,6 +1813,8 @@ static const vshCmdInfo info_save_image_edit[] = { static const vshCmdOptDef opts_save_image_edit[] = { {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to edit")}, + {"running", VSH_OT_BOOL, 0, N_("set domain to be running on restore")}, + {"paused", VSH_OT_BOOL, 0, N_("set domain to be paused on restore")}, {NULL, 0, 0, NULL} }; @@ -1810,7 +1826,22 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) char *tmp = NULL; char *doc = NULL; char *doc_edited = NULL; - unsigned int flags = VIR_DOMAIN_XML_SECURE; + unsigned int getxml_flags = VIR_DOMAIN_XML_SECURE; + unsigned int define_flags = 0; + + if (vshCommandOptBool(cmd, "running")) + define_flags |= VIR_DOMAIN_SAVE_RUNNING; + if (vshCommandOptBool(cmd, "paused")) + define_flags |= VIR_DOMAIN_SAVE_PAUSED; + + /* Normally, we let the API reject mutually exclusive flags. + * However, in the edit cycle, we let the user retry if the define + * step fails, but the define step will always fail on invalid + * flags, so we reject it up front to avoid looping. */ + if (define_flags == (VIR_DOMAIN_SAVE_RUNNING | VIR_DOMAIN_SAVE_PAUSED)) { + vshError(ctl, "%s", _("--running and --saved are mutually exclusive")); + return false; + } if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -1819,7 +1850,7 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) return false; /* Get the XML configuration of the saved image. */ - doc = virDomainSaveImageGetXMLDesc(ctl->conn, file, flags); + doc = virDomainSaveImageGetXMLDesc(ctl->conn, file, getxml_flags); if (!doc) goto cleanup; @@ -1837,8 +1868,9 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) if (!doc_edited) goto cleanup; - /* Compare original XML with edited. Has it changed at all? */ - if (STREQ(doc, doc_edited)) { + /* Compare original XML with edited. Short-circuit if it did not + * change, and we do not have any flags. */ + if (STREQ(doc, doc_edited) && !define_flags) { vshPrint(ctl, _("Saved image %s XML configuration not changed.\n"), file); ret = true; @@ -1846,7 +1878,8 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) } /* Everything checks out, so redefine the xml. */ - if (virDomainSaveImageDefineXML(ctl->conn, file, doc_edited, 0) < 0) { + if (virDomainSaveImageDefineXML(ctl->conn, file, doc_edited, + define_flags) < 0) { vshError(ctl, _("Failed to update %s"), file); goto cleanup; } @@ -1879,6 +1912,8 @@ static const vshCmdInfo info_managedsave[] = { static const vshCmdOptDef opts_managedsave[] = { {"bypass-cache", VSH_OT_BOOL, 0, N_("avoid file system cache when saving")}, {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"running", VSH_OT_BOOL, 0, N_("set domain to be running on next start")}, + {"paused", VSH_OT_BOOL, 0, N_("set domain to be paused on next start")}, {NULL, 0, 0, NULL} }; @@ -1895,6 +1930,10 @@ cmdManagedSave(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "bypass-cache")) flags |= VIR_DOMAIN_SAVE_BYPASS_CACHE; + if (vshCommandOptBool(cmd, "running")) + flags |= VIR_DOMAIN_SAVE_RUNNING; + if (vshCommandOptBool(cmd, "paused")) + flags |= VIR_DOMAIN_SAVE_PAUSED; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) return false; @@ -2238,6 +2277,8 @@ static const vshCmdOptDef opts_restore[] = { N_("avoid file system cache when restoring")}, {"xml", VSH_OT_STRING, 0, N_("filename containing updated XML for the target")}, + {"running", VSH_OT_BOOL, 0, N_("restore domain into running state")}, + {"paused", VSH_OT_BOOL, 0, N_("restore domain into paused state")}, {NULL, 0, 0, NULL} }; @@ -2258,6 +2299,10 @@ cmdRestore(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "bypass-cache")) flags |= VIR_DOMAIN_SAVE_BYPASS_CACHE; + if (vshCommandOptBool(cmd, "running")) + flags |= VIR_DOMAIN_SAVE_RUNNING; + if (vshCommandOptBool(cmd, "paused")) + flags |= VIR_DOMAIN_SAVE_PAUSED; if (vshCommandOptString(cmd, "xml", &xmlfile) < 0) { vshError(ctl, "%s", _("malformed xml argument")); @@ -12392,6 +12437,8 @@ static const vshCmdInfo info_snapshot_revert[] = { static const vshCmdOptDef opts_snapshot_revert[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"snapshotname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")}, + {"running", VSH_OT_BOOL, 0, N_("after reverting, change state to running")}, + {"paused", VSH_OT_BOOL, 0, N_("after reverting, change state to paused")}, {NULL, 0, 0, NULL} }; @@ -12402,6 +12449,12 @@ cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd) bool ret = false; const char *name = NULL; virDomainSnapshotPtr snapshot = NULL; + unsigned int flags = 0; + + if (vshCommandOptBool(cmd, "running")) + flags |= VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING; + if (vshCommandOptBool(cmd, "paused")) + flags |= VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED; if (!vshConnectionUsability(ctl, ctl->conn)) goto cleanup; @@ -12417,7 +12470,7 @@ cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd) if (snapshot == NULL) goto cleanup; - if (virDomainRevertToSnapshot(snapshot, 0) < 0) + if (virDomainRevertToSnapshot(snapshot, flags) < 0) goto cleanup; ret = true; diff --git a/tools/virsh.pod b/tools/virsh.pod index 2e765725a3..53b73883e6 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -623,6 +623,7 @@ The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment variables, and defaults to C. =item B I [I<--bypass-cache>] +[{I<--running> | I<--paused>}] Save and destroy (stop) a running domain, so it can be restarted from the same state at a later time. When the virsh B command is next run for @@ -630,6 +631,11 @@ the domain, it will automatically be started from this saved state. If I<--bypass-cache> is specified, the save will avoid the file system cache, although this may slow down the operation. +Normally, starting a managed save will decide between running or paused +based on the state the domain was in when the save was done; passing +either the I<--running> or I<--paused> flag will allow overriding which +state the B should use. + The B command can be used to query whether a domain currently has any managed save image. @@ -716,6 +722,7 @@ The exact behavior of a domain when it reboots is set by the I parameter in the domain's XML definition. =item B I [I<--bypass-cache>] [I<--xml> B] +[{I<--running> | I<--paused>}] Restores a domain from a B state file. See I for more info. @@ -728,12 +735,18 @@ in the host-specific portions of the domain XML. For example, it can be used to account for file naming differences in underlying storage due to disk snapshots taken after the guest was saved. +Normally, restoring a saved image will use the state recorded in the +save image to decide between running or paused; passing either the +I<--running> or I<--paused> flag will allow overriding which state the +domain should be started in. + B: To avoid corrupting file system contents within the domain, you should not reuse the saved state file for a second B unless you have also reverted all storage volumes back to the same contents as when the state file was created. =item B I I [I<--bypass-cache>] [I<--xml> B] +[{I<--running> | I<--paused>}] Saves a running domain (RAM, but not disk state) to a state file so that it can be restored @@ -753,12 +766,17 @@ in the host-specific portions of the domain XML. For example, it can be used to account for file naming differences that are planned to be made via disk snapshots of underlying storage after the guest is saved. +Normally, restoring a saved image will decide between running or paused +based on the state the domain was in when the save was done; passing +either the I<--running> or I<--paused> flag will allow overriding which +state the B should use. + Domain saved state files assume that disk images will be unchanged between the creation and restore point. For a more complete system restore point, where the disk state is saved alongside the memory state, see the B family of commands. -=item B I I +=item B I I [{I<--running> | I<--paused>}] Update the domain XML that will be used when I is later used in the B command. The I argument must be a file @@ -767,17 +785,27 @@ host-specific portions of the domain XML. For example, it can be used to account for file naming differences resulting from creating disk snapshots of underlying storage after the guest was saved. +The save image records whether the domain should be restored to a +running or paused state. Normally, this command does not alter the +recorded state; passing either the I<--running> or I<--paused> flag +will allow overriding which state the B should use. + =item B I [I<--security-info>] Extract the domain XML that was in effect at the time the saved state file I was created with the B command. Using I<--security-info> will also include security sensitive information. -=item B I +=item B I [{I<--running> | I<--paused>}] Edit the XML configuration associated with a saved state file I created by the B command. +The save image records whether the domain should be restored to a +running or paused state. Normally, this command does not alter the +recorded state; passing either the I<--running> or I<--paused> flag +will allow overriding which state the B should use. + This is equivalent to: virsh save-image-dumpxml state-file > state-file.xml @@ -1691,14 +1719,22 @@ Output the snapshot XML for the domain's snapshot named I. Output the name of the parent snapshot for the given I, if any. -=item B I I +=item B I I [{I<--running> | I<--paused>}] Revert the given domain to the snapshot specified by I. Be aware -that this is a destructive action; any changes in the domain since the +that this is a destructive action; any changes in the domain since the last snapshot was taken will be lost. Also note that the state of the domain after snapshot-revert is complete will be the state of the domain at the time the original snapshot was taken. +Normally, reverting to a snapshot leaves the domain in the state it was +at the time the snapshot was created, except that a disk snapshot with +no vm state leaves the domain in an inactive state. Passing either the +I<--running> or I<--paused> flag will perform additional state changes +(such as booting an inactive domain, or pausing a running domain). Since +transient domains cannot be inactive, it is required to use one of these +flags when reverting to a disk snapshot of a transient domain. + =item B I I I<--children> Delete the snapshot for the domain named I. If this snapshot