[libvirt] [PATCHv3 36/43] snapshot: add virsh domblklist command

Eric Blake eblake at redhat.com
Wed Aug 24 15:22:53 UTC 2011


This adds a convenience function to virsh that parses out block
information from the domain xml, making it much easier to see
what strings can be used in all other contexts that demand a
specific block name, especially when given the previous patch
that allows using either target or unique source name.

As an example on a domain with one disk and an empty cdrom drive:

Target     Source
-------------------------------------------
vda        /var/lib/libvirt/images/fedora_12.img
hdc        -

* tools/virsh.c (cmdDomblklist): New function.
* tools/virsh.pod (domblklist): Document it.
---
 tools/virsh.c   |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/virsh.pod |   10 +++++++
 2 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index d4581f7..fa80a52 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -1277,6 +1277,86 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
 }

 /*
+ * "domblklist" command
+ */
+static const vshCmdInfo info_domblklist[] = {
+    {"help", N_("list all domain blocks")},
+    {"desc", N_("Get the names of block devices for a domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domblklist[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"inactive", VSH_OT_BOOL, 0,
+     N_("get inactive rather than running configuration")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomblklist(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    bool ret = false;
+    int flags = 0;
+    char *xml = NULL;
+    xmlDocPtr xmldoc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    int ndisks;
+    xmlNodePtr *disks = NULL;
+    int i;
+
+    if (vshCommandOptBool(cmd, "inactive"))
+        flags |= VIR_DOMAIN_XML_INACTIVE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    xml = virDomainGetXMLDesc(dom, flags);
+    if (!xml)
+        goto cleanup;
+
+    xmldoc = virXMLParseStringCtxt(xml, "domain.xml", &ctxt);
+    if (!xmldoc)
+        goto cleanup;
+
+    ndisks = virXPathNodeSet("./devices/disk", ctxt, &disks);
+    if (ndisks < 0)
+        goto cleanup;
+
+    vshPrint(ctl, "%-10s %s\n", _("Target"), _("Source"));
+    vshPrint(ctl, "------------------------------------------------\n");
+
+    for (i = 0; i < ndisks; i++) {
+        char *target;
+        char *source;
+
+        ctxt->node = disks[i];
+        target = virXPathString("string(./target/@dev)", ctxt);
+        if (!target) {
+            vshError(ctl, "unable to query block list");
+            goto cleanup;
+        }
+        source = virXPathString("string(./source/@file"
+                                "|./source/@dev"
+                                "|./source/@dir"
+                                "|./source/@name)", ctxt);
+        vshPrint(ctl, "%-10s %s\n", target, source ? source : "-");
+        VIR_FREE(target);
+        VIR_FREE(source);
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(disks);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
  * "suspend" command
  */
 static const vshCmdInfo info_suspend[] = {
@@ -13015,6 +13095,7 @@ static const vshCmdDef domManagementCmds[] = {

 static const vshCmdDef domMonitoringCmds[] = {
     {"domblkinfo", cmdDomblkinfo, opts_domblkinfo, info_domblkinfo, 0},
+    {"domblklist", cmdDomblklist, opts_domblklist, info_domblklist, 0},
     {"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat, 0},
     {"domcontrol", cmdDomControl, opts_domcontrol, info_domcontrol, 0},
     {"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat, 0},
diff --git a/tools/virsh.pod b/tools/virsh.pod
index c37c9e4..b357330 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -447,6 +447,16 @@ Get block device size info for a domain.  A I<block-device> corresponds
 to a unique target name (<target dev='name'/>) or source file (<source
 file='name'/>) for one of the disk devices attached to I<domain>.

+=item B<domblklist> I<domain> [I<--inactive>]
+
+Print a table showing the names of all block devices associated with
+I<domain>, as well as the path to the source of each device.  If
+I<--inactive> is specified, query the block devices that will be used
+on the next boot, rather than those currently in use by a running
+domain.  Other contexts that require a block device name (such as
+I<domblkinfo> or I<snapshot-create> for disk snapshots) will accept
+either target or unique source names printed by this command.
+
 =item B<blockpull> I<domain> I<path> [I<bandwidth>]

 Populate a disk from its backing image. Once all data from its backing
-- 
1.7.4.4




More information about the libvir-list mailing list