On Sat, Sep 24, 2011 at 06:30:05PM -0600, Eric Blake wrote:
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.
---
tools/virsh.c | 83 +++++++++++++++++++++++++++++++++++++++++++++---------
tools/virsh.pod | 14 +++++----
2 files changed, 77 insertions(+), 20 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 035b209..7e7b65d 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -12987,7 +12987,7 @@ vshGetSnapshotParent(vshControl *ctl, virDomainSnapshotPtr
snapshot)
parent = virDomainSnapshotGetParent(snapshot, 0);
if (parent) {
/* API works, and virDomainSnapshotGetName will succeed */
- parent_name = vshStrdup(ctl, virDomainSnapshotGetName(snapshot));
+ parent_name = vshStrdup(ctl, virDomainSnapshotGetName(parent));
goto cleanup;
}
if (last_error->code == VIR_ERR_NO_DOMAIN_SNAPSHOT) {
That looks like a bug fix squashed in here instead of previous patch,
what am I missing ?
@@ -13032,6 +13032,7 @@ static const vshCmdOptDef
opts_snapshot_list[] = {
{"roots", VSH_OT_BOOL, 0, N_("list only snapshots without
parents")},
{"metadata", VSH_OT_BOOL, 0,
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}
};
@@ -13057,6 +13058,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
time_t creation_time_t;
char timestr[100];
struct tm time_info;
+ bool tree = vshCommandOptBool(cmd, "tree");
if (vshCommandOptBool(cmd, "parent")) {
if (vshCommandOptBool(cmd, "roots")) {
@@ -13064,8 +13066,18 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
_("--parent and --roots are mutually exlusive"));
return false;
}
+ if (tree) {
+ vshError(ctl, "%s",
+ _("--parent and --tree are mutually exlusive"));
+ return false;
+ }
parent_filter = 1;
} else if (vshCommandOptBool(cmd, "roots")) {
+ if (tree) {
+ vshError(ctl, "%s",
+ _("--roots and --tree are mutually exlusive"));
+ return false;
+ }
flags |= VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
}
@@ -13095,23 +13107,66 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
if (numsnaps < 0)
goto cleanup;
- if (parent_filter > 0)
- vshPrintExtra(ctl, " %-20s %-25s %-15s %s",
- _("Name"), _("Creation Time"),
_("State"), _("Parent"));
- else
- vshPrintExtra(ctl, " %-20s %-25s %s",
- _("Name"), _("Creation Time"),
_("State"));
- vshPrintExtra(ctl, "\n\
+ if (!tree) {
+ if (parent_filter > 0)
+ vshPrintExtra(ctl, " %-20s %-25s %-15s %s",
+ _("Name"), _("Creation Time"),
_("State"),
+ _("Parent"));
+ else
+ vshPrintExtra(ctl, " %-20s %-25s %s",
+ _("Name"), _("Creation Time"),
_("State"));
+ vshPrintExtra(ctl, "\n\
------------------------------------------------------------\n");
+ }
- if (numsnaps) {
- if (VIR_ALLOC_N(names, numsnaps) < 0)
- goto cleanup;
+ if (!numsnaps) {
+ ret = true;
+ goto cleanup;
+ }
- actual = virDomainSnapshotListNames(dom, names, numsnaps, flags);
- if (actual < 0)
- goto cleanup;
+ if (VIR_ALLOC_N(names, numsnaps) < 0)
+ 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);
for (i = 0; i < actual; i++) {
diff --git a/tools/virsh.pod b/tools/virsh.pod
index ddf7578..49aa42a 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1934,15 +1934,17 @@ except that it does some error checking.
The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment
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
-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; this option is not compatible with I<--parent>.
+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<--tree> is specified, the output will be in a tree format, listing
+just snapshot names. These three options are mutually exclusive.
If I<--metadata> is specified, the list will be filtered to just
snapshots that involve libvirt metadata, and thus would prevent
ACK, great improvement,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/