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

Martin Kletzander mkletzan at redhat.com
Wed Jul 25 14:08:05 UTC 2012


On 07/24/2012 11:18 AM, Osier Yang wrote:
> 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,
> 

I noticed just a removal of the function prototype for
vshCommandOptVolBy that is obviously not needed, so ACK.

Martin




More information about the libvir-list mailing list