[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/4] snapshot: add 'virsh snapshot-info'



Expose the recent API additions in virsh.  Borrows ideas from 'dominfo'
for the general type of information to display.  Output looks like:

$ tools/virsh snapshot-info fedora-local tmp
Name:           tmp
Domain:         fedora-local
Current:        no
State:          disk-snapshot
Parent:         -
Children:       1
Descendants:    2
Metadata:       yes

possibly with fewer lines when talking to older servers.

* tools/virsh.c (cmdSnapshotInfo): New command.
* tools/virsh.pod (snapshot-info): Document it.

---
 tools/virsh.c   |  125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/virsh.pod |    5 ++
 2 files changed, 130 insertions(+), 0 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index ffe6ed2..6a85338 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -16601,6 +16601,129 @@ cleanup:
 }

 /*
+ * "snapshot-info" command
+ */
+static const vshCmdInfo info_snapshot_info[] = {
+    {"help", N_("snapshot information")},
+    {"desc", N_("Returns basic information about a snapshot.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_snapshot_info[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"snapshotname", VSH_OT_DATA, 0, N_("snapshot name")},
+    {"current", VSH_OT_BOOL, 0, N_("info on current snapshot")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    virDomainSnapshotPtr snapshot = NULL;
+    const char *name;
+    char *doc = NULL;
+    char *tmp;
+    char *parent = NULL;
+    bool ret = false;
+    int count;
+    unsigned int flags;
+    int current;
+    int metadata;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    dom = vshCommandOptDomain(ctl, cmd, NULL);
+    if (dom == NULL)
+        return false;
+
+    if (vshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
+                          &snapshot, &name) < 0)
+        goto cleanup;
+
+    vshPrint(ctl, "%-15s %s\n", _("Name:"), name);
+    vshPrint(ctl, "%-15s %s\n", _("Domain:"), virDomainGetName(dom));
+
+    /* Determine if snapshot is current; this is useful enough that we
+     * attempt a fallback.  */
+    current = virDomainSnapshotIsCurrent(snapshot, 0);
+    if (current < 0) {
+        virDomainSnapshotPtr other = virDomainSnapshotCurrent(dom, 0);
+
+        virResetLastError();
+        current = 0;
+        if (other) {
+            if (STREQ(name, virDomainSnapshotGetName(other)))
+                current = 1;
+            virDomainSnapshotFree(other);
+        }
+    }
+    vshPrint(ctl, "%-15s %s\n", _("Current:"),
+             current > 0 ? _("yes") : _("no"));
+
+    /* Get the XML configuration of the snapshot to determine the
+     * state of the machine at the time of the snapshot.  */
+    doc = virDomainSnapshotGetXMLDesc(snapshot, 0);
+    if (!doc)
+        goto cleanup;
+
+    tmp = strstr(doc, "<state>");
+    if (!tmp) {
+        vshError(ctl, "%s",
+                 _("unexpected problem reading snapshot xml"));
+        goto cleanup;
+    }
+    tmp += strlen("<state>");
+    vshPrint(ctl, "%-15s %.*s\n", _("State:"),
+             (int) (strchr(tmp, '<') - tmp), tmp);
+
+    if (vshGetSnapshotParent(ctl, snapshot, &parent) < 0)
+        goto cleanup;
+    vshPrint(ctl, "%-15s %s\n", _("Parent:"), parent ? parent : "-");
+
+    /* Children, Descendants.  After this point, the fallback to
+     * compute children is too expensive, so we gracefully quit if the
+     * APIs don't exist.  */
+    if (ctl->useSnapshotOld) {
+        ret = true;
+        goto cleanup;
+    }
+    flags = 0;
+    count = virDomainSnapshotNumChildren(snapshot, 0);
+    if (count < 0)
+        goto cleanup;
+    vshPrint(ctl, "%-15s %d\n", _("Children:"), count);
+    flags = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
+    count = virDomainSnapshotNumChildren(snapshot, flags);
+    if (count < 0)
+        goto cleanup;
+    vshPrint(ctl, "%-15s %d\n", _("Descendants:"), count);
+
+    /* Metadata; the fallback here relies on the fact that metadata
+     * used to have an all-or-nothing effect on snapshot count.  */
+    metadata = virDomainSnapshotHasMetadata(snapshot, 0);
+    if (metadata < 0) {
+        virResetLastError();
+        count = virDomainSnapshotNum(dom,
+                                     VIR_DOMAIN_SNAPSHOT_LIST_METADATA);
+        metadata = count != 0;
+    }
+    vshPrint(ctl, "%-15s %s\n", _("Metadata:"),
+             metadata > 0 ? _("yes") : _("no"));
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(doc);
+    VIR_FREE(parent);
+    if (snapshot)
+        virDomainSnapshotFree(snapshot);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
  * "snapshot-list" command
  */
 static const vshCmdInfo info_snapshot_list[] = {
@@ -17702,6 +17825,8 @@ static const vshCmdDef snapshotCmds[] = {
      info_snapshot_dumpxml, 0},
     {"snapshot-edit", cmdSnapshotEdit, opts_snapshot_edit,
      info_snapshot_edit, 0},
+    {"snapshot-info", cmdSnapshotInfo, opts_snapshot_info,
+     info_snapshot_info, 0},
     {"snapshot-list", cmdSnapshotList, opts_snapshot_list,
      info_snapshot_list, 0},
     {"snapshot-parent", cmdSnapshotParent, opts_snapshot_parent,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index ef71717..6553825 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2504,6 +2504,11 @@ a snapshot name must be done with care, since the contents of some
 snapshots, such as internal snapshots within a single qcow2 file, are
 accessible only from the original name.

+=item B<snapshot-info> I<domain> {I<snapshot> | I<--current>}
+
+Output basic information about a named <snapshot>, or the current snapshot
+with I<--current>.
+
 =item B<snapshot-list> I<domain> [{I<--parent> | I<--roots> | I<--tree>}]
 [{[I<--from>] B<snapshot> | I<--current>} [I<--descendants>]]
 [I<--metadata>] [I<--leaves>]
-- 
1.7.7.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]