Down the road, I want to add virDomainSnapshotGetParent, and use
the new API rather than xml scraping; but this virsh command can
be implemented even without the new API.
* tools/virsh.c (cmdSnapshotParent): New command.
* tools/virsh.pod (snapshot-parent): Document it.
---
Adding this will make it a bit easier to track relationships between
snapshots, especially since 'virsh snapshot-list' covers everything
except the relationship.
tools/virsh.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 4 +++
2 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 1d660d0..ee08c01 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -12285,6 +12285,82 @@ cleanup:
}
/*
+ * "snapshot-parent" command
+ */
+static const vshCmdInfo info_snapshot_parent[] = {
+ {"help", N_("Get the name of the parent of the current
snapshot")},
+ {"desc", N_("Extract the snapshot's parent, if any")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_snapshot_parent[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or
uuid")},
+ {"snapshotname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot
name")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdSnapshotParent(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom = NULL;
+ bool ret = false;
+ const char *name = NULL;
+ virDomainSnapshotPtr snapshot = NULL;
+ char *xml = NULL;
+ char *parent = NULL;
+ xmlDocPtr xmldoc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto cleanup;
+
+ dom = vshCommandOptDomain(ctl, cmd, NULL);
+ if (dom == NULL)
+ goto cleanup;
+
+ if (vshCommandOptString(cmd, "snapshotname", &name) <= 0)
+ goto cleanup;
+
+ snapshot = virDomainSnapshotLookupByName(dom, name, 0);
+ if (snapshot == NULL)
+ goto cleanup;
+
+ xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
+ if (!xml)
+ goto cleanup;
+
+ xmldoc = xmlReadDoc((const xmlChar *) xml, "domainsnapshot.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xmldoc)
+ goto cleanup;
+ ctxt = xmlXPathNewContext(xmldoc);
+ if (!ctxt)
+ goto cleanup;
+
+ parent = virXPathString("string(/domainsnapshot/parent/name)", ctxt);
+ if (!parent)
+ goto cleanup;
+
+ vshPrint(ctl, "%s", parent);
+
+ ret = true;
+
+cleanup:
+ VIR_FREE(parent);
+ xmlXPathFreeContext(ctxt);
+ if (xmldoc)
+ xmlFreeDoc(xmldoc);
+ VIR_FREE(xml);
+ if (snapshot)
+ virDomainSnapshotFree(snapshot);
+ if (dom)
+ virDomainFree(dom);
+
+ return ret;
+}
+
+/*
* "snapshot-revert" command
*/
static const vshCmdInfo info_snapshot_revert[] = {
@@ -12754,6 +12830,8 @@ static const vshCmdDef snapshotCmds[] = {
info_snapshot_dumpxml, 0},
{"snapshot-list", cmdSnapshotList, opts_snapshot_list,
info_snapshot_list, 0},
+ {"snapshot-parent", cmdSnapshotParent, opts_snapshot_parent,
+ info_snapshot_parent, 0},
{"snapshot-revert", cmdDomainSnapshotRevert, opts_snapshot_revert,
info_snapshot_revert, 0},
{NULL, NULL, NULL, NULL, 0}
diff --git a/tools/virsh.pod b/tools/virsh.pod
index a6af1e6..1893c23 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1583,6 +1583,10 @@ List all of the available snapshots for the given domain.
Output the snapshot XML for the domain's snapshot named I<snapshot>.
+=item B<snapshot-parent> I<domain> I<snapshot>
+
+Output the name of the parent snapshot for the given I<snapshot>, if any.
+
=item B<snapshot-revert> I<domain> I<snapshot>
Revert the given domain to the snapshot specified by I<snapshot>. Be aware
--
1.7.4.4