Emulating --from requires grabbing the entire list of snapshots
and their parents, and recursively iterating over the list from
the point of interest - but we already do that for --tree. This
turns on emulation for that situation.
* tools/virsh.c (cmdSnapshotList): Add fallback.
---
Can be applied anywhere after 2/4, but by inserting it before 3/4, you
can actually test it against the same version of libvirtd (instead of
having to run an older server with newer client).
I'm also looking at implementing the fallback even when not in --tree,
but that's a bit more complex.
tools/virsh.c | 24 +++++++++++++++++-------
1 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 778725c..95baca5 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -13111,6 +13111,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
bool tree = vshCommandOptBool(cmd, "tree");
const char *from = NULL;
virDomainSnapshotPtr start = NULL;
+ bool emulate_from = false;
if (vshCommandOptString(cmd, "from", &from) < 0) {
vshError(ctl, _("invalid from argument '%s'"), from);
@@ -13161,14 +13162,23 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
}
numsnaps = virDomainSnapshotNumChildren(start, flags);
- if (numsnaps >= 0 && tree)
- numsnaps++;
+ if (tree) {
+ if (numsnaps >= 0) {
+ numsnaps++;
+ } else if (last_error->code == VIR_ERR_NO_SUPPORT) {
+ /* We can emulate --tree --from. */
+ virFreeError(last_error);
+ last_error = NULL;
+ emulate_from = true;
+ flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
+ numsnaps = virDomainSnapshotNum(dom, flags);
+ }
+ }
} else {
numsnaps = virDomainSnapshotNum(dom, flags);
}
- /* Fall back to simulation if --roots was unsupported.
- * XXX Is it worth emulating --from on older servers? */
+ /* Fall back to simulation if --roots was unsupported. */
if (numsnaps < 0 && last_error->code == VIR_ERR_INVALID_ARG &&
!from &&
(flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) {
virFreeError(last_error);
@@ -13201,7 +13211,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
if (VIR_ALLOC_N(names, numsnaps) < 0)
goto cleanup;
- if (from) {
+ if (from && !emulate_from) {
/* When mixing --from and --tree, we want to start the tree at the
* given snapshot. Without --tree, only list the children. */
if (tree) {
@@ -13226,7 +13236,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
if (tree) {
char indentBuf[INDENT_BUFLEN];
char **parents = vshCalloc(ctl, sizeof(char *), actual);
- for (i = (from ? 1 : 0); i < actual; i++) {
+ for (i = (from && !emulate_from ? 1 : 0); i < actual; i++) {
/* free up memory from previous iterations of the loop */
if (snapshot)
virDomainSnapshotFree(snapshot);
@@ -13241,7 +13251,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
}
for (i = 0 ; i < actual ; i++) {
memset(indentBuf, '\0', sizeof indentBuf);
- if (parents[i] == NULL)
+ if (emulate_from ? STREQ(names[i], from) : parents[i] == NULL)
cmdNodeListDevicesPrint(ctl,
names,
parents,
--
1.7.4.4