Iterating over one level of children requires parsing all snapshots
and their parents; a bit of code shuffling makes it pretty easy
to do this as well.
* tools/virsh.c (cmdSnapshotList): Add another fallback.
---
Applies anywhere after 2.5/4, but again, easiest to test against the
same version of libvirtd if applied before 3/4.
tools/virsh.c | 46 +++++++++++++++++++++++++++++++---------------
1 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 93e4528..232c9b8 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -13096,6 +13096,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
information needed, 1 for parent column */
int numsnaps;
char **names = NULL;
+ char **parents = NULL;
int actual = 0;
int i;
xmlDocPtr xml = NULL;
@@ -13112,6 +13113,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
const char *from = NULL;
virDomainSnapshotPtr start = NULL;
bool emulate_from = false;
+ bool descendants = false;
if (vshCommandOptString(cmd, "from", &from) < 0) {
vshError(ctl, _("invalid from argument '%s'"), from);
@@ -13155,25 +13157,27 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
if (from) {
+ descendants = vshCommandOptBool(cmd, "descendants");
start = virDomainSnapshotLookupByName(dom, from, 0);
if (!start)
goto cleanup;
- if (vshCommandOptBool(cmd, "descendants") || tree) {
+ if (descendants || tree) {
flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
}
numsnaps = virDomainSnapshotNumChildren(start, flags);
- /* XXX Is it worth emulating --from without --tree on older servers? */
- if (tree) {
- if (numsnaps >= 0) {
- numsnaps++;
- } else if (last_error->code == VIR_ERR_NO_SUPPORT) {
- /* We can emulate --tree --from. */
+ if (numsnaps < 0) {
+ /* XXX also want to emulate --descendants without --tree */
+ if ((!descendants || tree)
+ last_error->code == VIR_ERR_NO_SUPPORT) {
+ /* We can emulate --from. */
virFreeError(last_error);
last_error = NULL;
emulate_from = true;
flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
numsnaps = virDomainSnapshotNum(dom, flags);
}
+ } else if (tree) {
+ numsnaps++;
}
} else {
numsnaps = virDomainSnapshotNum(dom, flags);
@@ -13234,9 +13238,11 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
if (actual < 0)
goto cleanup;
- if (tree) {
- char indentBuf[INDENT_BUFLEN];
- char **parents = vshCalloc(ctl, sizeof(char *), actual);
+ if (!tree)
+ qsort(&names[0], actual, sizeof(char*), namesorter);
+
+ if (tree || emulate_from) {
+ parents = vshCalloc(ctl, sizeof(char *), actual);
for (i = (from && !emulate_from); i < actual; i++) {
/* free up memory from previous iterations of the loop */
if (snapshot)
@@ -13250,6 +13256,9 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
}
parents[i] = vshGetSnapshotParent(ctl, snapshot);
}
+ }
+ if (tree) {
+ char indentBuf[INDENT_BUFLEN];
for (i = 0 ; i < actual ; i++) {
memset(indentBuf, '\0', sizeof indentBuf);
if (emulate_from ? STREQ(names[i], from) : !parents[i])
@@ -13263,16 +13272,19 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
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);
+ if (emulate_from && descendants) {
+ /* XXX emulate --descendants as well */
+ goto cleanup;
+ }
for (i = 0; i < actual; i++) {
+ if (emulate_from && STRNEQ_NULLABLE(parents[i], from))
+ continue;
+
/* free up memory from previous iterations of the loop */
VIR_FREE(parent);
VIR_FREE(state);
@@ -13337,9 +13349,13 @@ cleanup:
xmlXPathFreeContext(ctxt);
xmlFreeDoc(xml);
VIR_FREE(doc);
- for (i = 0; i < actual; i++)
+ for (i = 0; i < actual; i++) {
VIR_FREE(names[i]);
+ if (parents)
+ VIR_FREE(parents[i]);
+ }
VIR_FREE(names);
+ VIR_FREE(parents);
if (dom)
virDomainFree(dom);
--
1.7.4.4