[libvirt] [PATCHv2 4/4] snapshot: expose location through virsh snapshot-info

Eric Blake eblake at redhat.com
Wed Nov 14 23:36:51 UTC 2012


Now that we can filter on this information, we should also make
it easy to get at.

* tools/virsh-snapshot.c (cmdSnapshotInfo): Add another output
row, and switch to XPath queries rather than strstr.
---
 tools/virsh-snapshot.c | 57 +++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 49 insertions(+), 8 deletions(-)

diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c
index 7cd2966..36f5b46 100644
--- a/tools/virsh-snapshot.c
+++ b/tools/virsh-snapshot.c
@@ -797,7 +797,10 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd)
     virDomainSnapshotPtr snapshot = NULL;
     const char *name;
     char *doc = NULL;
-    char *tmp;
+    xmlDocPtr xmldoc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    char *state = NULL;
+    int external;
     char *parent = NULL;
     bool ret = false;
     int count;
@@ -839,18 +842,48 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd)
     if (!doc)
         goto cleanup;

-    tmp = strstr(doc, "<state>");
-    if (!tmp) {
+    xmldoc = virXMLParseStringCtxt(doc, _("(domain_snapshot)"), &ctxt);
+    if (!xmldoc)
+        goto cleanup;
+
+    state = virXPathString("string(/domainsnapshot/state)", ctxt);
+    if (!state) {
         vshError(ctl, "%s",
                  _("unexpected problem reading snapshot xml"));
         goto cleanup;
     }
-    tmp += strlen("<state>");
-    vshPrint(ctl, "%-15s %.*s\n", _("State:"),
-             (int) (strchr(tmp, '<') - tmp), tmp);
+    vshPrint(ctl, "%-15s %s\n", _("State:"), state);
+
+    /* In addition to state, location is useful.  If the snapshot has
+     * a <memory> element, then the existence of snapshot='external'
+     * prior to <domain> is the deciding factor; for snapshots
+     * created prior to 1.0.1, a state of disk-only is the only
+     * external snapshot.  */
+    switch (virXPathBoolean("boolean(/domainsnapshot/memory)", ctxt)) {
+    case 1:
+        external = virXPathBoolean("boolean(/domainsnapshot/memory/@snapshot=external "
+                                   "| /domainsnapshot/disks/disk/@snapshot=external)",
+                                   ctxt);
+        break;
+    case 0:
+        external = STREQ(state, "disk-snapshot");
+        break;
+    default:
+        external = -1;
+        break;

-    if (vshGetSnapshotParent(ctl, snapshot, &parent) < 0)
+    }
+    if (external < 0) {
+        vshError(ctl, "%s",
+                 _("unexpected problem reading snapshot xml"));
         goto cleanup;
+    }
+    vshPrint(ctl, "%-15s %s\n", _("Location:"),
+             external ? _("external") : _("internal"));
+
+    /* Since we already have the XML, there's no need to call
+     * virDomainSnapshotGetParent */
+    parent = virXPathString("string(/domainsnapshot/parent/name)", ctxt);
     vshPrint(ctl, "%-15s %s\n", _("Parent:"), parent ? parent : "-");

     /* Children, Descendants.  After this point, the fallback to
@@ -862,8 +895,13 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd)
     }
     flags = 0;
     count = virDomainSnapshotNumChildren(snapshot, flags);
-    if (count < 0)
+    if (count < 0) {
+        if (last_error->code == VIR_ERR_NO_SUPPORT) {
+            vshResetLibvirtError();
+            ret = true;
+        }
         goto cleanup;
+    }
     vshPrint(ctl, "%-15s %d\n", _("Children:"), count);
     flags = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
     count = virDomainSnapshotNumChildren(snapshot, flags);
@@ -886,6 +924,9 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd)
     ret = true;

 cleanup:
+    VIR_FREE(state);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(xmldoc);
     VIR_FREE(doc);
     VIR_FREE(parent);
     if (snapshot)
-- 
1.7.11.7




More information about the libvir-list mailing list