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 d43123c..2e41b45 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"));
@@ -12382,6 +12427,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}
};
@@ -12392,6 +12439,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;
@@ -12407,7 +12460,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 b90c26e..30ab5ca 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<vi>.
=item B<managedsave> I<domain-id> [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<start> 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<start> should use.
+
The B<dominfo> 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<on_reboot> parameter in the domain's XML definition.
=item B<restore> I<state-file> [I<--bypass-cache>] [I<--xml>
B<file>]
+[{I<--running> | I<--paused>}]
Restores a domain from a B<virsh save> state file. See I<save> 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<Note>: To avoid corrupting file system contents within the domain, you
should not reuse the saved state file for a second B<restore> unless you
have also reverted all storage volumes back to the same contents as when
the state file was created.
=item B<save> I<domain-id> I<state-file> [I<--bypass-cache>]
[I<--xml> B<file>]
+[{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<restore> 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<snapshot> family of commands.
-=item B<save-image-define> I<file> I<xml>
+=item B<save-image-define> I<file> I<xml> [{I<--running> |
I<--paused>}]
Update the domain XML that will be used when I<file> is later
used in the B<restore> command. The I<xml> 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<restore> should use.
+
=item B<save-image-dumpxml> I<file> [I<--security-info>]
Extract the domain XML that was in effect at the time the saved state
file I<file> was created with the B<save> command. Using
I<--security-info> will also include security sensitive information.
-=item B<save-image-edit> I<file>
+=item B<save-image-edit> I<file> [{I<--running> | I<--paused>}]
Edit the XML configuration associated with a saved state file I<file>
created by the B<save> 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<restore> should use.
+
This is equivalent to:
virsh save-image-dumpxml state-file > state-file.xml
@@ -1681,14 +1709,22 @@ Output the snapshot XML for the domain's snapshot named
I<snapshot>.
Output the name of the parent snapshot for the given I<snapshot>, if any.
-=item B<snapshot-revert> I<domain> I<snapshot>
+=item B<snapshot-revert> I<domain> I<snapshot> [{I<--running> |
I<--paused>}]
Revert the given domain to the snapshot specified by I<snapshot>. 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<snapshot-delete> I<domain> I<snapshot> I<--children>
Delete the snapshot for the domain named I<snapshot>. If this snapshot
--
1.7.4.4