提交 1cf0e3db 编写于 作者: E Eric Blake

snapshot: add virsh snapshot-list --tree

Reuse the tree listing of nodedev-list, coupled with the new helper
function to efficiently grab snapshot parent names, to produce
tree output for a snapshot hierarchy.  For example:

$ virsh snapshot-list dom --tree
root1
 |
  +- sibling1
  +- sibling2
  |   |
  |   +- grandchild
  |
  +- sibling3

root2
 |
  +- child

* tools/virsh.c (cmdSnapshotList): Add --tree.
* tools/virsh.pod (snapshot-list): Document it.
上级 d1be48f9
...@@ -13042,6 +13042,7 @@ static const vshCmdOptDef opts_snapshot_list[] = { ...@@ -13042,6 +13042,7 @@ static const vshCmdOptDef opts_snapshot_list[] = {
{"roots", VSH_OT_BOOL, 0, N_("list only snapshots without parents")}, {"roots", VSH_OT_BOOL, 0, N_("list only snapshots without parents")},
{"metadata", VSH_OT_BOOL, 0, {"metadata", VSH_OT_BOOL, 0,
N_("list only snapshots that have metadata that would prevent undefine")}, N_("list only snapshots that have metadata that would prevent undefine")},
{"tree", VSH_OT_BOOL, 0, N_("list snapshots in a tree")},
{NULL, 0, 0, NULL} {NULL, 0, 0, NULL}
}; };
...@@ -13067,6 +13068,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) ...@@ -13067,6 +13068,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
time_t creation_time_t; time_t creation_time_t;
char timestr[100]; char timestr[100];
struct tm time_info; struct tm time_info;
bool tree = vshCommandOptBool(cmd, "tree");
if (vshCommandOptBool(cmd, "parent")) { if (vshCommandOptBool(cmd, "parent")) {
if (vshCommandOptBool(cmd, "roots")) { if (vshCommandOptBool(cmd, "roots")) {
...@@ -13074,8 +13076,18 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) ...@@ -13074,8 +13076,18 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
_("--parent and --roots are mutually exlusive")); _("--parent and --roots are mutually exlusive"));
return false; return false;
} }
if (tree) {
vshError(ctl, "%s",
_("--parent and --tree are mutually exlusive"));
return false;
}
parent_filter = 1; parent_filter = 1;
} else if (vshCommandOptBool(cmd, "roots")) { } else if (vshCommandOptBool(cmd, "roots")) {
if (tree) {
vshError(ctl, "%s",
_("--roots and --tree are mutually exlusive"));
return false;
}
flags |= VIR_DOMAIN_SNAPSHOT_LIST_ROOTS; flags |= VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
} }
...@@ -13105,23 +13117,66 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) ...@@ -13105,23 +13117,66 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
if (numsnaps < 0) if (numsnaps < 0)
goto cleanup; goto cleanup;
if (parent_filter > 0) if (!tree) {
vshPrintExtra(ctl, " %-20s %-25s %-15s %s", if (parent_filter > 0)
_("Name"), _("Creation Time"), _("State"), _("Parent")); vshPrintExtra(ctl, " %-20s %-25s %-15s %s",
else _("Name"), _("Creation Time"), _("State"),
vshPrintExtra(ctl, " %-20s %-25s %s", _("Parent"));
_("Name"), _("Creation Time"), _("State")); else
vshPrintExtra(ctl, "\n\ vshPrintExtra(ctl, " %-20s %-25s %s",
_("Name"), _("Creation Time"), _("State"));
vshPrintExtra(ctl, "\n\
------------------------------------------------------------\n"); ------------------------------------------------------------\n");
}
if (numsnaps) { if (!numsnaps) {
if (VIR_ALLOC_N(names, numsnaps) < 0) ret = true;
goto cleanup; goto cleanup;
}
actual = virDomainSnapshotListNames(dom, names, numsnaps, flags); if (VIR_ALLOC_N(names, numsnaps) < 0)
if (actual < 0) goto cleanup;
goto cleanup;
actual = virDomainSnapshotListNames(dom, names, numsnaps, flags);
if (actual < 0)
goto cleanup;
if (tree) {
char indentBuf[INDENT_BUFLEN];
char **parents = vshMalloc(ctl, sizeof(char *) * actual);
for (i = 0; i < actual; i++) {
/* free up memory from previous iterations of the loop */
if (snapshot)
virDomainSnapshotFree(snapshot);
snapshot = virDomainSnapshotLookupByName(dom, names[i], 0);
if (!snapshot) {
while (--i >= 0)
VIR_FREE(parents[i]);
VIR_FREE(parents);
goto cleanup;
}
parents[i] = vshGetSnapshotParent(ctl, snapshot);
}
for (i = 0 ; i < actual ; i++) {
memset(indentBuf, '\0', sizeof indentBuf);
if (parents[i] == NULL)
cmdNodeListDevicesPrint(ctl,
names,
parents,
actual,
i,
i,
0,
0,
indentBuf);
}
for (i = 0 ; i < actual ; i++)
VIR_FREE(parents[i]);
VIR_FREE(parents);
ret = true;
goto cleanup;
} else {
qsort(&names[0], actual, sizeof(char*), namesorter); qsort(&names[0], actual, sizeof(char*), namesorter);
for (i = 0; i < actual; i++) { for (i = 0; i < actual; i++) {
......
...@@ -1955,15 +1955,17 @@ except that it does some error checking. ...@@ -1955,15 +1955,17 @@ except that it does some error checking.
The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment
variables, and defaults to C<vi>. variables, and defaults to C<vi>.
=item B<snapshot-list> I<domain> [{I<--parent> | I<--roots>}] [I<--metadata>] =item B<snapshot-list> I<domain> [{I<--parent> | I<--roots> | I<--tree>}]
[I<--metadata>]
List all of the available snapshots for the given domain. List all of the available snapshots for the given domain, defaulting
to show columns for the snapshot name, creation time, and domain state.
If I<--parent> is specified, add a column to the output table giving If I<--parent> is specified, add a column to the output table giving
the name of the parent of each snapshot. the name of the parent of each snapshot. If I<--roots> is specified,
the list will be filtered to just snapshots that have no parents.
If I<--roots> is specified, the list will be filtered to just snapshots If I<--tree> is specified, the output will be in a tree format, listing
that have no parents; this option is not compatible with I<--parent>. just snapshot names. These three options are mutually exclusive.
If I<--metadata> is specified, the list will be filtered to just If I<--metadata> is specified, the list will be filtered to just
snapshots that involve libvirt metadata, and thus would prevent snapshots that involve libvirt metadata, and thus would prevent
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册