On 2012年01月28日 08:28, Eric Blake wrote:
From: "Zeeshan Ali (Khattak)"<zeeshanak(a)gnome.org>
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(a)redhat.com>
---
include/libvirt/libvirt.h.in | 11 ++++++
python/generator.py | 1 +
src/driver.h | 5 +++
src/libvirt.c | 76 ++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
tools/virsh.c | 82 ++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 11 ++++++
7 files changed, 187 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index e99cd00..d26cbbd 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2386,6 +2386,17 @@ char * virStorageVolGetXMLDesc
(virStorageVolPtr pool,
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:
*
diff --git a/python/generator.py b/python/generator.py
index de635dc..791b267 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -259,6 +259,7 @@ py_types = {
'double': ('d', None, "double", "double"),
'unsigned int': ('i', None, "int", "int"),
'unsigned long': ('l', None, "long", "long"),
+ 'long long': ('l', None, "longlong", "long
long"),
'unsigned long long': ('l', None, "longlong", "long
long"),
'unsigned char *': ('z', None, "charPtr", "char
*"),
'char *': ('z', None, "charPtr", "char *"),
diff --git a/src/driver.h b/src/driver.h
index df2aa60..485b578 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1261,6 +1261,10 @@ typedef int
unsigned long long offset,
unsigned long long length,
unsigned int flags);
+typedef int
+ (*virDrvStorageVolResize) (virStorageVolPtr vol,
+ long long capacity,
+ unsigned int flags);
typedef int
(*virDrvStoragePoolIsActive)(virStoragePoolPtr pool);
@@ -1323,6 +1327,7 @@ struct _virStorageDriver {
virDrvStorageVolGetInfo volGetInfo;
virDrvStorageVolGetXMLDesc volGetXMLDesc;
virDrvStorageVolGetPath volGetPath;
+ virDrvStorageVolResize volResize;
virDrvStoragePoolIsActive poolIsActive;
virDrvStoragePoolIsPersistent poolIsPersistent;
};
diff --git a/src/libvirt.c b/src/libvirt.c
index e9d638b..540d74a 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -12927,6 +12927,82 @@ error:
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:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 1340b0c..8bdb24b 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -519,6 +519,7 @@ LIBVIRT_0.9.9 {
LIBVIRT_0.9.10 {
global:
virDomainShutdownFlags;
+ virStorageVolResize;
virStorageVolWipePattern;
} LIBVIRT_0.9.9;
diff --git a/tools/virsh.c b/tools/virsh.c
index 9b37dc0..ffcd746 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -11279,6 +11279,87 @@ cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
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;
Late response, but it seems not good idea to expose the options
which are actually not implemented underlying yet. One would get
error like:
# virsh vol-resize /var/lib/libvirt/images/test.img 60 --shrink
error: invalid argument: storageVolumeResize: unsupported flags (0x4)
With the magic number "0x4", one'd never known what it is. It can
be improved roundabout, but it should be avoided in the beginning.
Regards,
Osier