[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