2012-07-24 08:44:49 +00:00
|
|
|
/*
|
|
|
|
* virsh-volume.c: Commands to manage storage volume
|
|
|
|
*
|
virsh: use more compact VIR_ENUM_IMPL
Dan Berrange suggested that using VIR_ENUM_IMPL is more compact
than open-coding switch statements, and still just as forceful
at making us remember to update lists if we add enum values
in the future. Make this change throughout virsh.
Sure enough, doing this change caught that we missed at least
VIR_STORAGE_VOL_NETDIR.
* tools/virsh-domain-monitor.c (vshDomainIOErrorToString)
(vshDomainControlStateToString, vshDomainStateToString)
(vshDomainStateReasonToString): Change switch to enum lookup.
(cmdDomControl, cmdDominfo): Update caller.
* tools/virsh-domain.c (vshDomainVcpuStateToString)
(vshDomainEventToString, vshDomainEventDetailToString): Change
switch to enum lookup.
(vshDomainBlockJobToString, vshDomainJobToString): New functions.
(cmdVcpuinfo, cmdBlockJob, cmdDomjobinfo, cmdEvent): Update
callers.
* tools/virsh-network.c (vshNetworkEventToString): Change switch
to enum lookup.
* tools/virsh-pool.c (vshStoragePoolStateToString): New function.
(cmdPoolList, cmdPoolInfo): Update callers.
* tools/virsh-volume.c (vshVolumeTypeToString): Change switch to
enum lookup.
(cmdVolInfo, cmdVolList): Update callers.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-21 19:55:06 +00:00
|
|
|
* Copyright (C) 2005, 2007-2014 Red Hat, Inc.
|
2012-07-24 08:44:49 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-24 08:44:49 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* Daniel Veillard <veillard@redhat.com>
|
|
|
|
* Karel Zak <kzak@redhat.com>
|
|
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-08-20 23:41:24 +00:00
|
|
|
#include <config.h>
|
|
|
|
#include "virsh-volume.h"
|
2012-07-24 08:44:49 +00:00
|
|
|
|
2012-08-20 23:41:24 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xpath.h>
|
|
|
|
#include <libxml/xmlsave.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 17:44:57 +00:00
|
|
|
#include "virutil.h"
|
2012-08-20 23:41:24 +00:00
|
|
|
#include "virfile.h"
|
|
|
|
#include "virsh-pool.h"
|
2012-12-13 18:13:21 +00:00
|
|
|
#include "virxml.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2012-08-20 23:41:24 +00:00
|
|
|
|
|
|
|
virStorageVolPtr
|
2012-07-24 08:44:49 +00:00
|
|
|
vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
|
|
|
|
const char *optname,
|
|
|
|
const char *pooloptname,
|
2012-08-20 23:41:24 +00:00
|
|
|
const char **name, unsigned int flags)
|
2012-07-24 08:44:49 +00:00
|
|
|
{
|
|
|
|
virStorageVolPtr vol = NULL;
|
|
|
|
virStoragePoolPtr pool = NULL;
|
|
|
|
const char *n = NULL, *p = NULL;
|
2012-08-20 23:41:24 +00:00
|
|
|
virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL);
|
2012-07-24 08:44:49 +00:00
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (pooloptname != NULL &&
|
|
|
|
vshCommandOptStringReq(ctl, cmd, pooloptname, &p) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
return NULL;
|
|
|
|
|
2014-03-03 14:21:37 +00:00
|
|
|
if (p) {
|
|
|
|
if (!(pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flags)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virStoragePoolIsActive(pool) != 1) {
|
|
|
|
vshError(ctl, _("pool '%s' is not active"), p);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
vshDebug(ctl, VSH_ERR_DEBUG, "%s: found option <%s>: %s\n",
|
|
|
|
cmd->def->name, optname, n);
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
*name = n;
|
|
|
|
|
|
|
|
/* try it by name */
|
2012-08-20 23:41:24 +00:00
|
|
|
if (pool && (flags & VSH_BYNAME)) {
|
2012-07-24 08:44:49 +00:00
|
|
|
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol name\n",
|
|
|
|
cmd->def->name, optname);
|
|
|
|
vol = virStorageVolLookupByName(pool, n);
|
|
|
|
}
|
|
|
|
/* try it by key */
|
2012-08-20 23:41:24 +00:00
|
|
|
if (!vol && (flags & VSH_BYUUID)) {
|
2012-07-24 08:44:49 +00:00
|
|
|
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 */
|
2012-08-20 23:41:24 +00:00
|
|
|
if (!vol && (flags & VSH_BYUUID)) {
|
2012-07-24 08:44:49 +00:00
|
|
|
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol path\n",
|
|
|
|
cmd->def->name, optname);
|
|
|
|
vol = virStorageVolLookupByPath(ctl->conn, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vol) {
|
2013-03-22 11:32:32 +00:00
|
|
|
if (pool || !pooloptname)
|
2012-07-24 08:44:49 +00:00
|
|
|
vshError(ctl, _("failed to get vol '%s'"), n);
|
|
|
|
else
|
|
|
|
vshError(ctl, _("failed to get vol '%s', specifying --%s "
|
|
|
|
"might help"), n, pooloptname);
|
|
|
|
}
|
|
|
|
|
2014-05-30 12:44:55 +00:00
|
|
|
/* If the pool was specified, then make sure that the returned
|
|
|
|
* volume is from the given pool */
|
|
|
|
if (pool && vol) {
|
|
|
|
virStoragePoolPtr volpool = NULL;
|
|
|
|
|
|
|
|
if ((volpool = virStoragePoolLookupByVolume(vol))) {
|
|
|
|
if (STRNEQ(virStoragePoolGetName(volpool),
|
|
|
|
virStoragePoolGetName(pool))) {
|
|
|
|
vshResetLibvirtError();
|
|
|
|
vshError(ctl,
|
|
|
|
_("Requested volume '%s' is not in pool '%s'"),
|
|
|
|
n, virStoragePoolGetName(pool));
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
vol = NULL;
|
|
|
|
}
|
|
|
|
virStoragePoolFree(volpool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-24 08:44:49 +00:00
|
|
|
if (pool)
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
|
|
|
|
return vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-create-as" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_create_as[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("create a volume from a set of args")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Create a vol.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_create_as[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("pool name")
|
|
|
|
},
|
|
|
|
{.name = "name",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("name of the volume")
|
|
|
|
},
|
|
|
|
{.name = "capacity",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("size of the vol, as scaled integer (default bytes)")
|
|
|
|
},
|
|
|
|
{.name = "allocation",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("initial allocation size, as scaled integer (default bytes)")
|
|
|
|
},
|
|
|
|
{.name = "format",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("file format type raw,bochs,qcow,qcow2,qed,vmdk")
|
|
|
|
},
|
|
|
|
{.name = "backing-vol",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("the backing volume if taking a snapshot")
|
|
|
|
},
|
|
|
|
{.name = "backing-vol-format",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("format of backing volume if taking a snapshot")
|
|
|
|
},
|
|
|
|
{.name = "prealloc-metadata",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("preallocate metadata (for qcow2 instead of full allocation)")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
2012-12-05 10:48:08 +00:00
|
|
|
unsigned long flags = 0;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
2012-12-05 10:48:08 +00:00
|
|
|
if (vshCommandOptBool(cmd, "prealloc-metadata"))
|
|
|
|
flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
|
2013-06-04 08:16:02 +00:00
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
|
2012-07-24 08:44:49 +00:00
|
|
|
return false;
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "capacity", &capacityStr) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "format", &format) < 0 ||
|
|
|
|
vshCommandOptStringReq(ctl, cmd, "backing-vol", &snapshotStrVol) < 0 ||
|
|
|
|
vshCommandOptStringReq(ctl, cmd, "backing-vol-format",
|
|
|
|
&snapshotStrFormat) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, "<volume>\n");
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAdjustIndent(&buf, 2);
|
|
|
|
virBufferAsprintf(&buf, "<name>%s</name>\n", name);
|
|
|
|
virBufferAsprintf(&buf, "<capacity>%llu</capacity>\n", capacity);
|
2012-07-24 08:44:49 +00:00
|
|
|
if (allocationStr)
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAsprintf(&buf, "<allocation>%llu</allocation>\n", allocation);
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
if (format) {
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAddLit(&buf, "<target>\n");
|
|
|
|
virBufferAdjustIndent(&buf, 2);
|
|
|
|
virBufferAsprintf(&buf, "<format type='%s'/>\n", format);
|
|
|
|
virBufferAdjustIndent(&buf, -2);
|
|
|
|
virBufferAddLit(&buf, "</target>\n");
|
2012-07-24 08:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAddLit(&buf, "<backingStore>\n");
|
|
|
|
virBufferAdjustIndent(&buf, 2);
|
|
|
|
virBufferAsprintf(&buf, "<path>%s</path>\n", snapshotStrVolPath);
|
2012-07-24 08:44:49 +00:00
|
|
|
if (snapshotStrFormat)
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAsprintf(&buf, "<format type='%s'/>\n",
|
2013-11-19 22:50:56 +00:00
|
|
|
snapshotStrFormat);
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAdjustIndent(&buf, -2);
|
|
|
|
virBufferAddLit(&buf, "</backingStore>\n");
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* Cleanup snapshot allocations */
|
|
|
|
VIR_FREE(snapshotStrVolPath);
|
|
|
|
virStorageVolFree(snapVol);
|
|
|
|
}
|
|
|
|
|
2014-03-12 23:52:07 +00:00
|
|
|
virBufferAdjustIndent(&buf, -2);
|
2012-07-24 08:44:49 +00:00
|
|
|
virBufferAddLit(&buf, "</volume>\n");
|
|
|
|
|
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
xml = virBufferContentAndReset(&buf);
|
2012-12-05 10:48:08 +00:00
|
|
|
vol = virStorageVolCreateXML(pool, xml, flags);
|
2012-07-24 08:44:49 +00:00
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("create a vol from an XML file")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Create a vol.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_create[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("pool name")
|
|
|
|
},
|
|
|
|
{.name = "file",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("file containing an XML vol description")
|
|
|
|
},
|
|
|
|
{.name = "prealloc-metadata",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("preallocate metadata (for qcow2 instead of full allocation)")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolCreate(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
const char *from = NULL;
|
2013-01-18 15:40:08 +00:00
|
|
|
bool ret = false;
|
2012-12-05 10:48:08 +00:00
|
|
|
unsigned int flags = 0;
|
2013-01-18 15:40:08 +00:00
|
|
|
char *buffer = NULL;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
2012-12-05 10:48:08 +00:00
|
|
|
if (vshCommandOptBool(cmd, "prealloc-metadata"))
|
|
|
|
flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
|
2013-06-04 08:16:02 +00:00
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
|
2012-07-24 08:44:49 +00:00
|
|
|
return false;
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
|
|
|
|
goto cleanup;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) {
|
2013-01-18 15:40:08 +00:00
|
|
|
vshSaveLibvirtError();
|
|
|
|
goto cleanup;
|
2012-07-24 08:44:49 +00:00
|
|
|
}
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if ((vol = virStorageVolCreateXML(pool, buffer, flags))) {
|
2012-07-24 08:44:49 +00:00
|
|
|
vshPrint(ctl, _("Vol %s created from %s\n"),
|
|
|
|
virStorageVolGetName(vol), from);
|
|
|
|
virStorageVolFree(vol);
|
2013-01-18 15:40:08 +00:00
|
|
|
ret = true;
|
2012-07-24 08:44:49 +00:00
|
|
|
} else {
|
|
|
|
vshError(ctl, _("Failed to create vol from %s"), from);
|
|
|
|
}
|
2013-01-18 15:40:08 +00:00
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2013-01-18 15:40:08 +00:00
|
|
|
VIR_FREE(buffer);
|
|
|
|
virStoragePoolFree(pool);
|
2012-07-24 08:44:49 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-create-from" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_create_from[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("create a vol, using another volume as input")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Create a vol from an existing volume.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_create_from[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "file",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("file containing an XML vol description")
|
|
|
|
},
|
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("input vol name or key")
|
|
|
|
},
|
|
|
|
{.name = "inputpool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid of the input volume's pool")
|
|
|
|
},
|
|
|
|
{.name = "prealloc-metadata",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("preallocate metadata (for qcow2 instead of full allocation)")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
2012-12-05 10:48:08 +00:00
|
|
|
unsigned int flags = 0;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-05 10:48:08 +00:00
|
|
|
if (vshCommandOptBool(cmd, "prealloc-metadata"))
|
|
|
|
flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
|
2013-01-18 15:40:08 +00:00
|
|
|
|
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) {
|
|
|
|
vshReportError(ctl);
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-12-05 10:48:08 +00:00
|
|
|
newvol = virStorageVolCreateXMLFrom(pool, buffer, inputvol, flags);
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
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;
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
VIR_FREE(buffer);
|
|
|
|
if (pool)
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
if (inputvol)
|
|
|
|
virStorageVolFree(inputvol);
|
|
|
|
if (newvol)
|
|
|
|
virStorageVolFree(newvol);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static xmlChar *
|
2013-01-18 15:33:34 +00:00
|
|
|
vshMakeCloneXML(const char *origxml, const char *newname)
|
2012-07-24 08:44:49 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
return newxml;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-clone" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_clone[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("clone a volume.")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Clone an existing volume.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_clone[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("orig vol name or key")
|
|
|
|
},
|
|
|
|
{.name = "newname",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("clone name")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "prealloc-metadata",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("preallocate metadata (for qcow2 instead of full allocation)")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
2012-12-05 10:48:08 +00:00
|
|
|
unsigned int flags = 0;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-05 10:48:08 +00:00
|
|
|
if (vshCommandOptBool(cmd, "prealloc-metadata"))
|
|
|
|
flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
|
|
|
|
|
2012-07-24 08:44:49 +00:00
|
|
|
origpool = virStoragePoolLookupByVolume(origvol);
|
|
|
|
if (!origpool) {
|
|
|
|
vshError(ctl, "%s", _("failed to get parent pool"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "newname", &name) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
origxml = virStorageVolGetXMLDesc(origvol, 0);
|
|
|
|
if (!origxml)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-01-18 15:33:34 +00:00
|
|
|
newxml = vshMakeCloneXML(origxml, name);
|
2012-07-24 08:44:49 +00:00
|
|
|
if (!newxml) {
|
|
|
|
vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-12-05 10:48:08 +00:00
|
|
|
newvol = virStorageVolCreateXMLFrom(origpool, (char *) newxml, origvol, flags);
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
2013-04-30 12:19:49 +00:00
|
|
|
.data = N_("upload file contents to a volume")
|
2013-02-07 15:25:10 +00:00
|
|
|
},
|
|
|
|
{.name = "desc",
|
2013-04-30 12:19:49 +00:00
|
|
|
.data = N_("Upload file contents to a volume")
|
2013-02-07 15:25:10 +00:00
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_upload[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "file",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("file")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "offset",
|
|
|
|
.type = VSH_OT_INT,
|
|
|
|
.help = N_("volume offset to upload to")
|
|
|
|
},
|
|
|
|
{.name = "length",
|
|
|
|
.type = VSH_OT_INT,
|
|
|
|
.help = N_("amount of data to upload")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2014-06-04 09:08:08 +00:00
|
|
|
if (vshCommandOptULongLongWrap(cmd, "offset", &offset) < 0) {
|
2012-07-24 08:44:49 +00:00
|
|
|
vshError(ctl, _("Unable to parse integer"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-04 09:08:08 +00:00
|
|
|
if (vshCommandOptULongLongWrap(cmd, "length", &length) < 0) {
|
2012-07-24 08:44:49 +00:00
|
|
|
vshError(ctl, _("Unable to parse integer"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((fd = open(file, O_RDONLY)) < 0) {
|
|
|
|
vshError(ctl, _("cannot read %s"), file);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-09-29 09:24:11 +00:00
|
|
|
if (!(st = virStreamNew(ctl->conn, 0))) {
|
|
|
|
vshError(ctl, _("cannot create a new stream"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
if (vol)
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
if (st)
|
|
|
|
virStreamFree(st);
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-download" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_download[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
2013-04-30 12:19:49 +00:00
|
|
|
.data = N_("download volume contents to a file")
|
2013-02-07 15:25:10 +00:00
|
|
|
},
|
|
|
|
{.name = "desc",
|
2013-04-30 12:19:49 +00:00
|
|
|
.data = N_("Download volume contents to a file")
|
2013-02-07 15:25:10 +00:00
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_download[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "file",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("file")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "offset",
|
|
|
|
.type = VSH_OT_INT,
|
|
|
|
.help = N_("volume offset to download from")
|
|
|
|
},
|
|
|
|
{.name = "length",
|
|
|
|
.type = VSH_OT_INT,
|
|
|
|
.help = N_("amount of data to download")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2014-07-15 12:26:28 +00:00
|
|
|
if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
|
|
|
|
vshError(ctl, _("Unable to parse offset value"));
|
2012-07-24 08:44:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-04 09:08:08 +00:00
|
|
|
if (vshCommandOptULongLongWrap(cmd, "length", &length) < 0) {
|
2014-07-15 12:26:28 +00:00
|
|
|
vshError(ctl, _("Unable to parse length value"));
|
2012-07-24 08:44:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
|
|
|
|
return false;
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-09-29 09:24:11 +00:00
|
|
|
if (!(st = virStreamNew(ctl->conn, 0))) {
|
|
|
|
vshError(ctl, _("cannot create a new stream"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("delete a vol")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Delete a given vol.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_delete[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolDelete(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
bool ret = true;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("wipe a vol")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Ensure data previously on a volume is not accessible to future reads")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_wipe[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "algorithm",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("perform selected wiping algorithm")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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 (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-18 15:40:08 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "algorithm", &algorithm_str) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
2014-03-25 06:53:59 +00:00
|
|
|
out:
|
2012-07-24 08:44:49 +00:00
|
|
|
virStorageVolFree(vol);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-11-12 15:13:41 +00:00
|
|
|
|
virsh: use more compact VIR_ENUM_IMPL
Dan Berrange suggested that using VIR_ENUM_IMPL is more compact
than open-coding switch statements, and still just as forceful
at making us remember to update lists if we add enum values
in the future. Make this change throughout virsh.
Sure enough, doing this change caught that we missed at least
VIR_STORAGE_VOL_NETDIR.
* tools/virsh-domain-monitor.c (vshDomainIOErrorToString)
(vshDomainControlStateToString, vshDomainStateToString)
(vshDomainStateReasonToString): Change switch to enum lookup.
(cmdDomControl, cmdDominfo): Update caller.
* tools/virsh-domain.c (vshDomainVcpuStateToString)
(vshDomainEventToString, vshDomainEventDetailToString): Change
switch to enum lookup.
(vshDomainBlockJobToString, vshDomainJobToString): New functions.
(cmdVcpuinfo, cmdBlockJob, cmdDomjobinfo, cmdEvent): Update
callers.
* tools/virsh-network.c (vshNetworkEventToString): Change switch
to enum lookup.
* tools/virsh-pool.c (vshStoragePoolStateToString): New function.
(cmdPoolList, cmdPoolInfo): Update callers.
* tools/virsh-volume.c (vshVolumeTypeToString): Change switch to
enum lookup.
(cmdVolInfo, cmdVolList): Update callers.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-21 19:55:06 +00:00
|
|
|
VIR_ENUM_DECL(vshStorageVol)
|
|
|
|
VIR_ENUM_IMPL(vshStorageVol,
|
|
|
|
VIR_STORAGE_VOL_LAST,
|
|
|
|
N_("file"),
|
|
|
|
N_("block"),
|
|
|
|
N_("dir"),
|
|
|
|
N_("network"),
|
|
|
|
N_("netdir"))
|
|
|
|
|
2013-11-12 15:13:41 +00:00
|
|
|
static const char *
|
|
|
|
vshVolumeTypeToString(int type)
|
|
|
|
{
|
virsh: use more compact VIR_ENUM_IMPL
Dan Berrange suggested that using VIR_ENUM_IMPL is more compact
than open-coding switch statements, and still just as forceful
at making us remember to update lists if we add enum values
in the future. Make this change throughout virsh.
Sure enough, doing this change caught that we missed at least
VIR_STORAGE_VOL_NETDIR.
* tools/virsh-domain-monitor.c (vshDomainIOErrorToString)
(vshDomainControlStateToString, vshDomainStateToString)
(vshDomainStateReasonToString): Change switch to enum lookup.
(cmdDomControl, cmdDominfo): Update caller.
* tools/virsh-domain.c (vshDomainVcpuStateToString)
(vshDomainEventToString, vshDomainEventDetailToString): Change
switch to enum lookup.
(vshDomainBlockJobToString, vshDomainJobToString): New functions.
(cmdVcpuinfo, cmdBlockJob, cmdDomjobinfo, cmdEvent): Update
callers.
* tools/virsh-network.c (vshNetworkEventToString): Change switch
to enum lookup.
* tools/virsh-pool.c (vshStoragePoolStateToString): New function.
(cmdPoolList, cmdPoolInfo): Update callers.
* tools/virsh-volume.c (vshVolumeTypeToString): Change switch to
enum lookup.
(cmdVolInfo, cmdVolList): Update callers.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-21 19:55:06 +00:00
|
|
|
const char *str = vshStorageVolTypeToString(type);
|
|
|
|
return str ? _(str) : _("unknown");
|
2013-11-12 15:13:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-24 08:44:49 +00:00
|
|
|
/*
|
|
|
|
* "vol-info" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_info[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("storage vol information")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Returns basic information about the storage vol.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_info[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStorageVolInfo info;
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2013-11-12 15:13:41 +00:00
|
|
|
vshPrint(ctl, "%-15s %s\n", _("Type:"),
|
virsh: use more compact VIR_ENUM_IMPL
Dan Berrange suggested that using VIR_ENUM_IMPL is more compact
than open-coding switch statements, and still just as forceful
at making us remember to update lists if we add enum values
in the future. Make this change throughout virsh.
Sure enough, doing this change caught that we missed at least
VIR_STORAGE_VOL_NETDIR.
* tools/virsh-domain-monitor.c (vshDomainIOErrorToString)
(vshDomainControlStateToString, vshDomainStateToString)
(vshDomainStateReasonToString): Change switch to enum lookup.
(cmdDomControl, cmdDominfo): Update caller.
* tools/virsh-domain.c (vshDomainVcpuStateToString)
(vshDomainEventToString, vshDomainEventDetailToString): Change
switch to enum lookup.
(vshDomainBlockJobToString, vshDomainJobToString): New functions.
(cmdVcpuinfo, cmdBlockJob, cmdDomjobinfo, cmdEvent): Update
callers.
* tools/virsh-network.c (vshNetworkEventToString): Change switch
to enum lookup.
* tools/virsh-pool.c (vshStoragePoolStateToString): New function.
(cmdPoolList, cmdPoolInfo): Update callers.
* tools/virsh-volume.c (vshVolumeTypeToString): Change switch to
enum lookup.
(cmdVolInfo, cmdVolList): Update callers.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-21 19:55:06 +00:00
|
|
|
vshVolumeTypeToString(info.type));
|
2012-07-24 08:44:49 +00:00
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
val = vshPrettyCapacity(info.capacity, &unit);
|
2012-07-24 08:44:49 +00:00
|
|
|
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
|
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
val = vshPrettyCapacity(info.allocation, &unit);
|
2012-07-24 08:44:49 +00:00
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("resize a vol")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Resizes a storage volume.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_resize[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "capacity",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("new capacity for the vol, as scaled integer (default bytes)")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "allocate",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("allocate the new capacity, rather than leaving it sparse")
|
|
|
|
},
|
|
|
|
{.name = "delta",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("use capacity as a delta to current size, rather than the new size")
|
|
|
|
},
|
|
|
|
{.name = "shrink",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("allow the resize to shrink the volume")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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 (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
|
|
|
|
return false;
|
|
|
|
|
2013-05-24 03:59:14 +00:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "capacity", &capacityStr) < 0)
|
2012-07-24 08:44:49 +00:00
|
|
|
goto cleanup;
|
|
|
|
virSkipSpaces(&capacityStr);
|
|
|
|
if (*capacityStr == '-') {
|
|
|
|
/* The API always requires a positive value; but we allow a
|
|
|
|
* negative value for convenience. */
|
2014-08-20 11:00:30 +00:00
|
|
|
if (delta && vshCommandOptBool(cmd, "shrink")) {
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
virStorageVolFree(vol);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-dumpxml" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_dumpxml[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("vol information in XML")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Output the vol information as an XML dump to stdout.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_dumpxml[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("vol name, key or path")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
bool ret = true;
|
|
|
|
char *dump;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-09-04 15:32:57 +00:00
|
|
|
static int
|
|
|
|
vshStorageVolSorter(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
virStorageVolPtr *va = (virStorageVolPtr *) a;
|
|
|
|
virStorageVolPtr *vb = (virStorageVolPtr *) b;
|
|
|
|
|
|
|
|
if (*va && !*vb)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!*va)
|
|
|
|
return *vb != NULL;
|
|
|
|
|
|
|
|
return vshStrcasecmp(virStorageVolGetName(*va),
|
|
|
|
virStorageVolGetName(*vb));
|
|
|
|
}
|
|
|
|
|
|
|
|
struct vshStorageVolList {
|
|
|
|
virStorageVolPtr *vols;
|
|
|
|
size_t nvols;
|
|
|
|
};
|
|
|
|
typedef struct vshStorageVolList *vshStorageVolListPtr;
|
|
|
|
|
|
|
|
static void
|
|
|
|
vshStorageVolListFree(vshStorageVolListPtr list)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-09-04 15:32:57 +00:00
|
|
|
|
|
|
|
if (list && list->vols) {
|
|
|
|
for (i = 0; i < list->nvols; i++) {
|
|
|
|
if (list->vols[i])
|
|
|
|
virStorageVolFree(list->vols[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(list->vols);
|
|
|
|
}
|
|
|
|
VIR_FREE(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static vshStorageVolListPtr
|
|
|
|
vshStorageVolListCollect(vshControl *ctl,
|
|
|
|
virStoragePoolPtr pool,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
vshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list));
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-09-04 15:32:57 +00:00
|
|
|
char **names = NULL;
|
|
|
|
virStorageVolPtr vol = NULL;
|
|
|
|
bool success = false;
|
|
|
|
size_t deleted = 0;
|
|
|
|
int nvols = 0;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-09-13 08:56:07 +00:00
|
|
|
/* try the list with flags support (0.10.2 and later) */
|
2012-09-04 15:32:57 +00:00
|
|
|
if ((ret = virStoragePoolListAllVolumes(pool,
|
|
|
|
&list->vols,
|
|
|
|
flags)) >= 0) {
|
|
|
|
list->nvols = ret;
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if the command is actually supported */
|
2012-09-13 08:56:07 +00:00
|
|
|
if (last_error && last_error->code == VIR_ERR_NO_SUPPORT)
|
2012-09-04 15:32:57 +00:00
|
|
|
goto fallback;
|
|
|
|
|
|
|
|
/* there was an error during the call */
|
|
|
|
vshError(ctl, "%s", _("Failed to list volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
fallback:
|
2012-09-13 08:56:07 +00:00
|
|
|
/* fall back to old method (0.10.1 and older) */
|
2012-09-04 15:32:57 +00:00
|
|
|
vshResetLibvirtError();
|
|
|
|
|
|
|
|
/* Determine the number of volumes in the pool */
|
|
|
|
if ((nvols = virStoragePoolNumOfVolumes(pool)) < 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to list storage volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nvols == 0) {
|
|
|
|
success = true;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Retrieve the list of volume names in the pool */
|
|
|
|
names = vshCalloc(ctl, nvols, sizeof(*names));
|
|
|
|
if ((nvols = virStoragePoolListVolumes(pool, names, nvols)) < 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to list storage volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
list->vols = vshMalloc(ctl, sizeof(virStorageVolPtr) * (nvols));
|
|
|
|
list->nvols = 0;
|
|
|
|
|
|
|
|
/* get the vols */
|
|
|
|
for (i = 0; i < nvols; i++) {
|
|
|
|
if (!(vol = virStorageVolLookupByName(pool, names[i])))
|
|
|
|
continue;
|
|
|
|
list->vols[list->nvols++] = vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* truncate the list for not found vols */
|
|
|
|
deleted = nvols - list->nvols;
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
finished:
|
2012-09-04 15:32:57 +00:00
|
|
|
/* sort the list */
|
|
|
|
if (list->vols && list->nvols)
|
|
|
|
qsort(list->vols, list->nvols, sizeof(*list->vols), vshStorageVolSorter);
|
|
|
|
|
|
|
|
if (deleted)
|
|
|
|
VIR_SHRINK_N(list->vols, list->nvols, deleted);
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
if (nvols > 0)
|
|
|
|
for (i = 0; i < nvols; i++)
|
|
|
|
VIR_FREE(names[i]);
|
2012-09-04 15:32:57 +00:00
|
|
|
VIR_FREE(names);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
vshStorageVolListFree(list);
|
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2012-07-24 08:44:49 +00:00
|
|
|
/*
|
|
|
|
* "vol-list" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_list[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("list vols")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Returns list of vols by pool.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_list[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = "details",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("display extended details for volumes")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virStorageVolInfo volumeInfo;
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
char *outputStr = NULL;
|
|
|
|
const char *unit;
|
|
|
|
double val;
|
|
|
|
bool details = vshCommandOptBool(cmd, "details");
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2014-02-21 21:33:30 +00:00
|
|
|
bool ret = false;
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
2012-09-04 15:32:57 +00:00
|
|
|
vshStorageVolListPtr list = NULL;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* Look up the pool information given to us by the user */
|
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
|
|
|
|
return false;
|
|
|
|
|
2012-09-04 15:32:57 +00:00
|
|
|
if (!(list = vshStorageVolListCollect(ctl, pool, 0)))
|
|
|
|
goto cleanup;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
2012-09-04 15:32:57 +00:00
|
|
|
if (list->nvols > 0)
|
|
|
|
volInfoTexts = vshCalloc(ctl, list->nvols, sizeof(*volInfoTexts));
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* Collect the rest of the volume information for display */
|
2012-09-04 15:32:57 +00:00
|
|
|
for (i = 0; i < list->nvols; i++) {
|
2012-07-24 08:44:49 +00:00
|
|
|
/* Retrieve volume info */
|
2012-09-04 15:32:57 +00:00
|
|
|
virStorageVolPtr vol = list->vols[i];
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* 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 */
|
2013-11-12 15:13:41 +00:00
|
|
|
volInfoTexts[i].type = vshStrdup(ctl,
|
virsh: use more compact VIR_ENUM_IMPL
Dan Berrange suggested that using VIR_ENUM_IMPL is more compact
than open-coding switch statements, and still just as forceful
at making us remember to update lists if we add enum values
in the future. Make this change throughout virsh.
Sure enough, doing this change caught that we missed at least
VIR_STORAGE_VOL_NETDIR.
* tools/virsh-domain-monitor.c (vshDomainIOErrorToString)
(vshDomainControlStateToString, vshDomainStateToString)
(vshDomainStateReasonToString): Change switch to enum lookup.
(cmdDomControl, cmdDominfo): Update caller.
* tools/virsh-domain.c (vshDomainVcpuStateToString)
(vshDomainEventToString, vshDomainEventDetailToString): Change
switch to enum lookup.
(vshDomainBlockJobToString, vshDomainJobToString): New functions.
(cmdVcpuinfo, cmdBlockJob, cmdDomjobinfo, cmdEvent): Update
callers.
* tools/virsh-network.c (vshNetworkEventToString): Change switch
to enum lookup.
* tools/virsh-pool.c (vshStoragePoolStateToString): New function.
(cmdPoolList, cmdPoolInfo): Update callers.
* tools/virsh-volume.c (vshVolumeTypeToString): Change switch to
enum lookup.
(cmdVolInfo, cmdVolList): Update callers.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-21 19:55:06 +00:00
|
|
|
vshVolumeTypeToString(volumeInfo.type));
|
2012-07-24 08:44:49 +00:00
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
val = vshPrettyCapacity(volumeInfo.capacity, &unit);
|
2014-02-21 21:33:30 +00:00
|
|
|
if (virAsprintf(&volInfoTexts[i].capacity,
|
|
|
|
"%.2lf %s", val, unit) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
val = vshPrettyCapacity(volumeInfo.allocation, &unit);
|
2014-02-21 21:33:30 +00:00
|
|
|
if (virAsprintf(&volInfoTexts[i].allocation,
|
|
|
|
"%.2lf %s", val, unit) < 0)
|
|
|
|
goto cleanup;
|
2012-07-24 08:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
2012-09-04 15:32:57 +00:00
|
|
|
stringLength = strlen(virStorageVolGetName(list->vols[i]));
|
2012-07-24 08:44:49 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
2013-11-12 14:11:55 +00:00
|
|
|
vshPrintExtra(ctl, " %-20s %-40s\n", _("Name"), _("Path"));
|
|
|
|
vshPrintExtra(ctl, "---------------------------------------"
|
|
|
|
"---------------------------------------\n");
|
2012-09-04 15:32:57 +00:00
|
|
|
for (i = 0; i < list->nvols; i++) {
|
2013-11-12 14:11:55 +00:00
|
|
|
vshPrint(ctl, " %-20s %-40s\n", virStorageVolGetName(list->vols[i]),
|
2012-07-24 08:44:49 +00:00
|
|
|
volInfoTexts[i].path);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup and return */
|
2014-02-21 21:33:30 +00:00
|
|
|
ret = true;
|
2012-07-24 08:44:49 +00:00
|
|
|
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);
|
|
|
|
|
2014-02-21 21:33:30 +00:00
|
|
|
if (virAsprintf(&outputStr,
|
|
|
|
" %%-%lus %%-%lus %%-%lus %%%lus %%%lus\n",
|
|
|
|
(unsigned long) nameStrLength,
|
|
|
|
(unsigned long) pathStrLength,
|
|
|
|
(unsigned long) typeStrLength,
|
|
|
|
(unsigned long) capStrLength,
|
|
|
|
(unsigned long) allocStrLength) < 0)
|
|
|
|
goto cleanup;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* Display the header */
|
|
|
|
vshPrint(ctl, outputStr, _("Name"), _("Path"), _("Type"),
|
|
|
|
("Capacity"), _("Allocation"));
|
|
|
|
for (i = nameStrLength + pathStrLength + typeStrLength
|
|
|
|
+ capStrLength + allocStrLength
|
2013-11-12 14:11:55 +00:00
|
|
|
+ 10; i > 0; i--)
|
2012-07-24 08:44:49 +00:00
|
|
|
vshPrintExtra(ctl, "-");
|
|
|
|
vshPrintExtra(ctl, "\n");
|
|
|
|
|
|
|
|
/* Display the volume info rows */
|
2012-09-04 15:32:57 +00:00
|
|
|
for (i = 0; i < list->nvols; i++) {
|
2012-07-24 08:44:49 +00:00
|
|
|
vshPrint(ctl, outputStr,
|
2012-09-04 15:32:57 +00:00
|
|
|
virStorageVolGetName(list->vols[i]),
|
2012-07-24 08:44:49 +00:00
|
|
|
volInfoTexts[i].path,
|
|
|
|
volInfoTexts[i].type,
|
|
|
|
volInfoTexts[i].capacity,
|
|
|
|
volInfoTexts[i].allocation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup and return */
|
2014-02-21 21:33:30 +00:00
|
|
|
ret = true;
|
2012-07-24 08:44:49 +00:00
|
|
|
|
2014-03-25 06:53:59 +00:00
|
|
|
cleanup:
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* Safely free the memory allocated in this function */
|
2012-09-04 15:32:57 +00:00
|
|
|
if (list && list->nvols) {
|
|
|
|
for (i = 0; i < list->nvols; 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);
|
|
|
|
}
|
2012-07-24 08:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup remaining memory */
|
|
|
|
VIR_FREE(outputStr);
|
|
|
|
VIR_FREE(volInfoTexts);
|
|
|
|
virStoragePoolFree(pool);
|
2012-09-04 15:32:57 +00:00
|
|
|
vshStorageVolListFree(list);
|
2012-07-24 08:44:49 +00:00
|
|
|
|
|
|
|
/* Return the desired value */
|
2014-02-21 21:33:30 +00:00
|
|
|
return ret;
|
2012-07-24 08:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-name" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_vol_name[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("returns the volume name for a given volume key or path")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = ""
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_name[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("volume key or path")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolName(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
|
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("returns the storage pool for a given volume key or path")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = ""
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_pool[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "uuid",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("return the pool uuid rather than pool name")
|
|
|
|
},
|
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("volume key or path")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolPool(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
/* 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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("returns the volume key for a given volume name or path")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = ""
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_key[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("volume name or path")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolKey(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
|
|
|
|
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[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("returns the volume path for a given volume name or key")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = ""
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_vol_path[] = {
|
2013-01-14 14:48:52 +00:00
|
|
|
{.name = "vol",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("volume name or key")
|
|
|
|
},
|
|
|
|
{.name = "pool",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.help = N_("pool name or uuid")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-24 08:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVolPath(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
char * StorageVolPath;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2012-07-23 07:19:04 +00:00
|
|
|
|
2012-08-20 23:41:24 +00:00
|
|
|
const vshCmdDef storageVolCmds[] = {
|
2013-02-07 15:25:10 +00:00
|
|
|
{.name = "vol-clone",
|
|
|
|
.handler = cmdVolClone,
|
|
|
|
.opts = opts_vol_clone,
|
|
|
|
.info = info_vol_clone,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-create-as",
|
|
|
|
.handler = cmdVolCreateAs,
|
|
|
|
.opts = opts_vol_create_as,
|
|
|
|
.info = info_vol_create_as,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-create",
|
|
|
|
.handler = cmdVolCreate,
|
|
|
|
.opts = opts_vol_create,
|
|
|
|
.info = info_vol_create,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-create-from",
|
|
|
|
.handler = cmdVolCreateFrom,
|
|
|
|
.opts = opts_vol_create_from,
|
|
|
|
.info = info_vol_create_from,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-delete",
|
|
|
|
.handler = cmdVolDelete,
|
|
|
|
.opts = opts_vol_delete,
|
|
|
|
.info = info_vol_delete,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-download",
|
|
|
|
.handler = cmdVolDownload,
|
|
|
|
.opts = opts_vol_download,
|
|
|
|
.info = info_vol_download,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-dumpxml",
|
|
|
|
.handler = cmdVolDumpXML,
|
|
|
|
.opts = opts_vol_dumpxml,
|
|
|
|
.info = info_vol_dumpxml,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-info",
|
|
|
|
.handler = cmdVolInfo,
|
|
|
|
.opts = opts_vol_info,
|
|
|
|
.info = info_vol_info,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-key",
|
|
|
|
.handler = cmdVolKey,
|
|
|
|
.opts = opts_vol_key,
|
|
|
|
.info = info_vol_key,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-list",
|
|
|
|
.handler = cmdVolList,
|
|
|
|
.opts = opts_vol_list,
|
|
|
|
.info = info_vol_list,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-name",
|
|
|
|
.handler = cmdVolName,
|
|
|
|
.opts = opts_vol_name,
|
|
|
|
.info = info_vol_name,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-path",
|
|
|
|
.handler = cmdVolPath,
|
|
|
|
.opts = opts_vol_path,
|
|
|
|
.info = info_vol_path,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-pool",
|
|
|
|
.handler = cmdVolPool,
|
|
|
|
.opts = opts_vol_pool,
|
|
|
|
.info = info_vol_pool,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-resize",
|
|
|
|
.handler = cmdVolResize,
|
|
|
|
.opts = opts_vol_resize,
|
|
|
|
.info = info_vol_resize,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-upload",
|
|
|
|
.handler = cmdVolUpload,
|
|
|
|
.opts = opts_vol_upload,
|
|
|
|
.info = info_vol_upload,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "vol-wipe",
|
|
|
|
.handler = cmdVolWipe,
|
|
|
|
.opts = opts_vol_wipe,
|
|
|
|
.info = info_vol_wipe,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 07:19:04 +00:00
|
|
|
};
|