mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-09 09:14:57 +00:00
resize: add virStorageVolResize() API
Add a new function to allow changing of capacity of storage volumes. Plan out several flags, even if not all of them will be implemented up front. Expose the new command via 'virsh vol-resize'. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
b2e13f9c44
commit
6714fd04d2
@ -2386,6 +2386,17 @@ char * virStorageVolGetXMLDesc (virStorageVolPtr pool,
|
|||||||
|
|
||||||
char * virStorageVolGetPath (virStorageVolPtr vol);
|
char * virStorageVolGetPath (virStorageVolPtr vol);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VIR_STORAGE_VOL_RESIZE_ALLOCATE = 1 << 0, /* force allocation of new size */
|
||||||
|
VIR_STORAGE_VOL_RESIZE_DELTA = 1 << 1, /* size is relative to current */
|
||||||
|
VIR_STORAGE_VOL_RESIZE_SHRINK = 1 << 2, /* allow decrease in capacity */
|
||||||
|
} virStorageVolResizeFlags;
|
||||||
|
|
||||||
|
int virStorageVolResize (virStorageVolPtr vol,
|
||||||
|
long long capacity,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virKeycodeSet:
|
* virKeycodeSet:
|
||||||
*
|
*
|
||||||
|
@ -259,6 +259,7 @@ py_types = {
|
|||||||
'double': ('d', None, "double", "double"),
|
'double': ('d', None, "double", "double"),
|
||||||
'unsigned int': ('i', None, "int", "int"),
|
'unsigned int': ('i', None, "int", "int"),
|
||||||
'unsigned long': ('l', None, "long", "long"),
|
'unsigned long': ('l', None, "long", "long"),
|
||||||
|
'long long': ('l', None, "longlong", "long long"),
|
||||||
'unsigned long long': ('l', None, "longlong", "long long"),
|
'unsigned long long': ('l', None, "longlong", "long long"),
|
||||||
'unsigned char *': ('z', None, "charPtr", "char *"),
|
'unsigned char *': ('z', None, "charPtr", "char *"),
|
||||||
'char *': ('z', None, "charPtr", "char *"),
|
'char *': ('z', None, "charPtr", "char *"),
|
||||||
|
@ -1261,6 +1261,10 @@ typedef int
|
|||||||
unsigned long long offset,
|
unsigned long long offset,
|
||||||
unsigned long long length,
|
unsigned long long length,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
typedef int
|
||||||
|
(*virDrvStorageVolResize) (virStorageVolPtr vol,
|
||||||
|
long long capacity,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
typedef int
|
typedef int
|
||||||
(*virDrvStoragePoolIsActive)(virStoragePoolPtr pool);
|
(*virDrvStoragePoolIsActive)(virStoragePoolPtr pool);
|
||||||
@ -1323,6 +1327,7 @@ struct _virStorageDriver {
|
|||||||
virDrvStorageVolGetInfo volGetInfo;
|
virDrvStorageVolGetInfo volGetInfo;
|
||||||
virDrvStorageVolGetXMLDesc volGetXMLDesc;
|
virDrvStorageVolGetXMLDesc volGetXMLDesc;
|
||||||
virDrvStorageVolGetPath volGetPath;
|
virDrvStorageVolGetPath volGetPath;
|
||||||
|
virDrvStorageVolResize volResize;
|
||||||
virDrvStoragePoolIsActive poolIsActive;
|
virDrvStoragePoolIsActive poolIsActive;
|
||||||
virDrvStoragePoolIsPersistent poolIsPersistent;
|
virDrvStoragePoolIsPersistent poolIsPersistent;
|
||||||
};
|
};
|
||||||
|
@ -12927,6 +12927,82 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virStorageVolResize:
|
||||||
|
* @vol: pointer to storage volume
|
||||||
|
* @capacity: new capacity, in bytes
|
||||||
|
* @flags: bitwise-OR of virStorageVolResizeFlags
|
||||||
|
*
|
||||||
|
* Changes the capacity of the storage volume @vol to @capacity. The
|
||||||
|
* operation will fail if the new capacity requires allocation that would
|
||||||
|
* exceed the remaining free space in the parent pool. The contents of
|
||||||
|
* the new capacity will appear as all zero bytes.
|
||||||
|
*
|
||||||
|
* Normally, the operation will attempt to affect capacity with a minimum
|
||||||
|
* impact on allocation (that is, the default operation favors a sparse
|
||||||
|
* resize). If @flags contains VIR_STORAGE_VOL_RESIZE_ALLOCATE, then the
|
||||||
|
* operation will ensure that allocation is sufficient for the new
|
||||||
|
* capacity; this may make the operation take noticeably longer.
|
||||||
|
*
|
||||||
|
* Normally, the operation treats @capacity as the new size in bytes;
|
||||||
|
* but if @flags contains VIR_STORAGE_RESIZE_DELTA, then @capacity
|
||||||
|
* represents the size difference to add to the current size. It is
|
||||||
|
* up to the storage pool implementation whether unaligned requests are
|
||||||
|
* rounded up to the next valid boundary, or rejected.
|
||||||
|
*
|
||||||
|
* Normally, this operation should only be used to enlarge capacity;
|
||||||
|
* but if @flags contains VIR_STORAGE_RESIZE_SHRINK, it is possible to
|
||||||
|
* attempt a reduction in capacity even though it might cause data loss.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, or -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virStorageVolResize(virStorageVolPtr vol,
|
||||||
|
long long capacity,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virConnectPtr conn;
|
||||||
|
VIR_DEBUG("vol=%p capacity=%lld flags=%x", vol, capacity, flags);
|
||||||
|
|
||||||
|
virResetLastError();
|
||||||
|
|
||||||
|
if (!VIR_IS_STORAGE_VOL(vol)) {
|
||||||
|
virLibStorageVolError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = vol->conn;
|
||||||
|
|
||||||
|
if (conn->flags & VIR_CONNECT_RO) {
|
||||||
|
virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Negative capacity is valid only with both delta and shrink;
|
||||||
|
* zero capacity is valid with either delta or shrink. */
|
||||||
|
if ((capacity < 0 && !(flags & VIR_STORAGE_VOL_RESIZE_DELTA) &&
|
||||||
|
!(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) ||
|
||||||
|
(capacity == 0 && !((flags & VIR_STORAGE_VOL_RESIZE_DELTA) ||
|
||||||
|
(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)))) {
|
||||||
|
virLibStorageVolError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->storageDriver && conn->storageDriver->volResize) {
|
||||||
|
int ret;
|
||||||
|
ret = conn->storageDriver->volResize(vol, capacity, flags);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||||
|
|
||||||
|
error:
|
||||||
|
virDispatchError(vol->conn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virNodeNumOfDevices:
|
* virNodeNumOfDevices:
|
||||||
|
@ -519,6 +519,7 @@ LIBVIRT_0.9.9 {
|
|||||||
LIBVIRT_0.9.10 {
|
LIBVIRT_0.9.10 {
|
||||||
global:
|
global:
|
||||||
virDomainShutdownFlags;
|
virDomainShutdownFlags;
|
||||||
|
virStorageVolResize;
|
||||||
virStorageVolWipePattern;
|
virStorageVolWipePattern;
|
||||||
} LIBVIRT_0.9.9;
|
} LIBVIRT_0.9.9;
|
||||||
|
|
||||||
|
@ -11279,6 +11279,87 @@ cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
|
|||||||
return ret;
|
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 with optional k,M,G,T suffix")},
|
||||||
|
{"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;
|
||||||
|
if (delta && *capacityStr == '-') {
|
||||||
|
if (cmdVolSize(capacityStr + 1, &capacity) < 0) {
|
||||||
|
vshError(ctl, _("Malformed size %s"), capacityStr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
capacity = -capacity;
|
||||||
|
} else {
|
||||||
|
if (cmdVolSize(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
|
* "vol-dumpxml" command
|
||||||
@ -16139,6 +16220,7 @@ static const vshCmdDef storageVolCmds[] = {
|
|||||||
{"vol-name", cmdVolName, opts_vol_name, info_vol_name, 0},
|
{"vol-name", cmdVolName, opts_vol_name, info_vol_name, 0},
|
||||||
{"vol-path", cmdVolPath, opts_vol_path, info_vol_path, 0},
|
{"vol-path", cmdVolPath, opts_vol_path, info_vol_path, 0},
|
||||||
{"vol-pool", cmdVolPool, opts_vol_pool, info_vol_pool, 0},
|
{"vol-pool", cmdVolPool, opts_vol_pool, info_vol_pool, 0},
|
||||||
|
{"vol-resize", cmdVolResize, opts_vol_resize, info_vol_resize, 0},
|
||||||
{"vol-upload", cmdVolUpload, opts_vol_upload, info_vol_upload, 0},
|
{"vol-upload", cmdVolUpload, opts_vol_upload, info_vol_upload, 0},
|
||||||
{"vol-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe, 0},
|
{"vol-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe, 0},
|
||||||
{NULL, NULL, NULL, NULL, 0}
|
{NULL, NULL, NULL, NULL, 0}
|
||||||
|
@ -2012,6 +2012,17 @@ I<--pool> I<pool-or-uuid> is the name or UUID of the storage pool the volume
|
|||||||
is in. I<vol-name-or-path> is the name or path of the volume to return the
|
is in. I<vol-name-or-path> is the name or path of the volume to return the
|
||||||
volume key for.
|
volume key for.
|
||||||
|
|
||||||
|
=item B<vol-resize> [I<--pool> I<pool-or-uuid>] I<vol-name-or-path>
|
||||||
|
I<pool-or-uuid> I<capacity> [I<--allocate>] [I<--delta>] [I<--shrink>]
|
||||||
|
|
||||||
|
Resize the capacity of the given volume, in bytes.
|
||||||
|
I<--pool> I<pool-or-uuid> is the name or UUID of the storage pool the volume
|
||||||
|
is in. I<vol-name-or-key-or-path> is the name or key or path of the volume
|
||||||
|
to resize. The new capacity might be sparse unless I<--allocate> is
|
||||||
|
specified. Normally, I<capacity> is the new size, but if I<--delta>
|
||||||
|
is present, then it is added to the existing size. Attempts to shrink
|
||||||
|
the volume will fail unless I<--shrink> is present.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 SECRET COMMMANDS
|
=head1 SECRET COMMMANDS
|
||||||
|
Loading…
Reference in New Issue
Block a user