char *historyfile; /* readline history file name */
bool useGetInfo; /* must use virDomainGetInfo, since
virDomainGetState is not supported */
+ bool useSnapshotGetXML; /* must use virDomainSnapshotGetXMLDesc, since
+ virDomainSnapshotGetParent is missing */
} __vshControl;
typedef struct vshCmdGrp {
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
disconnected = 0;
ctl->useGetInfo = false;
+ ctl->useSnapshotGetXML = false;
}
/* ---------------
ctl->name = vshStrdup(ctl, name);
ctl->useGetInfo = false;
+ ctl->useSnapshotGetXML = false;
ctl->readonly = ro;
ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault,
return ret;
}
+/* Helper function to get the name of a snapshot's parent. Caller
+ * must free the result. */
+static char *
+vshGetSnapshotParent(vshControl *ctl, virDomainSnapshotPtr snapshot)
+{
+ virDomainSnapshotPtr parent = NULL;
+ char *xml = NULL;
+ xmlDocPtr xmldoc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ char *parent_name = NULL;
+
+ /* Try new API, since it is faster. */
+ if (!ctl->useSnapshotGetXML) {
+ parent = virDomainSnapshotGetParent(snapshot, 0);
+ if (parent) {
+ /* API works, and virDomainSnapshotGetName will succeed */
+ parent_name = vshStrdup(ctl, virDomainSnapshotGetName(parent));
+ goto cleanup;
+ }
+ if (last_error->code == VIR_ERR_NO_DOMAIN_SNAPSHOT) {
+ /* API works, and we found a root with no parent */
+ goto cleanup;
+ }
+ /* API didn't work, fall back to XML scraping. */
+ ctl->useSnapshotGetXML = true;
+ }
+
+ xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
+ if (!xml)
+ goto cleanup;
+
+ xmldoc = virXMLParseStringCtxt(xml, _("(domain_snapshot)"), &ctxt);
+ if (!xmldoc)
+ goto cleanup;
+
+ parent_name = virXPathString("string(/domainsnapshot/parent/name)", ctxt);
+
+cleanup:
+ if (parent)
+ virDomainSnapshotFree(parent);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xmldoc);
+ VIR_FREE(xml);
+ return parent_name;
+}
+
/*
* "snapshot-list" command
*/
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;
if (snapshot == NULL)
goto cleanup;
- xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
- if (!xml)
- goto cleanup;
-
- xmldoc = virXMLParseStringCtxt(xml, _("(domain_snapshot)"), &ctxt);
- if (!xmldoc)
- goto cleanup;
-
- parent = virXPathString("string(/domainsnapshot/parent/name)", ctxt);
+ parent = vshGetSnapshotParent(ctl, snapshot);
if (!parent)
goto cleanup;
cleanup:
VIR_FREE(parent);
- xmlXPathFreeContext(ctxt);
- xmlFreeDoc(xmldoc);
- VIR_FREE(xml);
if (snapshot)
virDomainSnapshotFree(snapshot);
if (dom)