[libvirt] [PATCH 04/13] virsh: Split cmds of storage volume group from virsh.c

Osier Yang jyang at redhat.com
Tue Jul 24 09:18:25 UTC 2012


This splits commands of storage volume group into virsh-volume.c,
The helpers not for common use are moved too. Standard copyright
is added for the new file.

* tools/virsh.c:
  Remove commands for storage storage volume and a few helpers.
  (vshCommandOptVol, vshCommandOptVolBy).

* tools/virsh-volume.c:
  New file, filled with commands of storage volume group and its
  helpers.
---
 tools/virsh-volume.c | 1440 +++++++++++++++++++++++++++++++++++++++++
 tools/virsh.c        | 1746 +++++---------------------------------------------
 2 files changed, 1595 insertions(+), 1591 deletions(-)
 create mode 100644 tools/virsh-volume.c

diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c
new file mode 100644
index 0000000..6fb721e
--- /dev/null
+++ b/tools/virsh-volume.c
@@ -0,0 +1,1440 @@
+/*
+ * virsh-volume.c: Commands to manage storage volume
+ *
+ * Copyright (C) 2005, 2007-2012 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *  Daniel Veillard <veillard at redhat.com>
+ *  Karel Zak <kzak at redhat.com>
+ *  Daniel P. Berrange <berrange at redhat.com>
+ *
+ */
+
+/* default is lookup by Name and UUID */
+#define vshCommandOptVol(_ctl, _cmd, _optname, _pooloptname, _name)   \
+    vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name,     \
+                           VSH_BYUUID|VSH_BYNAME)
+
+static virStorageVolPtr
+vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
+                   const char *optname,
+                   const char *pooloptname,
+                   const char **name, int flag)
+{
+    virStorageVolPtr vol = NULL;
+    virStoragePoolPtr pool = NULL;
+    const char *n = NULL, *p = NULL;
+
+    if (vshCommandOptString(cmd, optname, &n) <= 0)
+        return NULL;
+
+    if (pooloptname != NULL && vshCommandOptString(cmd, pooloptname, &p) < 0) {
+        vshError(ctl, "%s", _("missing option"));
+        return NULL;
+    }
+
+    if (p)
+        pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flag);
+
+    vshDebug(ctl, VSH_ERR_DEBUG, "%s: found option <%s>: %s\n",
+             cmd->def->name, optname, n);
+
+    if (name)
+        *name = n;
+
+    /* try it by name */
+    if (pool && (flag & VSH_BYNAME)) {
+        vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol name\n",
+                 cmd->def->name, optname);
+        vol = virStorageVolLookupByName(pool, n);
+    }
+    /* try it by key */
+    if (vol == NULL && (flag & VSH_BYUUID)) {
+        vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol key\n",
+                 cmd->def->name, optname);
+        vol = virStorageVolLookupByKey(ctl->conn, n);
+    }
+    /* try it by path */
+    if (vol == NULL && (flag & VSH_BYUUID)) {
+        vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol path\n",
+                 cmd->def->name, optname);
+        vol = virStorageVolLookupByPath(ctl->conn, n);
+    }
+
+    if (!vol) {
+        if (pool)
+            vshError(ctl, _("failed to get vol '%s'"), n);
+        else
+            vshError(ctl, _("failed to get vol '%s', specifying --%s "
+                            "might help"), n, pooloptname);
+    }
+
+    if (pool)
+        virStoragePoolFree(pool);
+
+    return vol;
+}
+
+/*
+ * "vol-create-as" command
+ */
+static const vshCmdInfo info_vol_create_as[] = {
+    {"help", N_("create a volume from a set of args")},
+    {"desc", N_("Create a vol.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_create_as[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
+    {"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the volume")},
+    {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ,
+     N_("size of the vol, as scaled integer (default bytes)")},
+    {"allocation", VSH_OT_STRING, 0,
+     N_("initial allocation size, as scaled integer (default bytes)")},
+    {"format", VSH_OT_STRING, 0,
+     N_("file format type raw,bochs,qcow,qcow2,qed,vmdk")},
+    {"backing-vol", VSH_OT_STRING, 0,
+     N_("the backing volume if taking a snapshot")},
+    {"backing-vol-format", VSH_OT_STRING, 0,
+     N_("format of backing volume if taking a snapshot")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+vshVolSize(const char *data, unsigned long long *val)
+{
+    char *end;
+    if (virStrToLong_ull(data, &end, 10, val) < 0)
+        return -1;
+    return virScaleInteger(val, end, 1, ULLONG_MAX);
+}
+
+static bool
+cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr pool;
+    virStorageVolPtr vol;
+    char *xml;
+    const char *name, *capacityStr = NULL, *allocationStr = NULL, *format = NULL;
+    const char *snapshotStrVol = NULL, *snapshotStrFormat = NULL;
+    unsigned long long capacity, allocation = 0;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                     VSH_BYNAME)))
+        return false;
+
+    if (vshCommandOptString(cmd, "name", &name) <= 0)
+        goto cleanup;
+
+    if (vshCommandOptString(cmd, "capacity", &capacityStr) <= 0)
+        goto cleanup;
+
+    if (vshVolSize(capacityStr, &capacity) < 0) {
+        vshError(ctl, _("Malformed size %s"), capacityStr);
+        goto cleanup;
+    }
+
+    if (vshCommandOptString(cmd, "allocation", &allocationStr) > 0 &&
+        vshVolSize(allocationStr, &allocation) < 0) {
+        vshError(ctl, _("Malformed size %s"), allocationStr);
+        goto cleanup;
+    }
+
+    if (vshCommandOptString(cmd, "format", &format) < 0 ||
+        vshCommandOptString(cmd, "backing-vol", &snapshotStrVol) < 0 ||
+        vshCommandOptString(cmd, "backing-vol-format",
+                            &snapshotStrFormat) < 0) {
+        vshError(ctl, "%s", _("missing argument"));
+        goto cleanup;
+    }
+
+
+    virBufferAddLit(&buf, "<volume>\n");
+    virBufferAsprintf(&buf, "  <name>%s</name>\n", name);
+    virBufferAsprintf(&buf, "  <capacity>%llu</capacity>\n", capacity);
+    if (allocationStr)
+        virBufferAsprintf(&buf, "  <allocation>%llu</allocation>\n", allocation);
+
+    if (format) {
+        virBufferAddLit(&buf, "  <target>\n");
+        virBufferAsprintf(&buf, "    <format type='%s'/>\n",format);
+        virBufferAddLit(&buf, "  </target>\n");
+    }
+
+    /* Convert the snapshot parameters into backingStore XML */
+    if (snapshotStrVol) {
+        /* Lookup snapshot backing volume.  Try the backing-vol
+         *  parameter as a name */
+        vshDebug(ctl, VSH_ERR_DEBUG,
+                 "%s: Look up backing store volume '%s' as name\n",
+                 cmd->def->name, snapshotStrVol);
+        virStorageVolPtr snapVol = virStorageVolLookupByName(pool, snapshotStrVol);
+        if (snapVol)
+                vshDebug(ctl, VSH_ERR_DEBUG,
+                         "%s: Backing store volume found using '%s' as name\n",
+                         cmd->def->name, snapshotStrVol);
+
+        if (snapVol == NULL) {
+            /* Snapshot backing volume not found by name.  Try the
+             *  backing-vol parameter as a key */
+            vshDebug(ctl, VSH_ERR_DEBUG,
+                     "%s: Look up backing store volume '%s' as key\n",
+                     cmd->def->name, snapshotStrVol);
+            snapVol = virStorageVolLookupByKey(ctl->conn, snapshotStrVol);
+            if (snapVol)
+                vshDebug(ctl, VSH_ERR_DEBUG,
+                         "%s: Backing store volume found using '%s' as key\n",
+                         cmd->def->name, snapshotStrVol);
+        }
+        if (snapVol == NULL) {
+            /* Snapshot backing volume not found by key.  Try the
+             *  backing-vol parameter as a path */
+            vshDebug(ctl, VSH_ERR_DEBUG,
+                     "%s: Look up backing store volume '%s' as path\n",
+                     cmd->def->name, snapshotStrVol);
+            snapVol = virStorageVolLookupByPath(ctl->conn, snapshotStrVol);
+            if (snapVol)
+                vshDebug(ctl, VSH_ERR_DEBUG,
+                         "%s: Backing store volume found using '%s' as path\n",
+                         cmd->def->name, snapshotStrVol);
+        }
+        if (snapVol == NULL) {
+            vshError(ctl, _("failed to get vol '%s'"), snapshotStrVol);
+            goto cleanup;
+        }
+
+        char *snapshotStrVolPath;
+        if ((snapshotStrVolPath = virStorageVolGetPath(snapVol)) == NULL) {
+            virStorageVolFree(snapVol);
+            goto cleanup;
+        }
+
+        /* Create XML for the backing store */
+        virBufferAddLit(&buf, "  <backingStore>\n");
+        virBufferAsprintf(&buf, "    <path>%s</path>\n",snapshotStrVolPath);
+        if (snapshotStrFormat)
+            virBufferAsprintf(&buf, "    <format type='%s'/>\n",snapshotStrFormat);
+        virBufferAddLit(&buf, "  </backingStore>\n");
+
+        /* Cleanup snapshot allocations */
+        VIR_FREE(snapshotStrVolPath);
+        virStorageVolFree(snapVol);
+    }
+
+    virBufferAddLit(&buf, "</volume>\n");
+
+    if (virBufferError(&buf)) {
+        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+        goto cleanup;
+    }
+    xml = virBufferContentAndReset(&buf);
+    vol = virStorageVolCreateXML(pool, xml, 0);
+    VIR_FREE(xml);
+    virStoragePoolFree(pool);
+
+    if (vol != NULL) {
+        vshPrint(ctl, _("Vol %s created\n"), name);
+        virStorageVolFree(vol);
+        return true;
+    } else {
+        vshError(ctl, _("Failed to create vol %s"), name);
+        return false;
+    }
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    virStoragePoolFree(pool);
+    return false;
+}
+
+/*
+ * "vol-create" command
+ */
+static const vshCmdInfo info_vol_create[] = {
+    {"help", N_("create a vol from an XML file")},
+    {"desc", N_("Create a vol.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_create[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolCreate(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr pool;
+    virStorageVolPtr vol;
+    const char *from = NULL;
+    bool ret = true;
+    char *buffer;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                           VSH_BYNAME)))
+        return false;
+
+    if (vshCommandOptString(cmd, "file", &from) <= 0) {
+        virStoragePoolFree(pool);
+        return false;
+    }
+
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
+        virshReportError(ctl);
+        virStoragePoolFree(pool);
+        return false;
+    }
+
+    vol = virStorageVolCreateXML(pool, buffer, 0);
+    VIR_FREE(buffer);
+    virStoragePoolFree(pool);
+
+    if (vol != NULL) {
+        vshPrint(ctl, _("Vol %s created from %s\n"),
+                 virStorageVolGetName(vol), from);
+        virStorageVolFree(vol);
+    } else {
+        vshError(ctl, _("Failed to create vol from %s"), from);
+        ret = false;
+    }
+    return ret;
+}
+
+/*
+ * "vol-create-from" command
+ */
+static const vshCmdInfo info_vol_create_from[] = {
+    {"help", N_("create a vol, using another volume as input")},
+    {"desc", N_("Create a vol from an existing volume.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_create_from[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("input vol name or key")},
+    {"inputpool", VSH_OT_STRING, 0, N_("pool name or uuid of the input volume's pool")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr pool = NULL;
+    virStorageVolPtr newvol = NULL, inputvol = NULL;
+    const char *from = NULL;
+    bool ret = false;
+    char *buffer = NULL;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        goto cleanup;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+        goto cleanup;
+
+    if (vshCommandOptString(cmd, "file", &from) <= 0) {
+        goto cleanup;
+    }
+
+    if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
+        goto cleanup;
+
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
+        virshReportError(ctl);
+        goto cleanup;
+    }
+
+    newvol = virStorageVolCreateXMLFrom(pool, buffer, inputvol, 0);
+
+    if (newvol != NULL) {
+        vshPrint(ctl, _("Vol %s created from input vol %s\n"),
+                 virStorageVolGetName(newvol), virStorageVolGetName(inputvol));
+    } else {
+        vshError(ctl, _("Failed to create vol from %s"), from);
+        goto cleanup;
+    }
+
+    ret = true;
+cleanup:
+    VIR_FREE(buffer);
+    if (pool)
+        virStoragePoolFree(pool);
+    if (inputvol)
+        virStorageVolFree(inputvol);
+    if (newvol)
+        virStorageVolFree(newvol);
+    return ret;
+}
+
+static xmlChar *
+makeCloneXML(const char *origxml, const char *newname)
+{
+
+    xmlDocPtr doc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    xmlChar *newxml = NULL;
+    int size;
+
+    doc = virXMLParseStringCtxt(origxml, _("(volume_definition)"), &ctxt);
+    if (!doc)
+        goto cleanup;
+
+    obj = xmlXPathEval(BAD_CAST "/volume/name", ctxt);
+    if (obj == NULL || obj->nodesetval == NULL ||
+        obj->nodesetval->nodeTab == NULL)
+        goto cleanup;
+
+    xmlNodeSetContent(obj->nodesetval->nodeTab[0], (const xmlChar *)newname);
+    xmlDocDumpMemory(doc, &newxml, &size);
+
+cleanup:
+    xmlXPathFreeObject(obj);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(doc);
+    return newxml;
+}
+
+/*
+ * "vol-clone" command
+ */
+static const vshCmdInfo info_vol_clone[] = {
+    {"help", N_("clone a volume.")},
+    {"desc", N_("Clone an existing volume.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_clone[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("orig vol name or key")},
+    {"newname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("clone name")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolClone(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr origpool = NULL;
+    virStorageVolPtr origvol = NULL, newvol = NULL;
+    const char *name = NULL;
+    char *origxml = NULL;
+    xmlChar *newxml = NULL;
+    bool ret = false;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        goto cleanup;
+
+    if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        goto cleanup;
+
+    origpool = virStoragePoolLookupByVolume(origvol);
+    if (!origpool) {
+        vshError(ctl, "%s", _("failed to get parent pool"));
+        goto cleanup;
+    }
+
+    if (vshCommandOptString(cmd, "newname", &name) <= 0)
+        goto cleanup;
+
+    origxml = virStorageVolGetXMLDesc(origvol, 0);
+    if (!origxml)
+        goto cleanup;
+
+    newxml = makeCloneXML(origxml, name);
+    if (!newxml) {
+        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+        goto cleanup;
+    }
+
+    newvol = virStorageVolCreateXMLFrom(origpool, (char *) newxml, origvol, 0);
+
+    if (newvol != NULL) {
+        vshPrint(ctl, _("Vol %s cloned from %s\n"),
+                 virStorageVolGetName(newvol), virStorageVolGetName(origvol));
+    } else {
+        vshError(ctl, _("Failed to clone vol from %s"),
+                 virStorageVolGetName(origvol));
+        goto cleanup;
+    }
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(origxml);
+    xmlFree(newxml);
+    if (origvol)
+        virStorageVolFree(origvol);
+    if (newvol)
+        virStorageVolFree(newvol);
+    if (origpool)
+        virStoragePoolFree(origpool);
+    return ret;
+}
+
+/*
+ * "vol-upload" command
+ */
+static const vshCmdInfo info_vol_upload[] = {
+    {"help", N_("upload a file into a volume")},
+    {"desc", N_("Upload a file into a volume")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_upload[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {"offset", VSH_OT_INT, 0, N_("volume offset to upload to") },
+    {"length", VSH_OT_INT, 0, N_("amount of data to upload") },
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolUploadSource(virStreamPtr st ATTRIBUTE_UNUSED,
+                   char *bytes, size_t nbytes, void *opaque)
+{
+    int *fd = opaque;
+
+    return saferead(*fd, bytes, nbytes);
+}
+
+static bool
+cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
+{
+    const char *file = NULL;
+    virStorageVolPtr vol = NULL;
+    bool ret = false;
+    int fd = -1;
+    virStreamPtr st = NULL;
+    const char *name = NULL;
+    unsigned long long offset = 0, length = 0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        goto cleanup;
+
+    if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
+        vshError(ctl, _("Unable to parse integer"));
+        return false;
+    }
+
+    if (vshCommandOptULongLong(cmd, "length", &length) < 0) {
+        vshError(ctl, _("Unable to parse integer"));
+        return false;
+    }
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
+        return false;
+    }
+
+    if (vshCommandOptString(cmd, "file", &file) < 0) {
+        vshError(ctl, _("file must not be empty"));
+        goto cleanup;
+    }
+
+    if ((fd = open(file, O_RDONLY)) < 0) {
+        vshError(ctl, _("cannot read %s"), file);
+        goto cleanup;
+    }
+
+    st = virStreamNew(ctl->conn, 0);
+    if (virStorageVolUpload(vol, st, offset, length, 0) < 0) {
+        vshError(ctl, _("cannot upload to volume %s"), name);
+        goto cleanup;
+    }
+
+    if (virStreamSendAll(st, cmdVolUploadSource, &fd) < 0) {
+        vshError(ctl, _("cannot send data to volume %s"), name);
+        goto cleanup;
+    }
+
+    if (VIR_CLOSE(fd) < 0) {
+        vshError(ctl, _("cannot close file %s"), file);
+        virStreamAbort(st);
+        goto cleanup;
+    }
+
+    if (virStreamFinish(st) < 0) {
+        vshError(ctl, _("cannot close volume %s"), name);
+        goto cleanup;
+    }
+
+    ret = true;
+
+cleanup:
+    if (vol)
+        virStorageVolFree(vol);
+    if (st)
+        virStreamFree(st);
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+/*
+ * "vol-download" command
+ */
+static const vshCmdInfo info_vol_download[] = {
+    {"help", N_("Download a volume to a file")},
+    {"desc", N_("Download a volume to a file")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_download[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {"offset", VSH_OT_INT, 0, N_("volume offset to download from") },
+    {"length", VSH_OT_INT, 0, N_("amount of data to download") },
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
+{
+    const char *file = NULL;
+    virStorageVolPtr vol = NULL;
+    bool ret = false;
+    int fd = -1;
+    virStreamPtr st = NULL;
+    const char *name = NULL;
+    unsigned long long offset = 0, length = 0;
+    bool created = false;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
+        vshError(ctl, _("Unable to parse integer"));
+        return false;
+    }
+
+    if (vshCommandOptULongLong(cmd, "length", &length) < 0) {
+        vshError(ctl, _("Unable to parse integer"));
+        return false;
+    }
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
+        return false;
+
+    if (vshCommandOptString(cmd, "file", &file) < 0) {
+        vshError(ctl, _("file must not be empty"));
+        goto cleanup;
+    }
+
+    if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) {
+        if (errno != EEXIST ||
+            (fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) {
+            vshError(ctl, _("cannot create %s"), file);
+            goto cleanup;
+        }
+    } else {
+        created = true;
+    }
+
+    st = virStreamNew(ctl->conn, 0);
+    if (virStorageVolDownload(vol, st, offset, length, 0) < 0) {
+        vshError(ctl, _("cannot download from volume %s"), name);
+        goto cleanup;
+    }
+
+    if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) {
+        vshError(ctl, _("cannot receive data from volume %s"), name);
+        goto cleanup;
+    }
+
+    if (VIR_CLOSE(fd) < 0) {
+        vshError(ctl, _("cannot close file %s"), file);
+        virStreamAbort(st);
+        goto cleanup;
+    }
+
+    if (virStreamFinish(st) < 0) {
+        vshError(ctl, _("cannot close volume %s"), name);
+        goto cleanup;
+    }
+
+    ret = true;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    if (!ret && created)
+        unlink(file);
+    if (vol)
+        virStorageVolFree(vol);
+    if (st)
+        virStreamFree(st);
+    return ret;
+}
+
+/*
+ * "vol-delete" command
+ */
+static const vshCmdInfo info_vol_delete[] = {
+    {"help", N_("delete a vol")},
+    {"desc", N_("Delete a given vol.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_delete[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolDelete(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+    bool ret = true;
+    const char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
+        return false;
+    }
+
+    if (virStorageVolDelete(vol, 0) == 0) {
+        vshPrint(ctl, _("Vol %s deleted\n"), name);
+    } else {
+        vshError(ctl, _("Failed to delete vol %s"), name);
+        ret = false;
+    }
+
+    virStorageVolFree(vol);
+    return ret;
+}
+
+/*
+ * "vol-wipe" command
+ */
+static const vshCmdInfo info_vol_wipe[] = {
+    {"help", N_("wipe a vol")},
+    {"desc", N_("Ensure data previously on a volume is not accessible to future reads")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_wipe[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {"algorithm", VSH_OT_STRING, 0, N_("perform selected wiping algorithm")},
+    {NULL, 0, 0, NULL}
+};
+
+VIR_ENUM_DECL(virStorageVolWipeAlgorithm)
+VIR_ENUM_IMPL(virStorageVolWipeAlgorithm, VIR_STORAGE_VOL_WIPE_ALG_LAST,
+              "zero", "nnsa", "dod", "bsi", "gutmann", "schneier",
+              "pfitzner7", "pfitzner33", "random");
+
+static bool
+cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+    bool ret = false;
+    const char *name;
+    const char *algorithm_str = NULL;
+    int algorithm = VIR_STORAGE_VOL_WIPE_ALG_ZERO;
+    int funcRet;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
+        return false;
+    }
+
+    if (vshCommandOptString(cmd, "algorithm", &algorithm_str) < 0) {
+        vshError(ctl, "%s", _("missing argument"));
+        goto out;
+    }
+
+    if (algorithm_str &&
+        (algorithm = virStorageVolWipeAlgorithmTypeFromString(algorithm_str)) < 0) {
+        vshError(ctl, _("Unsupported algorithm '%s'"), algorithm_str);
+        goto out;
+    }
+
+    if ((funcRet = virStorageVolWipePattern(vol, algorithm, 0)) < 0) {
+        if (last_error->code == VIR_ERR_NO_SUPPORT &&
+            algorithm == VIR_STORAGE_VOL_WIPE_ALG_ZERO)
+            funcRet = virStorageVolWipe(vol, 0);
+    }
+
+    if (funcRet < 0) {
+        vshError(ctl, _("Failed to wipe vol %s"), name);
+        goto out;
+    }
+
+    vshPrint(ctl, _("Vol %s wiped\n"), name);
+    ret = true;
+out:
+    virStorageVolFree(vol);
+    return ret;
+}
+
+/*
+ * "vol-info" command
+ */
+static const vshCmdInfo info_vol_info[] = {
+    {"help", N_("storage vol information")},
+    {"desc", N_("Returns basic information about the storage vol.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_info[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolInfo info;
+    virStorageVolPtr vol;
+    bool ret = true;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        return false;
+
+    vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol));
+
+    if (virStorageVolGetInfo(vol, &info) == 0) {
+        double val;
+        const char *unit;
+        switch(info.type) {
+        case VIR_STORAGE_VOL_FILE:
+            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("file"));
+            break;
+
+        case VIR_STORAGE_VOL_BLOCK:
+            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("block"));
+            break;
+
+        case VIR_STORAGE_VOL_DIR:
+            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("dir"));
+            break;
+
+        case VIR_STORAGE_VOL_NETWORK:
+            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("network"));
+            break;
+
+        default:
+            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("unknown"));
+        }
+
+        val = prettyCapacity(info.capacity, &unit);
+        vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
+
+        val = prettyCapacity(info.allocation, &unit);
+        vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
+    } else {
+        ret = false;
+    }
+
+    virStorageVolFree(vol);
+    return ret;
+}
+
+/*
+ * "vol-resize" command
+ */
+static const vshCmdInfo info_vol_resize[] = {
+    {"help", N_("resize a vol")},
+    {"desc", N_("Resizes a storage volume.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_resize[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ,
+     N_("new capacity for the vol, as scaled integer (default bytes)")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {"allocate", VSH_OT_BOOL, 0,
+     N_("allocate the new capacity, rather than leaving it sparse")},
+    {"delta", VSH_OT_BOOL, 0,
+     N_("use capacity as a delta to current size, rather than the new size")},
+    {"shrink", VSH_OT_BOOL, 0, N_("allow the resize to shrink the volume")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolResize(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+    const char *capacityStr = NULL;
+    unsigned long long capacity = 0;
+    unsigned int flags = 0;
+    bool ret = false;
+    bool delta = false;
+
+    if (vshCommandOptBool(cmd, "allocate"))
+        flags |= VIR_STORAGE_VOL_RESIZE_ALLOCATE;
+    if (vshCommandOptBool(cmd, "delta")) {
+        delta = true;
+        flags |= VIR_STORAGE_VOL_RESIZE_DELTA;
+    }
+    if (vshCommandOptBool(cmd, "shrink"))
+        flags |= VIR_STORAGE_VOL_RESIZE_SHRINK;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        return false;
+
+    if (vshCommandOptString(cmd, "capacity", &capacityStr) <= 0)
+        goto cleanup;
+    virSkipSpaces(&capacityStr);
+    if (*capacityStr == '-') {
+        /* The API always requires a positive value; but we allow a
+         * negative value for convenience.  */
+        if (delta && vshCommandOptBool(cmd, "shrink")){
+            capacityStr++;
+        } else {
+            vshError(ctl, "%s",
+                     _("negative size requires --delta and --shrink"));
+            goto cleanup;
+        }
+    }
+    if (vshVolSize(capacityStr, &capacity) < 0) {
+        vshError(ctl, _("Malformed size %s"), capacityStr);
+        goto cleanup;
+    }
+
+    if (virStorageVolResize(vol, capacity, flags) == 0) {
+        vshPrint(ctl,
+                 delta ? _("Size of volume '%s' successfully changed by %s\n")
+                 : _("Size of volume '%s' successfully changed to %s\n"),
+                 virStorageVolGetName(vol), capacityStr);
+        ret = true;
+    } else {
+        vshError(ctl,
+                 delta ? _("Failed to change size of volume '%s' by %s\n")
+                 : _("Failed to change size of volume '%s' to %s\n"),
+                 virStorageVolGetName(vol), capacityStr);
+        ret = false;
+    }
+
+cleanup:
+    virStorageVolFree(vol);
+    return ret;
+}
+
+/*
+ * "vol-dumpxml" command
+ */
+static const vshCmdInfo info_vol_dumpxml[] = {
+    {"help", N_("vol information in XML")},
+    {"desc", N_("Output the vol information as an XML dump to stdout.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_dumpxml[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+    bool ret = true;
+    char *dump;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        return false;
+
+    dump = virStorageVolGetXMLDesc(vol, 0);
+    if (dump != NULL) {
+        vshPrint(ctl, "%s", dump);
+        VIR_FREE(dump);
+    } else {
+        ret = false;
+    }
+
+    virStorageVolFree(vol);
+    return ret;
+}
+
+/*
+ * "vol-list" command
+ */
+static const vshCmdInfo info_vol_list[] = {
+    {"help", N_("list vols")},
+    {"desc", N_("Returns list of vols by pool.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_list[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
+    {"details", VSH_OT_BOOL, 0, N_("display extended details for volumes")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    virStorageVolInfo volumeInfo;
+    virStoragePoolPtr pool;
+    char **activeNames = NULL;
+    char *outputStr = NULL;
+    const char *unit;
+    double val;
+    bool details = vshCommandOptBool(cmd, "details");
+    int numVolumes = 0, i;
+    int ret;
+    bool functionReturn;
+    int stringLength = 0;
+    size_t allocStrLength = 0, capStrLength = 0;
+    size_t nameStrLength = 0, pathStrLength = 0;
+    size_t typeStrLength = 0;
+    struct volInfoText {
+        char *allocation;
+        char *capacity;
+        char *path;
+        char *type;
+    };
+    struct volInfoText *volInfoTexts = NULL;
+
+    /* Check the connection to libvirtd daemon is still working */
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    /* Look up the pool information given to us by the user */
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+        return false;
+
+    /* Determine the number of volumes in the pool */
+    numVolumes = virStoragePoolNumOfVolumes(pool);
+
+    if (numVolumes < 0) {
+        vshError(ctl, "%s", _("Failed to list storage volumes"));
+        virStoragePoolFree(pool);
+        return false;
+    }
+
+    /* Retrieve the list of volume names in the pool */
+    if (numVolumes > 0) {
+        activeNames = vshCalloc(ctl, numVolumes, sizeof(*activeNames));
+        if ((numVolumes = virStoragePoolListVolumes(pool, activeNames,
+                                                    numVolumes)) < 0) {
+            vshError(ctl, "%s", _("Failed to list active vols"));
+            VIR_FREE(activeNames);
+            virStoragePoolFree(pool);
+            return false;
+        }
+
+        /* Sort the volume names */
+        qsort(&activeNames[0], numVolumes, sizeof(*activeNames), vshNameSorter);
+
+        /* Set aside memory for volume information pointers */
+        volInfoTexts = vshCalloc(ctl, numVolumes, sizeof(*volInfoTexts));
+    }
+
+    /* Collect the rest of the volume information for display */
+    for (i = 0; i < numVolumes; i++) {
+        /* Retrieve volume info */
+        virStorageVolPtr vol = virStorageVolLookupByName(pool,
+                                                         activeNames[i]);
+
+        /* Retrieve the volume path */
+        if ((volInfoTexts[i].path = virStorageVolGetPath(vol)) == NULL) {
+            /* Something went wrong retrieving a volume path, cope with it */
+            volInfoTexts[i].path = vshStrdup(ctl, _("unknown"));
+        }
+
+        /* If requested, retrieve volume type and sizing information */
+        if (details) {
+            if (virStorageVolGetInfo(vol, &volumeInfo) != 0) {
+                /* Something went wrong retrieving volume info, cope with it */
+                volInfoTexts[i].allocation = vshStrdup(ctl, _("unknown"));
+                volInfoTexts[i].capacity = vshStrdup(ctl, _("unknown"));
+                volInfoTexts[i].type = vshStrdup(ctl, _("unknown"));
+            } else {
+                /* Convert the returned volume info into output strings */
+
+                /* Volume type */
+                switch (volumeInfo.type) {
+                        case VIR_STORAGE_VOL_FILE:
+                            volInfoTexts[i].type = vshStrdup(ctl, _("file"));
+                            break;
+                        case VIR_STORAGE_VOL_BLOCK:
+                            volInfoTexts[i].type = vshStrdup(ctl, _("block"));
+                            break;
+                        case VIR_STORAGE_VOL_DIR:
+                            volInfoTexts[i].type = vshStrdup(ctl, _("dir"));
+                            break;
+                        default:
+                            volInfoTexts[i].type = vshStrdup(ctl, _("unknown"));
+                }
+
+                /* Create the capacity output string */
+                val = prettyCapacity(volumeInfo.capacity, &unit);
+                ret = virAsprintf(&volInfoTexts[i].capacity,
+                                  "%.2lf %s", val, unit);
+                if (ret < 0) {
+                    /* An error occurred creating the string, return */
+                    goto asprintf_failure;
+                }
+
+                /* Create the allocation output string */
+                val = prettyCapacity(volumeInfo.allocation, &unit);
+                ret = virAsprintf(&volInfoTexts[i].allocation,
+                                  "%.2lf %s", val, unit);
+                if (ret < 0) {
+                    /* An error occurred creating the string, return */
+                    goto asprintf_failure;
+                }
+            }
+
+            /* Remember the largest length for each output string.
+             * This lets us displaying header and volume information rows
+             * using a single, properly sized, printf style output string.
+             */
+
+            /* Keep the length of name string if longest so far */
+            stringLength = strlen(activeNames[i]);
+            if (stringLength > nameStrLength)
+                nameStrLength = stringLength;
+
+            /* Keep the length of path string if longest so far */
+            stringLength = strlen(volInfoTexts[i].path);
+            if (stringLength > pathStrLength)
+                pathStrLength = stringLength;
+
+            /* Keep the length of type string if longest so far */
+            stringLength = strlen(volInfoTexts[i].type);
+            if (stringLength > typeStrLength)
+                typeStrLength = stringLength;
+
+            /* Keep the length of capacity string if longest so far */
+            stringLength = strlen(volInfoTexts[i].capacity);
+            if (stringLength > capStrLength)
+                capStrLength = stringLength;
+
+            /* Keep the length of allocation string if longest so far */
+            stringLength = strlen(volInfoTexts[i].allocation);
+            if (stringLength > allocStrLength)
+                allocStrLength = stringLength;
+        }
+
+        /* Cleanup memory allocation */
+        virStorageVolFree(vol);
+    }
+
+    /* If the --details option wasn't selected, we output the volume
+     * info using the fixed string format from previous versions to
+     * maintain backward compatibility.
+     */
+
+    /* Output basic info then return if --details option not selected */
+    if (!details) {
+        /* The old output format */
+        vshPrintExtra(ctl, "%-20s %-40s\n", _("Name"), _("Path"));
+        vshPrintExtra(ctl, "-----------------------------------------\n");
+        for (i = 0; i < numVolumes; i++) {
+            vshPrint(ctl, "%-20s %-40s\n", activeNames[i],
+                     volInfoTexts[i].path);
+        }
+
+        /* Cleanup and return */
+        functionReturn = true;
+        goto cleanup;
+    }
+
+    /* We only get here if the --details option was selected. */
+
+    /* Use the length of name header string if it's longest */
+    stringLength = strlen(_("Name"));
+    if (stringLength > nameStrLength)
+        nameStrLength = stringLength;
+
+    /* Use the length of path header string if it's longest */
+    stringLength = strlen(_("Path"));
+    if (stringLength > pathStrLength)
+        pathStrLength = stringLength;
+
+    /* Use the length of type header string if it's longest */
+    stringLength = strlen(_("Type"));
+    if (stringLength > typeStrLength)
+        typeStrLength = stringLength;
+
+    /* Use the length of capacity header string if it's longest */
+    stringLength = strlen(_("Capacity"));
+    if (stringLength > capStrLength)
+        capStrLength = stringLength;
+
+    /* Use the length of allocation header string if it's longest */
+    stringLength = strlen(_("Allocation"));
+    if (stringLength > allocStrLength)
+        allocStrLength = stringLength;
+
+    /* Display the string lengths for debugging */
+    vshDebug(ctl, VSH_ERR_DEBUG,
+             "Longest name string = %zu chars\n", nameStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG,
+             "Longest path string = %zu chars\n", pathStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG,
+             "Longest type string = %zu chars\n", typeStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG,
+             "Longest capacity string = %zu chars\n", capStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG,
+             "Longest allocation string = %zu chars\n", allocStrLength);
+
+    /* Create the output template */
+    ret = virAsprintf(&outputStr,
+                      "%%-%lus  %%-%lus  %%-%lus  %%%lus  %%%lus\n",
+                      (unsigned long) nameStrLength,
+                      (unsigned long) pathStrLength,
+                      (unsigned long) typeStrLength,
+                      (unsigned long) capStrLength,
+                      (unsigned long) allocStrLength);
+    if (ret < 0) {
+        /* An error occurred creating the string, return */
+        goto asprintf_failure;
+    }
+
+    /* Display the header */
+    vshPrint(ctl, outputStr, _("Name"), _("Path"), _("Type"),
+             ("Capacity"), _("Allocation"));
+    for (i = nameStrLength + pathStrLength + typeStrLength
+                           + capStrLength + allocStrLength
+                           + 8; i > 0; i--)
+        vshPrintExtra(ctl, "-");
+    vshPrintExtra(ctl, "\n");
+
+    /* Display the volume info rows */
+    for (i = 0; i < numVolumes; i++) {
+        vshPrint(ctl, outputStr,
+                 activeNames[i],
+                 volInfoTexts[i].path,
+                 volInfoTexts[i].type,
+                 volInfoTexts[i].capacity,
+                 volInfoTexts[i].allocation);
+    }
+
+    /* Cleanup and return */
+    functionReturn = true;
+    goto cleanup;
+
+asprintf_failure:
+
+    /* Display an appropriate error message then cleanup and return */
+    switch (errno) {
+    case ENOMEM:
+        /* Couldn't allocate memory */
+        vshError(ctl, "%s", _("Out of memory"));
+        break;
+    default:
+        /* Some other error */
+        vshError(ctl, _("virAsprintf failed (errno %d)"), errno);
+    }
+    functionReturn = false;
+
+cleanup:
+
+    /* Safely free the memory allocated in this function */
+    for (i = 0; i < numVolumes; i++) {
+        /* Cleanup the memory for one volume info structure per loop */
+        VIR_FREE(volInfoTexts[i].path);
+        VIR_FREE(volInfoTexts[i].type);
+        VIR_FREE(volInfoTexts[i].capacity);
+        VIR_FREE(volInfoTexts[i].allocation);
+        VIR_FREE(activeNames[i]);
+    }
+
+    /* Cleanup remaining memory */
+    VIR_FREE(outputStr);
+    VIR_FREE(volInfoTexts);
+    VIR_FREE(activeNames);
+    virStoragePoolFree(pool);
+
+    /* Return the desired value */
+    return functionReturn;
+}
+
+/*
+ * "vol-name" command
+ */
+static const vshCmdInfo info_vol_name[] = {
+    {"help", N_("returns the volume name for a given volume key or path")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_name[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume key or path")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolName(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
+                                   VSH_BYUUID)))
+        return false;
+
+    vshPrint(ctl, "%s\n", virStorageVolGetName(vol));
+    virStorageVolFree(vol);
+    return true;
+}
+
+/*
+ * "vol-pool" command
+ */
+static const vshCmdInfo info_vol_pool[] = {
+    {"help", N_("returns the storage pool for a given volume key or path")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_pool[] = {
+    {"uuid", VSH_OT_BOOL, 0, N_("return the pool uuid rather than pool name")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume key or path")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolPool(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr pool;
+    virStorageVolPtr vol;
+    char uuid[VIR_UUID_STRING_BUFLEN];
+
+    /* Check the connection to libvirtd daemon is still working */
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    /* Use the supplied string to locate the volume */
+    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
+                                   VSH_BYUUID))) {
+        return false;
+    }
+
+    /* Look up the parent storage pool for the volume */
+    pool = virStoragePoolLookupByVolume(vol);
+    if (pool == NULL) {
+        vshError(ctl, "%s", _("failed to get parent pool"));
+        virStorageVolFree(vol);
+        return false;
+    }
+
+    /* Return the requested details of the parent storage pool */
+    if (vshCommandOptBool(cmd, "uuid")) {
+        /* Retrieve and return pool UUID string */
+        if (virStoragePoolGetUUIDString(pool, &uuid[0]) == 0)
+            vshPrint(ctl, "%s\n", uuid);
+    } else {
+        /* Return the storage pool name */
+        vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
+    }
+
+    /* Cleanup */
+    virStorageVolFree(vol);
+    virStoragePoolFree(pool);
+    return true;
+}
+
+/*
+ * "vol-key" command
+ */
+static const vshCmdInfo info_vol_key[] = {
+    {"help", N_("returns the volume key for a given volume name or path")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_key[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume name or path")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolKey(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        return false;
+
+    vshPrint(ctl, "%s\n", virStorageVolGetKey(vol));
+    virStorageVolFree(vol);
+    return true;
+}
+
+/*
+ * "vol-path" command
+ */
+static const vshCmdInfo info_vol_path[] = {
+    {"help", N_("returns the volume path for a given volume name or key")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_path[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume name or key")},
+    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolPath(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol;
+    char * StorageVolPath;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) {
+        return false;
+    }
+
+    if ((StorageVolPath = virStorageVolGetPath(vol)) == NULL) {
+        virStorageVolFree(vol);
+        return false;
+    }
+
+    vshPrint(ctl, "%s\n", StorageVolPath);
+    VIR_FREE(StorageVolPath);
+    virStorageVolFree(vol);
+    return true;
+}
diff --git a/tools/virsh.c b/tools/virsh.c
index e3ecd54..ac8ad09 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -372,16 +372,6 @@ static virStoragePoolPtr vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd,
     vshCommandOptPoolBy(_ctl, _cmd, _optname, _name,             \
                            VSH_BYUUID|VSH_BYNAME)
 
-static virStorageVolPtr vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
-                                           const char *optname,
-                                           const char *pooloptname,
-                                           const char **name, int flag);
-
-/* default is lookup by Name and UUID */
-#define vshCommandOptVol(_ctl, _cmd, _optname, _pooloptname, _name)   \
-    vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name,     \
-                           VSH_BYUUID|VSH_BYNAME)
-
 static virSecretPtr vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd,
                                         const char **name);
 
@@ -4159,1632 +4149,264 @@ cmdPoolDiscoverSources(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED)
         return false;
 
     if (srcSpecFile && virFileReadAll(srcSpecFile, VIRSH_MAX_XML_FILE, &srcSpec) < 0)
-        return false;
-
-    srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0);
-    VIR_FREE(srcSpec);
-    if (srcList == NULL) {
-        vshError(ctl, _("Failed to find any %s pool sources"), type);
-        return false;
-    }
-    vshPrint(ctl, "%s", srcList);
-    VIR_FREE(srcList);
-
-    return true;
-}
-
-
-/*
- * "pool-info" command
- */
-static const vshCmdInfo info_pool_info[] = {
-    {"help", N_("storage pool information")},
-    {"desc", N_("Returns basic information about the storage pool.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_pool_info[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdPoolInfo(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolInfo info;
-    virStoragePoolPtr pool;
-    int autostart = 0;
-    int persistent = 0;
-    bool ret = true;
-    char uuid[VIR_UUID_STRING_BUFLEN];
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
-        return false;
-
-    vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool));
-
-    if (virStoragePoolGetUUIDString(pool, &uuid[0])==0)
-        vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
-
-    if (virStoragePoolGetInfo(pool, &info) == 0) {
-        double val;
-        const char *unit;
-        switch (info.state) {
-        case VIR_STORAGE_POOL_INACTIVE:
-            vshPrint(ctl, "%-15s %s\n", _("State:"),
-                     _("inactive"));
-            break;
-        case VIR_STORAGE_POOL_BUILDING:
-            vshPrint(ctl, "%-15s %s\n", _("State:"),
-                     _("building"));
-            break;
-        case VIR_STORAGE_POOL_RUNNING:
-            vshPrint(ctl, "%-15s %s\n", _("State:"),
-                     _("running"));
-            break;
-        case VIR_STORAGE_POOL_DEGRADED:
-            vshPrint(ctl, "%-15s %s\n", _("State:"),
-                     _("degraded"));
-            break;
-        case VIR_STORAGE_POOL_INACCESSIBLE:
-            vshPrint(ctl, "%-15s %s\n", _("State:"),
-                     _("inaccessible"));
-            break;
-        }
-
-        /* Check and display whether the pool is persistent or not */
-        persistent = virStoragePoolIsPersistent(pool);
-        vshDebug(ctl, VSH_ERR_DEBUG, "Pool persistent flag value: %d\n",
-                 persistent);
-        if (persistent < 0)
-            vshPrint(ctl, "%-15s %s\n", _("Persistent:"),  _("unknown"));
-        else
-            vshPrint(ctl, "%-15s %s\n", _("Persistent:"), persistent ? _("yes") : _("no"));
-
-        /* Check and display whether the pool is autostarted or not */
-        virStoragePoolGetAutostart(pool, &autostart);
-        vshDebug(ctl, VSH_ERR_DEBUG, "Pool autostart flag value: %d\n",
-                 autostart);
-        if (autostart < 0)
-            vshPrint(ctl, "%-15s %s\n", _("Autostart:"), _("no autostart"));
-        else
-            vshPrint(ctl, "%-15s %s\n", _("Autostart:"), autostart ? _("yes") : _("no"));
-
-        if (info.state == VIR_STORAGE_POOL_RUNNING ||
-            info.state == VIR_STORAGE_POOL_DEGRADED) {
-            val = prettyCapacity(info.capacity, &unit);
-            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
-
-            val = prettyCapacity(info.allocation, &unit);
-            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
-
-            val = prettyCapacity(info.available, &unit);
-            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Available:"), val, unit);
-        }
-    } else {
-        ret = false;
-    }
-
-    virStoragePoolFree(pool);
-    return ret;
-}
-
-
-/*
- * "pool-name" command
- */
-static const vshCmdInfo info_pool_name[] = {
-    {"help", N_("convert a pool UUID to pool name")},
-    {"desc", ""},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_pool_name[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdPoolName(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
-                                           VSH_BYUUID)))
-        return false;
-
-    vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
-    virStoragePoolFree(pool);
-    return true;
-}
-
-
-/*
- * "pool-start" command
- */
-static const vshCmdInfo info_pool_start[] = {
-    {"help", N_("start a (previously defined) inactive pool")},
-    {"desc", N_("Start a pool.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_pool_start[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name or uuid of the inactive pool")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdPoolStart(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool;
-    bool ret = true;
-    const char *name = NULL;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
-         return false;
-
-    if (virStoragePoolCreate(pool, 0) == 0) {
-        vshPrint(ctl, _("Pool %s started\n"), name);
-    } else {
-        vshError(ctl, _("Failed to start pool %s"), name);
-        ret = false;
-    }
-
-    virStoragePoolFree(pool);
-    return ret;
-}
-
-
-/*
- * "vol-create-as" command
- */
-static const vshCmdInfo info_vol_create_as[] = {
-    {"help", N_("create a volume from a set of args")},
-    {"desc", N_("Create a vol.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_create_as[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
-    {"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the volume")},
-    {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ,
-     N_("size of the vol, as scaled integer (default bytes)")},
-    {"allocation", VSH_OT_STRING, 0,
-     N_("initial allocation size, as scaled integer (default bytes)")},
-    {"format", VSH_OT_STRING, 0,
-     N_("file format type raw,bochs,qcow,qcow2,qed,vmdk")},
-    {"backing-vol", VSH_OT_STRING, 0,
-     N_("the backing volume if taking a snapshot")},
-    {"backing-vol-format", VSH_OT_STRING, 0,
-     N_("format of backing volume if taking a snapshot")},
-    {NULL, 0, 0, NULL}
-};
-
-static int
-vshVolSize(const char *data, unsigned long long *val)
-{
-    char *end;
-    if (virStrToLong_ull(data, &end, 10, val) < 0)
-        return -1;
-    return virScaleInteger(val, end, 1, ULLONG_MAX);
-}
-
-static bool
-cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool;
-    virStorageVolPtr vol;
-    char *xml;
-    const char *name, *capacityStr = NULL, *allocationStr = NULL, *format = NULL;
-    const char *snapshotStrVol = NULL, *snapshotStrFormat = NULL;
-    unsigned long long capacity, allocation = 0;
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
-                                     VSH_BYNAME)))
-        return false;
-
-    if (vshCommandOptString(cmd, "name", &name) <= 0)
-        goto cleanup;
-
-    if (vshCommandOptString(cmd, "capacity", &capacityStr) <= 0)
-        goto cleanup;
-
-    if (vshVolSize(capacityStr, &capacity) < 0) {
-        vshError(ctl, _("Malformed size %s"), capacityStr);
-        goto cleanup;
-    }
-
-    if (vshCommandOptString(cmd, "allocation", &allocationStr) > 0 &&
-        vshVolSize(allocationStr, &allocation) < 0) {
-        vshError(ctl, _("Malformed size %s"), allocationStr);
-        goto cleanup;
-    }
-
-    if (vshCommandOptString(cmd, "format", &format) < 0 ||
-        vshCommandOptString(cmd, "backing-vol", &snapshotStrVol) < 0 ||
-        vshCommandOptString(cmd, "backing-vol-format",
-                            &snapshotStrFormat) < 0) {
-        vshError(ctl, "%s", _("missing argument"));
-        goto cleanup;
-    }
-
-
-    virBufferAddLit(&buf, "<volume>\n");
-    virBufferAsprintf(&buf, "  <name>%s</name>\n", name);
-    virBufferAsprintf(&buf, "  <capacity>%llu</capacity>\n", capacity);
-    if (allocationStr)
-        virBufferAsprintf(&buf, "  <allocation>%llu</allocation>\n", allocation);
-
-    if (format) {
-        virBufferAddLit(&buf, "  <target>\n");
-        virBufferAsprintf(&buf, "    <format type='%s'/>\n",format);
-        virBufferAddLit(&buf, "  </target>\n");
-    }
-
-    /* Convert the snapshot parameters into backingStore XML */
-    if (snapshotStrVol) {
-        /* Lookup snapshot backing volume.  Try the backing-vol
-         *  parameter as a name */
-        vshDebug(ctl, VSH_ERR_DEBUG,
-                 "%s: Look up backing store volume '%s' as name\n",
-                 cmd->def->name, snapshotStrVol);
-        virStorageVolPtr snapVol = virStorageVolLookupByName(pool, snapshotStrVol);
-        if (snapVol)
-                vshDebug(ctl, VSH_ERR_DEBUG,
-                         "%s: Backing store volume found using '%s' as name\n",
-                         cmd->def->name, snapshotStrVol);
-
-        if (snapVol == NULL) {
-            /* Snapshot backing volume not found by name.  Try the
-             *  backing-vol parameter as a key */
-            vshDebug(ctl, VSH_ERR_DEBUG,
-                     "%s: Look up backing store volume '%s' as key\n",
-                     cmd->def->name, snapshotStrVol);
-            snapVol = virStorageVolLookupByKey(ctl->conn, snapshotStrVol);
-            if (snapVol)
-                vshDebug(ctl, VSH_ERR_DEBUG,
-                         "%s: Backing store volume found using '%s' as key\n",
-                         cmd->def->name, snapshotStrVol);
-        }
-        if (snapVol == NULL) {
-            /* Snapshot backing volume not found by key.  Try the
-             *  backing-vol parameter as a path */
-            vshDebug(ctl, VSH_ERR_DEBUG,
-                     "%s: Look up backing store volume '%s' as path\n",
-                     cmd->def->name, snapshotStrVol);
-            snapVol = virStorageVolLookupByPath(ctl->conn, snapshotStrVol);
-            if (snapVol)
-                vshDebug(ctl, VSH_ERR_DEBUG,
-                         "%s: Backing store volume found using '%s' as path\n",
-                         cmd->def->name, snapshotStrVol);
-        }
-        if (snapVol == NULL) {
-            vshError(ctl, _("failed to get vol '%s'"), snapshotStrVol);
-            goto cleanup;
-        }
-
-        char *snapshotStrVolPath;
-        if ((snapshotStrVolPath = virStorageVolGetPath(snapVol)) == NULL) {
-            virStorageVolFree(snapVol);
-            goto cleanup;
-        }
-
-        /* Create XML for the backing store */
-        virBufferAddLit(&buf, "  <backingStore>\n");
-        virBufferAsprintf(&buf, "    <path>%s</path>\n",snapshotStrVolPath);
-        if (snapshotStrFormat)
-            virBufferAsprintf(&buf, "    <format type='%s'/>\n",snapshotStrFormat);
-        virBufferAddLit(&buf, "  </backingStore>\n");
-
-        /* Cleanup snapshot allocations */
-        VIR_FREE(snapshotStrVolPath);
-        virStorageVolFree(snapVol);
-    }
-
-    virBufferAddLit(&buf, "</volume>\n");
-
-    if (virBufferError(&buf)) {
-        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
-        goto cleanup;
-    }
-    xml = virBufferContentAndReset(&buf);
-    vol = virStorageVolCreateXML(pool, xml, 0);
-    VIR_FREE(xml);
-    virStoragePoolFree(pool);
-
-    if (vol != NULL) {
-        vshPrint(ctl, _("Vol %s created\n"), name);
-        virStorageVolFree(vol);
-        return true;
-    } else {
-        vshError(ctl, _("Failed to create vol %s"), name);
-        return false;
-    }
-
- cleanup:
-    virBufferFreeAndReset(&buf);
-    virStoragePoolFree(pool);
-    return false;
-}
-
-
-/*
- * "pool-undefine" command
- */
-static const vshCmdInfo info_pool_undefine[] = {
-    {"help", N_("undefine an inactive pool")},
-    {"desc", N_("Undefine the configuration for an inactive pool.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_pool_undefine[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdPoolUndefine(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool;
-    bool ret = true;
-    const char *name;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
-        return false;
-
-    if (virStoragePoolUndefine(pool) == 0) {
-        vshPrint(ctl, _("Pool %s has been undefined\n"), name);
-    } else {
-        vshError(ctl, _("Failed to undefine pool %s"), name);
-        ret = false;
-    }
-
-    virStoragePoolFree(pool);
-    return ret;
-}
-
-
-/*
- * "pool-uuid" command
- */
-static const vshCmdInfo info_pool_uuid[] = {
-    {"help", N_("convert a pool name to pool UUID")},
-    {"desc", ""},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_pool_uuid[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdPoolUuid(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool;
-    char uuid[VIR_UUID_STRING_BUFLEN];
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
-                                           VSH_BYNAME)))
-        return false;
-
-    if (virStoragePoolGetUUIDString(pool, uuid) != -1)
-        vshPrint(ctl, "%s\n", uuid);
-    else
-        vshError(ctl, "%s", _("failed to get pool UUID"));
-
-    virStoragePoolFree(pool);
-    return true;
-}
-
-
-/*
- * "vol-create" command
- */
-static const vshCmdInfo info_vol_create[] = {
-    {"help", N_("create a vol from an XML file")},
-    {"desc", N_("Create a vol.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_create[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
-    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolCreate(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool;
-    virStorageVolPtr vol;
-    const char *from = NULL;
-    bool ret = true;
-    char *buffer;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
-                                           VSH_BYNAME)))
-        return false;
-
-    if (vshCommandOptString(cmd, "file", &from) <= 0) {
-        virStoragePoolFree(pool);
-        return false;
-    }
-
-    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
-        virshReportError(ctl);
-        virStoragePoolFree(pool);
-        return false;
-    }
-
-    vol = virStorageVolCreateXML(pool, buffer, 0);
-    VIR_FREE(buffer);
-    virStoragePoolFree(pool);
-
-    if (vol != NULL) {
-        vshPrint(ctl, _("Vol %s created from %s\n"),
-                 virStorageVolGetName(vol), from);
-        virStorageVolFree(vol);
-    } else {
-        vshError(ctl, _("Failed to create vol from %s"), from);
-        ret = false;
-    }
-    return ret;
-}
-
-/*
- * "vol-create-from" command
- */
-static const vshCmdInfo info_vol_create_from[] = {
-    {"help", N_("create a vol, using another volume as input")},
-    {"desc", N_("Create a vol from an existing volume.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_create_from[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
-    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")},
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("input vol name or key")},
-    {"inputpool", VSH_OT_STRING, 0, N_("pool name or uuid of the input volume's pool")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr pool = NULL;
-    virStorageVolPtr newvol = NULL, inputvol = NULL;
-    const char *from = NULL;
-    bool ret = false;
-    char *buffer = NULL;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        goto cleanup;
-
-    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
-        goto cleanup;
-
-    if (vshCommandOptString(cmd, "file", &from) <= 0) {
-        goto cleanup;
-    }
-
-    if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
-        goto cleanup;
-
-    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
-        virshReportError(ctl);
-        goto cleanup;
-    }
-
-    newvol = virStorageVolCreateXMLFrom(pool, buffer, inputvol, 0);
-
-    if (newvol != NULL) {
-        vshPrint(ctl, _("Vol %s created from input vol %s\n"),
-                 virStorageVolGetName(newvol), virStorageVolGetName(inputvol));
-    } else {
-        vshError(ctl, _("Failed to create vol from %s"), from);
-        goto cleanup;
-    }
-
-    ret = true;
-cleanup:
-    VIR_FREE(buffer);
-    if (pool)
-        virStoragePoolFree(pool);
-    if (inputvol)
-        virStorageVolFree(inputvol);
-    if (newvol)
-        virStorageVolFree(newvol);
-    return ret;
-}
-
-static xmlChar *
-makeCloneXML(const char *origxml, const char *newname)
-{
-
-    xmlDocPtr doc = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    xmlXPathObjectPtr obj = NULL;
-    xmlChar *newxml = NULL;
-    int size;
-
-    doc = virXMLParseStringCtxt(origxml, _("(volume_definition)"), &ctxt);
-    if (!doc)
-        goto cleanup;
-
-    obj = xmlXPathEval(BAD_CAST "/volume/name", ctxt);
-    if (obj == NULL || obj->nodesetval == NULL ||
-        obj->nodesetval->nodeTab == NULL)
-        goto cleanup;
-
-    xmlNodeSetContent(obj->nodesetval->nodeTab[0], (const xmlChar *)newname);
-    xmlDocDumpMemory(doc, &newxml, &size);
-
-cleanup:
-    xmlXPathFreeObject(obj);
-    xmlXPathFreeContext(ctxt);
-    xmlFreeDoc(doc);
-    return newxml;
-}
-
-/*
- * "vol-clone" command
- */
-static const vshCmdInfo info_vol_clone[] = {
-    {"help", N_("clone a volume.")},
-    {"desc", N_("Clone an existing volume.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_clone[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("orig vol name or key")},
-    {"newname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("clone name")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolClone(vshControl *ctl, const vshCmd *cmd)
-{
-    virStoragePoolPtr origpool = NULL;
-    virStorageVolPtr origvol = NULL, newvol = NULL;
-    const char *name = NULL;
-    char *origxml = NULL;
-    xmlChar *newxml = NULL;
-    bool ret = false;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        goto cleanup;
-
-    if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
-        goto cleanup;
-
-    origpool = virStoragePoolLookupByVolume(origvol);
-    if (!origpool) {
-        vshError(ctl, "%s", _("failed to get parent pool"));
-        goto cleanup;
-    }
-
-    if (vshCommandOptString(cmd, "newname", &name) <= 0)
-        goto cleanup;
-
-    origxml = virStorageVolGetXMLDesc(origvol, 0);
-    if (!origxml)
-        goto cleanup;
-
-    newxml = makeCloneXML(origxml, name);
-    if (!newxml) {
-        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
-        goto cleanup;
-    }
-
-    newvol = virStorageVolCreateXMLFrom(origpool, (char *) newxml, origvol, 0);
-
-    if (newvol != NULL) {
-        vshPrint(ctl, _("Vol %s cloned from %s\n"),
-                 virStorageVolGetName(newvol), virStorageVolGetName(origvol));
-    } else {
-        vshError(ctl, _("Failed to clone vol from %s"),
-                 virStorageVolGetName(origvol));
-        goto cleanup;
-    }
-
-    ret = true;
-
-cleanup:
-    VIR_FREE(origxml);
-    xmlFree(newxml);
-    if (origvol)
-        virStorageVolFree(origvol);
-    if (newvol)
-        virStorageVolFree(newvol);
-    if (origpool)
-        virStoragePoolFree(origpool);
-    return ret;
-}
-
-
-/*
- * "vol-upload" command
- */
-static const vshCmdInfo info_vol_upload[] = {
-    {"help", N_("upload a file into a volume")},
-    {"desc", N_("Upload a file into a volume")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_upload[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {"offset", VSH_OT_INT, 0, N_("volume offset to upload to") },
-    {"length", VSH_OT_INT, 0, N_("amount of data to upload") },
-    {NULL, 0, 0, NULL}
-};
-
-static int
-cmdVolUploadSource(virStreamPtr st ATTRIBUTE_UNUSED,
-                   char *bytes, size_t nbytes, void *opaque)
-{
-    int *fd = opaque;
-
-    return saferead(*fd, bytes, nbytes);
-}
-
-static bool
-cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
-{
-    const char *file = NULL;
-    virStorageVolPtr vol = NULL;
-    bool ret = false;
-    int fd = -1;
-    virStreamPtr st = NULL;
-    const char *name = NULL;
-    unsigned long long offset = 0, length = 0;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        goto cleanup;
-
-    if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
-        vshError(ctl, _("Unable to parse integer"));
-        return false;
-    }
-
-    if (vshCommandOptULongLong(cmd, "length", &length) < 0) {
-        vshError(ctl, _("Unable to parse integer"));
-        return false;
-    }
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
-        return false;
-    }
-
-    if (vshCommandOptString(cmd, "file", &file) < 0) {
-        vshError(ctl, _("file must not be empty"));
-        goto cleanup;
-    }
-
-    if ((fd = open(file, O_RDONLY)) < 0) {
-        vshError(ctl, _("cannot read %s"), file);
-        goto cleanup;
-    }
-
-    st = virStreamNew(ctl->conn, 0);
-    if (virStorageVolUpload(vol, st, offset, length, 0) < 0) {
-        vshError(ctl, _("cannot upload to volume %s"), name);
-        goto cleanup;
-    }
-
-    if (virStreamSendAll(st, cmdVolUploadSource, &fd) < 0) {
-        vshError(ctl, _("cannot send data to volume %s"), name);
-        goto cleanup;
-    }
-
-    if (VIR_CLOSE(fd) < 0) {
-        vshError(ctl, _("cannot close file %s"), file);
-        virStreamAbort(st);
-        goto cleanup;
-    }
-
-    if (virStreamFinish(st) < 0) {
-        vshError(ctl, _("cannot close volume %s"), name);
-        goto cleanup;
-    }
-
-    ret = true;
-
-cleanup:
-    if (vol)
-        virStorageVolFree(vol);
-    if (st)
-        virStreamFree(st);
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
-
-/*
- * "vol-download" command
- */
-static const vshCmdInfo info_vol_download[] = {
-    {"help", N_("Download a volume to a file")},
-    {"desc", N_("Download a volume to a file")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_download[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {"offset", VSH_OT_INT, 0, N_("volume offset to download from") },
-    {"length", VSH_OT_INT, 0, N_("amount of data to download") },
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
-{
-    const char *file = NULL;
-    virStorageVolPtr vol = NULL;
-    bool ret = false;
-    int fd = -1;
-    virStreamPtr st = NULL;
-    const char *name = NULL;
-    unsigned long long offset = 0, length = 0;
-    bool created = false;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
-        vshError(ctl, _("Unable to parse integer"));
-        return false;
-    }
-
-    if (vshCommandOptULongLong(cmd, "length", &length) < 0) {
-        vshError(ctl, _("Unable to parse integer"));
-        return false;
-    }
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
-        return false;
-
-    if (vshCommandOptString(cmd, "file", &file) < 0) {
-        vshError(ctl, _("file must not be empty"));
-        goto cleanup;
-    }
-
-    if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) {
-        if (errno != EEXIST ||
-            (fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) {
-            vshError(ctl, _("cannot create %s"), file);
-            goto cleanup;
-        }
-    } else {
-        created = true;
-    }
-
-    st = virStreamNew(ctl->conn, 0);
-    if (virStorageVolDownload(vol, st, offset, length, 0) < 0) {
-        vshError(ctl, _("cannot download from volume %s"), name);
-        goto cleanup;
-    }
-
-    if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) {
-        vshError(ctl, _("cannot receive data from volume %s"), name);
-        goto cleanup;
-    }
-
-    if (VIR_CLOSE(fd) < 0) {
-        vshError(ctl, _("cannot close file %s"), file);
-        virStreamAbort(st);
-        goto cleanup;
-    }
-
-    if (virStreamFinish(st) < 0) {
-        vshError(ctl, _("cannot close volume %s"), name);
-        goto cleanup;
-    }
-
-    ret = true;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    if (!ret && created)
-        unlink(file);
-    if (vol)
-        virStorageVolFree(vol);
-    if (st)
-        virStreamFree(st);
-    return ret;
-}
-
-
-/*
- * "vol-delete" command
- */
-static const vshCmdInfo info_vol_delete[] = {
-    {"help", N_("delete a vol")},
-    {"desc", N_("Delete a given vol.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_delete[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolDelete(vshControl *ctl, const vshCmd *cmd)
-{
-    virStorageVolPtr vol;
-    bool ret = true;
-    const char *name;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
-        return false;
-    }
-
-    if (virStorageVolDelete(vol, 0) == 0) {
-        vshPrint(ctl, _("Vol %s deleted\n"), name);
-    } else {
-        vshError(ctl, _("Failed to delete vol %s"), name);
-        ret = false;
-    }
-
-    virStorageVolFree(vol);
-    return ret;
-}
-
-
-/*
- * "vol-wipe" command
- */
-static const vshCmdInfo info_vol_wipe[] = {
-    {"help", N_("wipe a vol")},
-    {"desc", N_("Ensure data previously on a volume is not accessible to future reads")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_wipe[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {"algorithm", VSH_OT_STRING, 0, N_("perform selected wiping algorithm")},
-    {NULL, 0, 0, NULL}
-};
-
-VIR_ENUM_DECL(virStorageVolWipeAlgorithm)
-VIR_ENUM_IMPL(virStorageVolWipeAlgorithm, VIR_STORAGE_VOL_WIPE_ALG_LAST,
-              "zero", "nnsa", "dod", "bsi", "gutmann", "schneier",
-              "pfitzner7", "pfitzner33", "random");
-
-static bool
-cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
-{
-    virStorageVolPtr vol;
-    bool ret = false;
-    const char *name;
-    const char *algorithm_str = NULL;
-    int algorithm = VIR_STORAGE_VOL_WIPE_ALG_ZERO;
-    int funcRet;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
-        return false;
-    }
-
-    if (vshCommandOptString(cmd, "algorithm", &algorithm_str) < 0) {
-        vshError(ctl, "%s", _("missing argument"));
-        goto out;
-    }
-
-    if (algorithm_str &&
-        (algorithm = virStorageVolWipeAlgorithmTypeFromString(algorithm_str)) < 0) {
-        vshError(ctl, _("Unsupported algorithm '%s'"), algorithm_str);
-        goto out;
-    }
-
-    if ((funcRet = virStorageVolWipePattern(vol, algorithm, 0)) < 0) {
-        if (last_error->code == VIR_ERR_NO_SUPPORT &&
-            algorithm == VIR_STORAGE_VOL_WIPE_ALG_ZERO)
-            funcRet = virStorageVolWipe(vol, 0);
-    }
-
-    if (funcRet < 0) {
-        vshError(ctl, _("Failed to wipe vol %s"), name);
-        goto out;
-    }
-
-    vshPrint(ctl, _("Vol %s wiped\n"), name);
-    ret = true;
-out:
-    virStorageVolFree(vol);
-    return ret;
-}
-
-
-/*
- * "vol-info" command
- */
-static const vshCmdInfo info_vol_info[] = {
-    {"help", N_("storage vol information")},
-    {"desc", N_("Returns basic information about the storage vol.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_info[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
-{
-    virStorageVolInfo info;
-    virStorageVolPtr vol;
-    bool ret = true;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
-        return false;
-
-    vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol));
-
-    if (virStorageVolGetInfo(vol, &info) == 0) {
-        double val;
-        const char *unit;
-        switch(info.type) {
-        case VIR_STORAGE_VOL_FILE:
-            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("file"));
-            break;
-
-        case VIR_STORAGE_VOL_BLOCK:
-            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("block"));
-            break;
-
-        case VIR_STORAGE_VOL_DIR:
-            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("dir"));
-            break;
-
-        case VIR_STORAGE_VOL_NETWORK:
-            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("network"));
-            break;
-
-        default:
-            vshPrint(ctl, "%-15s %s\n", _("Type:"), _("unknown"));
-        }
-
-        val = prettyCapacity(info.capacity, &unit);
-        vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
-
-        val = prettyCapacity(info.allocation, &unit);
-        vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
-    } else {
-        ret = false;
-    }
-
-    virStorageVolFree(vol);
-    return ret;
-}
-
-/*
- * "vol-resize" command
- */
-static const vshCmdInfo info_vol_resize[] = {
-    {"help", N_("resize a vol")},
-    {"desc", N_("Resizes a storage volume.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_resize[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ,
-     N_("new capacity for the vol, as scaled integer (default bytes)")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {"allocate", VSH_OT_BOOL, 0,
-     N_("allocate the new capacity, rather than leaving it sparse")},
-    {"delta", VSH_OT_BOOL, 0,
-     N_("use capacity as a delta to current size, rather than the new size")},
-    {"shrink", VSH_OT_BOOL, 0, N_("allow the resize to shrink the volume")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolResize(vshControl *ctl, const vshCmd *cmd)
-{
-    virStorageVolPtr vol;
-    const char *capacityStr = NULL;
-    unsigned long long capacity = 0;
-    unsigned int flags = 0;
-    bool ret = false;
-    bool delta = false;
-
-    if (vshCommandOptBool(cmd, "allocate"))
-        flags |= VIR_STORAGE_VOL_RESIZE_ALLOCATE;
-    if (vshCommandOptBool(cmd, "delta")) {
-        delta = true;
-        flags |= VIR_STORAGE_VOL_RESIZE_DELTA;
-    }
-    if (vshCommandOptBool(cmd, "shrink"))
-        flags |= VIR_STORAGE_VOL_RESIZE_SHRINK;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
-        return false;
-
-    if (vshCommandOptString(cmd, "capacity", &capacityStr) <= 0)
-        goto cleanup;
-    virSkipSpaces(&capacityStr);
-    if (*capacityStr == '-') {
-        /* The API always requires a positive value; but we allow a
-         * negative value for convenience.  */
-        if (delta && vshCommandOptBool(cmd, "shrink")){
-            capacityStr++;
-        } else {
-            vshError(ctl, "%s",
-                     _("negative size requires --delta and --shrink"));
-            goto cleanup;
-        }
-    }
-    if (vshVolSize(capacityStr, &capacity) < 0) {
-        vshError(ctl, _("Malformed size %s"), capacityStr);
-        goto cleanup;
-    }
-
-    if (virStorageVolResize(vol, capacity, flags) == 0) {
-        vshPrint(ctl,
-                 delta ? _("Size of volume '%s' successfully changed by %s\n")
-                 : _("Size of volume '%s' successfully changed to %s\n"),
-                 virStorageVolGetName(vol), capacityStr);
-        ret = true;
-    } else {
-        vshError(ctl,
-                 delta ? _("Failed to change size of volume '%s' by %s\n")
-                 : _("Failed to change size of volume '%s' to %s\n"),
-                 virStorageVolGetName(vol), capacityStr);
-        ret = false;
-    }
-
-cleanup:
-    virStorageVolFree(vol);
-    return ret;
-}
-
-
-/*
- * "vol-dumpxml" command
- */
-static const vshCmdInfo info_vol_dumpxml[] = {
-    {"help", N_("vol information in XML")},
-    {"desc", N_("Output the vol information as an XML dump to stdout.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_dumpxml[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd)
-{
-    virStorageVolPtr vol;
-    bool ret = true;
-    char *dump;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
-        return false;
-
-    dump = virStorageVolGetXMLDesc(vol, 0);
-    if (dump != NULL) {
-        vshPrint(ctl, "%s", dump);
-        VIR_FREE(dump);
-    } else {
-        ret = false;
-    }
-
-    virStorageVolFree(vol);
-    return ret;
-}
-
-
-/*
- * "vol-list" command
- */
-static const vshCmdInfo info_vol_list[] = {
-    {"help", N_("list vols")},
-    {"desc", N_("Returns list of vols by pool.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_vol_list[] = {
-    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
-    {"details", VSH_OT_BOOL, 0, N_("display extended details for volumes")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
-    virStorageVolInfo volumeInfo;
-    virStoragePoolPtr pool;
-    char **activeNames = NULL;
-    char *outputStr = NULL;
-    const char *unit;
-    double val;
-    bool details = vshCommandOptBool(cmd, "details");
-    int numVolumes = 0, i;
-    int ret;
-    bool functionReturn;
-    int stringLength = 0;
-    size_t allocStrLength = 0, capStrLength = 0;
-    size_t nameStrLength = 0, pathStrLength = 0;
-    size_t typeStrLength = 0;
-    struct volInfoText {
-        char *allocation;
-        char *capacity;
-        char *path;
-        char *type;
-    };
-    struct volInfoText *volInfoTexts = NULL;
-
-    /* Check the connection to libvirtd daemon is still working */
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    /* Look up the pool information given to us by the user */
-    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
-        return false;
-
-    /* Determine the number of volumes in the pool */
-    numVolumes = virStoragePoolNumOfVolumes(pool);
-
-    if (numVolumes < 0) {
-        vshError(ctl, "%s", _("Failed to list storage volumes"));
-        virStoragePoolFree(pool);
-        return false;
-    }
-
-    /* Retrieve the list of volume names in the pool */
-    if (numVolumes > 0) {
-        activeNames = vshCalloc(ctl, numVolumes, sizeof(*activeNames));
-        if ((numVolumes = virStoragePoolListVolumes(pool, activeNames,
-                                                    numVolumes)) < 0) {
-            vshError(ctl, "%s", _("Failed to list active vols"));
-            VIR_FREE(activeNames);
-            virStoragePoolFree(pool);
-            return false;
-        }
-
-        /* Sort the volume names */
-        qsort(&activeNames[0], numVolumes, sizeof(*activeNames), vshNameSorter);
-
-        /* Set aside memory for volume information pointers */
-        volInfoTexts = vshCalloc(ctl, numVolumes, sizeof(*volInfoTexts));
-    }
-
-    /* Collect the rest of the volume information for display */
-    for (i = 0; i < numVolumes; i++) {
-        /* Retrieve volume info */
-        virStorageVolPtr vol = virStorageVolLookupByName(pool,
-                                                         activeNames[i]);
-
-        /* Retrieve the volume path */
-        if ((volInfoTexts[i].path = virStorageVolGetPath(vol)) == NULL) {
-            /* Something went wrong retrieving a volume path, cope with it */
-            volInfoTexts[i].path = vshStrdup(ctl, _("unknown"));
-        }
-
-        /* If requested, retrieve volume type and sizing information */
-        if (details) {
-            if (virStorageVolGetInfo(vol, &volumeInfo) != 0) {
-                /* Something went wrong retrieving volume info, cope with it */
-                volInfoTexts[i].allocation = vshStrdup(ctl, _("unknown"));
-                volInfoTexts[i].capacity = vshStrdup(ctl, _("unknown"));
-                volInfoTexts[i].type = vshStrdup(ctl, _("unknown"));
-            } else {
-                /* Convert the returned volume info into output strings */
-
-                /* Volume type */
-                switch (volumeInfo.type) {
-                        case VIR_STORAGE_VOL_FILE:
-                            volInfoTexts[i].type = vshStrdup(ctl, _("file"));
-                            break;
-                        case VIR_STORAGE_VOL_BLOCK:
-                            volInfoTexts[i].type = vshStrdup(ctl, _("block"));
-                            break;
-                        case VIR_STORAGE_VOL_DIR:
-                            volInfoTexts[i].type = vshStrdup(ctl, _("dir"));
-                            break;
-                        default:
-                            volInfoTexts[i].type = vshStrdup(ctl, _("unknown"));
-                }
-
-                /* Create the capacity output string */
-                val = prettyCapacity(volumeInfo.capacity, &unit);
-                ret = virAsprintf(&volInfoTexts[i].capacity,
-                                  "%.2lf %s", val, unit);
-                if (ret < 0) {
-                    /* An error occurred creating the string, return */
-                    goto asprintf_failure;
-                }
-
-                /* Create the allocation output string */
-                val = prettyCapacity(volumeInfo.allocation, &unit);
-                ret = virAsprintf(&volInfoTexts[i].allocation,
-                                  "%.2lf %s", val, unit);
-                if (ret < 0) {
-                    /* An error occurred creating the string, return */
-                    goto asprintf_failure;
-                }
-            }
-
-            /* Remember the largest length for each output string.
-             * This lets us displaying header and volume information rows
-             * using a single, properly sized, printf style output string.
-             */
-
-            /* Keep the length of name string if longest so far */
-            stringLength = strlen(activeNames[i]);
-            if (stringLength > nameStrLength)
-                nameStrLength = stringLength;
-
-            /* Keep the length of path string if longest so far */
-            stringLength = strlen(volInfoTexts[i].path);
-            if (stringLength > pathStrLength)
-                pathStrLength = stringLength;
-
-            /* Keep the length of type string if longest so far */
-            stringLength = strlen(volInfoTexts[i].type);
-            if (stringLength > typeStrLength)
-                typeStrLength = stringLength;
-
-            /* Keep the length of capacity string if longest so far */
-            stringLength = strlen(volInfoTexts[i].capacity);
-            if (stringLength > capStrLength)
-                capStrLength = stringLength;
-
-            /* Keep the length of allocation string if longest so far */
-            stringLength = strlen(volInfoTexts[i].allocation);
-            if (stringLength > allocStrLength)
-                allocStrLength = stringLength;
-        }
-
-        /* Cleanup memory allocation */
-        virStorageVolFree(vol);
-    }
-
-    /* If the --details option wasn't selected, we output the volume
-     * info using the fixed string format from previous versions to
-     * maintain backward compatibility.
-     */
-
-    /* Output basic info then return if --details option not selected */
-    if (!details) {
-        /* The old output format */
-        vshPrintExtra(ctl, "%-20s %-40s\n", _("Name"), _("Path"));
-        vshPrintExtra(ctl, "-----------------------------------------\n");
-        for (i = 0; i < numVolumes; i++) {
-            vshPrint(ctl, "%-20s %-40s\n", activeNames[i],
-                     volInfoTexts[i].path);
-        }
+        return false;
 
-        /* Cleanup and return */
-        functionReturn = true;
-        goto cleanup;
+    srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0);
+    VIR_FREE(srcSpec);
+    if (srcList == NULL) {
+        vshError(ctl, _("Failed to find any %s pool sources"), type);
+        return false;
     }
+    vshPrint(ctl, "%s", srcList);
+    VIR_FREE(srcList);
 
-    /* We only get here if the --details option was selected. */
+    return true;
+}
 
-    /* Use the length of name header string if it's longest */
-    stringLength = strlen(_("Name"));
-    if (stringLength > nameStrLength)
-        nameStrLength = stringLength;
 
-    /* Use the length of path header string if it's longest */
-    stringLength = strlen(_("Path"));
-    if (stringLength > pathStrLength)
-        pathStrLength = stringLength;
+/*
+ * "pool-info" command
+ */
+static const vshCmdInfo info_pool_info[] = {
+    {"help", N_("storage pool information")},
+    {"desc", N_("Returns basic information about the storage pool.")},
+    {NULL, NULL}
+};
 
-    /* Use the length of type header string if it's longest */
-    stringLength = strlen(_("Type"));
-    if (stringLength > typeStrLength)
-        typeStrLength = stringLength;
+static const vshCmdOptDef opts_pool_info[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
 
-    /* Use the length of capacity header string if it's longest */
-    stringLength = strlen(_("Capacity"));
-    if (stringLength > capStrLength)
-        capStrLength = stringLength;
+static bool
+cmdPoolInfo(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolInfo info;
+    virStoragePoolPtr pool;
+    int autostart = 0;
+    int persistent = 0;
+    bool ret = true;
+    char uuid[VIR_UUID_STRING_BUFLEN];
 
-    /* Use the length of allocation header string if it's longest */
-    stringLength = strlen(_("Allocation"));
-    if (stringLength > allocStrLength)
-        allocStrLength = stringLength;
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
 
-    /* Display the string lengths for debugging */
-    vshDebug(ctl, VSH_ERR_DEBUG,
-             "Longest name string = %zu chars\n", nameStrLength);
-    vshDebug(ctl, VSH_ERR_DEBUG,
-             "Longest path string = %zu chars\n", pathStrLength);
-    vshDebug(ctl, VSH_ERR_DEBUG,
-             "Longest type string = %zu chars\n", typeStrLength);
-    vshDebug(ctl, VSH_ERR_DEBUG,
-             "Longest capacity string = %zu chars\n", capStrLength);
-    vshDebug(ctl, VSH_ERR_DEBUG,
-             "Longest allocation string = %zu chars\n", allocStrLength);
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+        return false;
 
-    /* Create the output template */
-    ret = virAsprintf(&outputStr,
-                      "%%-%lus  %%-%lus  %%-%lus  %%%lus  %%%lus\n",
-                      (unsigned long) nameStrLength,
-                      (unsigned long) pathStrLength,
-                      (unsigned long) typeStrLength,
-                      (unsigned long) capStrLength,
-                      (unsigned long) allocStrLength);
-    if (ret < 0) {
-        /* An error occurred creating the string, return */
-        goto asprintf_failure;
-    }
+    vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool));
 
-    /* Display the header */
-    vshPrint(ctl, outputStr, _("Name"), _("Path"), _("Type"),
-             ("Capacity"), _("Allocation"));
-    for (i = nameStrLength + pathStrLength + typeStrLength
-                           + capStrLength + allocStrLength
-                           + 8; i > 0; i--)
-        vshPrintExtra(ctl, "-");
-    vshPrintExtra(ctl, "\n");
+    if (virStoragePoolGetUUIDString(pool, &uuid[0])==0)
+        vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
 
-    /* Display the volume info rows */
-    for (i = 0; i < numVolumes; i++) {
-        vshPrint(ctl, outputStr,
-                 activeNames[i],
-                 volInfoTexts[i].path,
-                 volInfoTexts[i].type,
-                 volInfoTexts[i].capacity,
-                 volInfoTexts[i].allocation);
-    }
+    if (virStoragePoolGetInfo(pool, &info) == 0) {
+        double val;
+        const char *unit;
+        switch (info.state) {
+        case VIR_STORAGE_POOL_INACTIVE:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("inactive"));
+            break;
+        case VIR_STORAGE_POOL_BUILDING:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("building"));
+            break;
+        case VIR_STORAGE_POOL_RUNNING:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("running"));
+            break;
+        case VIR_STORAGE_POOL_DEGRADED:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("degraded"));
+            break;
+        case VIR_STORAGE_POOL_INACCESSIBLE:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("inaccessible"));
+            break;
+        }
 
-    /* Cleanup and return */
-    functionReturn = true;
-    goto cleanup;
+        /* Check and display whether the pool is persistent or not */
+        persistent = virStoragePoolIsPersistent(pool);
+        vshDebug(ctl, VSH_ERR_DEBUG, "Pool persistent flag value: %d\n",
+                 persistent);
+        if (persistent < 0)
+            vshPrint(ctl, "%-15s %s\n", _("Persistent:"),  _("unknown"));
+        else
+            vshPrint(ctl, "%-15s %s\n", _("Persistent:"), persistent ? _("yes") : _("no"));
 
-asprintf_failure:
+        /* Check and display whether the pool is autostarted or not */
+        virStoragePoolGetAutostart(pool, &autostart);
+        vshDebug(ctl, VSH_ERR_DEBUG, "Pool autostart flag value: %d\n",
+                 autostart);
+        if (autostart < 0)
+            vshPrint(ctl, "%-15s %s\n", _("Autostart:"), _("no autostart"));
+        else
+            vshPrint(ctl, "%-15s %s\n", _("Autostart:"), autostart ? _("yes") : _("no"));
 
-    /* Display an appropriate error message then cleanup and return */
-    switch (errno) {
-    case ENOMEM:
-        /* Couldn't allocate memory */
-        vshError(ctl, "%s", _("Out of memory"));
-        break;
-    default:
-        /* Some other error */
-        vshError(ctl, _("virAsprintf failed (errno %d)"), errno);
-    }
-    functionReturn = false;
+        if (info.state == VIR_STORAGE_POOL_RUNNING ||
+            info.state == VIR_STORAGE_POOL_DEGRADED) {
+            val = prettyCapacity(info.capacity, &unit);
+            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
 
-cleanup:
+            val = prettyCapacity(info.allocation, &unit);
+            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
 
-    /* Safely free the memory allocated in this function */
-    for (i = 0; i < numVolumes; i++) {
-        /* Cleanup the memory for one volume info structure per loop */
-        VIR_FREE(volInfoTexts[i].path);
-        VIR_FREE(volInfoTexts[i].type);
-        VIR_FREE(volInfoTexts[i].capacity);
-        VIR_FREE(volInfoTexts[i].allocation);
-        VIR_FREE(activeNames[i]);
+            val = prettyCapacity(info.available, &unit);
+            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Available:"), val, unit);
+        }
+    } else {
+        ret = false;
     }
 
-    /* Cleanup remaining memory */
-    VIR_FREE(outputStr);
-    VIR_FREE(volInfoTexts);
-    VIR_FREE(activeNames);
     virStoragePoolFree(pool);
-
-    /* Return the desired value */
-    return functionReturn;
+    return ret;
 }
 
 
 /*
- * "vol-name" command
+ * "pool-name" command
  */
-static const vshCmdInfo info_vol_name[] = {
-    {"help", N_("returns the volume name for a given volume key or path")},
+static const vshCmdInfo info_pool_name[] = {
+    {"help", N_("convert a pool UUID to pool name")},
     {"desc", ""},
     {NULL, NULL}
 };
 
-static const vshCmdOptDef opts_vol_name[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume key or path")},
+static const vshCmdOptDef opts_pool_name[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool uuid")},
     {NULL, 0, 0, NULL}
 };
 
 static bool
-cmdVolName(vshControl *ctl, const vshCmd *cmd)
+cmdPoolName(vshControl *ctl, const vshCmd *cmd)
 {
-    virStorageVolPtr vol;
+    virStoragePoolPtr pool;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;
-
-    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
-                                   VSH_BYUUID)))
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                           VSH_BYUUID)))
         return false;
 
-    vshPrint(ctl, "%s\n", virStorageVolGetName(vol));
-    virStorageVolFree(vol);
+    vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
+    virStoragePoolFree(pool);
     return true;
 }
 
 
 /*
- * "vol-pool" command
+ * "pool-start" command
  */
-static const vshCmdInfo info_vol_pool[] = {
-    {"help", N_("returns the storage pool for a given volume key or path")},
-    {"desc", ""},
+static const vshCmdInfo info_pool_start[] = {
+    {"help", N_("start a (previously defined) inactive pool")},
+    {"desc", N_("Start a pool.")},
     {NULL, NULL}
 };
 
-static const vshCmdOptDef opts_vol_pool[] = {
-    {"uuid", VSH_OT_BOOL, 0, N_("return the pool uuid rather than pool name")},
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume key or path")},
+static const vshCmdOptDef opts_pool_start[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name or uuid of the inactive pool")},
     {NULL, 0, 0, NULL}
 };
 
 static bool
-cmdVolPool(vshControl *ctl, const vshCmd *cmd)
+cmdPoolStart(vshControl *ctl, const vshCmd *cmd)
 {
     virStoragePoolPtr pool;
-    virStorageVolPtr vol;
-    char uuid[VIR_UUID_STRING_BUFLEN];
+    bool ret = true;
+    const char *name = NULL;
 
-    /* Check the connection to libvirtd daemon is still working */
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;
 
-    /* Use the supplied string to locate the volume */
-    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
-                                   VSH_BYUUID))) {
-        return false;
-    }
-
-    /* Look up the parent storage pool for the volume */
-    pool = virStoragePoolLookupByVolume(vol);
-    if (pool == NULL) {
-        vshError(ctl, "%s", _("failed to get parent pool"));
-        virStorageVolFree(vol);
-        return false;
-    }
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+         return false;
 
-    /* Return the requested details of the parent storage pool */
-    if (vshCommandOptBool(cmd, "uuid")) {
-        /* Retrieve and return pool UUID string */
-        if (virStoragePoolGetUUIDString(pool, &uuid[0]) == 0)
-            vshPrint(ctl, "%s\n", uuid);
+    if (virStoragePoolCreate(pool, 0) == 0) {
+        vshPrint(ctl, _("Pool %s started\n"), name);
     } else {
-        /* Return the storage pool name */
-        vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
+        vshError(ctl, _("Failed to start pool %s"), name);
+        ret = false;
     }
 
-    /* Cleanup */
-    virStorageVolFree(vol);
     virStoragePoolFree(pool);
-    return true;
+    return ret;
 }
 
-
 /*
- * "vol-key" command
+ * "pool-undefine" command
  */
-static const vshCmdInfo info_vol_key[] = {
-    {"help", N_("returns the volume key for a given volume name or path")},
-    {"desc", ""},
+static const vshCmdInfo info_pool_undefine[] = {
+    {"help", N_("undefine an inactive pool")},
+    {"desc", N_("Undefine the configuration for an inactive pool.")},
     {NULL, NULL}
 };
 
-static const vshCmdOptDef opts_vol_key[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume name or path")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+static const vshCmdOptDef opts_pool_undefine[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
     {NULL, 0, 0, NULL}
 };
 
 static bool
-cmdVolKey(vshControl *ctl, const vshCmd *cmd)
+cmdPoolUndefine(vshControl *ctl, const vshCmd *cmd)
 {
-    virStorageVolPtr vol;
+    virStoragePoolPtr pool;
+    bool ret = true;
+    const char *name;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;
 
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
         return false;
 
-    vshPrint(ctl, "%s\n", virStorageVolGetKey(vol));
-    virStorageVolFree(vol);
-    return true;
-}
+    if (virStoragePoolUndefine(pool) == 0) {
+        vshPrint(ctl, _("Pool %s has been undefined\n"), name);
+    } else {
+        vshError(ctl, _("Failed to undefine pool %s"), name);
+        ret = false;
+    }
 
+    virStoragePoolFree(pool);
+    return ret;
+}
 
 
 /*
- * "vol-path" command
+ * "pool-uuid" command
  */
-static const vshCmdInfo info_vol_path[] = {
-    {"help", N_("returns the volume path for a given volume name or key")},
+static const vshCmdInfo info_pool_uuid[] = {
+    {"help", N_("convert a pool name to pool UUID")},
     {"desc", ""},
     {NULL, NULL}
 };
 
-static const vshCmdOptDef opts_vol_path[] = {
-    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume name or key")},
-    {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+static const vshCmdOptDef opts_pool_uuid[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
     {NULL, 0, 0, NULL}
 };
 
 static bool
-cmdVolPath(vshControl *ctl, const vshCmd *cmd)
+cmdPoolUuid(vshControl *ctl, const vshCmd *cmd)
 {
-    virStorageVolPtr vol;
-    char * StorageVolPath;
+    virStoragePoolPtr pool;
+    char uuid[VIR_UUID_STRING_BUFLEN];
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;
 
-    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) {
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                           VSH_BYNAME)))
         return false;
-    }
 
-    if ((StorageVolPath = virStorageVolGetPath(vol)) == NULL) {
-        virStorageVolFree(vol);
-        return false;
-    }
+    if (virStoragePoolGetUUIDString(pool, uuid) != -1)
+        vshPrint(ctl, "%s\n", uuid);
+    else
+        vshError(ctl, "%s", _("failed to get pool UUID"));
 
-    vshPrint(ctl, "%s\n", StorageVolPath);
-    VIR_FREE(StorageVolPath);
-    virStorageVolFree(vol);
+    virStoragePoolFree(pool);
     return true;
 }
 
-
 /*
  * "secret-define" command
  */
@@ -9618,66 +8240,6 @@ vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
     return pool;
 }
 
-static virStorageVolPtr
-vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
-                   const char *optname,
-                   const char *pooloptname,
-                   const char **name, int flag)
-{
-    virStorageVolPtr vol = NULL;
-    virStoragePoolPtr pool = NULL;
-    const char *n = NULL, *p = NULL;
-
-    if (vshCommandOptString(cmd, optname, &n) <= 0)
-        return NULL;
-
-    if (pooloptname != NULL && vshCommandOptString(cmd, pooloptname, &p) < 0) {
-        vshError(ctl, "%s", _("missing option"));
-        return NULL;
-    }
-
-    if (p)
-        pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flag);
-
-    vshDebug(ctl, VSH_ERR_DEBUG, "%s: found option <%s>: %s\n",
-             cmd->def->name, optname, n);
-
-    if (name)
-        *name = n;
-
-    /* try it by name */
-    if (pool && (flag & VSH_BYNAME)) {
-        vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol name\n",
-                 cmd->def->name, optname);
-        vol = virStorageVolLookupByName(pool, n);
-    }
-    /* try it by key */
-    if (vol == NULL && (flag & VSH_BYUUID)) {
-        vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol key\n",
-                 cmd->def->name, optname);
-        vol = virStorageVolLookupByKey(ctl->conn, n);
-    }
-    /* try it by path */
-    if (vol == NULL && (flag & VSH_BYUUID)) {
-        vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol path\n",
-                 cmd->def->name, optname);
-        vol = virStorageVolLookupByPath(ctl->conn, n);
-    }
-
-    if (!vol) {
-        if (pool)
-            vshError(ctl, _("failed to get vol '%s'"), n);
-        else
-            vshError(ctl, _("failed to get vol '%s', specifying --%s "
-                            "might help"), n, pooloptname);
-    }
-
-    if (pool)
-        virStoragePoolFree(pool);
-
-    return vol;
-}
-
 static virSecretPtr
 vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name)
 {
@@ -11171,6 +9733,8 @@ static const vshCmdDef storagePoolCmds[] = {
     {NULL, NULL, NULL, NULL, 0}
 };
 
+#include "virsh-volume.c"
+
 static const vshCmdDef storageVolCmds[] = {
     {"vol-clone", cmdVolClone, opts_vol_clone, info_vol_clone, 0},
     {"vol-create-as", cmdVolCreateAs, opts_vol_create_as,
-- 
1.7.7.3




More information about the libvir-list mailing list