]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
resize: add virStorageVolResize() API
authorZeeshan Ali (Khattak) <zeeshanak@gnome.org>
Fri, 27 Jan 2012 05:29:56 +0000 (07:29 +0200)
committerEric Blake <eblake@redhat.com>
Sat, 28 Jan 2012 02:56:18 +0000 (19:56 -0700)
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>
include/libvirt/libvirt.h.in
python/generator.py
src/driver.h
src/libvirt.c
src/libvirt_public.syms
tools/virsh.c
tools/virsh.pod

index e99cd003fed29101408466f262adab79025575f5..d26cbbdb1896185dcf3ba00113108c7a6e8b27c2 100644 (file)
@@ -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:
  *
index de635dc92dc9ecdf0523fe28bb3d83104f635b29..791b267a5002b8df905e1774ed75eaa96d5a83b8 100755 (executable)
@@ -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 *"),
index df2aa60b93b18f2b59fcdb976f78d2b8a9e1199d..485b578ad6d279cc205d042371862050312c3116 100644 (file)
@@ -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;
 };
index e9d638bc470d4e97ec21e5e27865dfe012ce5fa4..540d74a65f55d72cda191759da13a475749ac1f1 100644 (file)
@@ -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:
index 1340b0c22c243f0f3edf210cbbc5cb377e835b1e..8bdb24bae276bf7b8be343b7849c30a04de999cc 100644 (file)
@@ -519,6 +519,7 @@ LIBVIRT_0.9.9 {
 LIBVIRT_0.9.10 {
     global:
         virDomainShutdownFlags;
+        virStorageVolResize;
         virStorageVolWipePattern;
 } LIBVIRT_0.9.9;
 
index 9b37dc0410a9acddd613b2e15db23b94f5702e81..ffcd746b367be1f75123fa90ef156028374ec111 100644 (file)
@@ -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;
+
+    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
@@ -16139,6 +16220,7 @@ static const vshCmdDef storageVolCmds[] = {
     {"vol-name", cmdVolName, opts_vol_name, info_vol_name, 0},
     {"vol-path", cmdVolPath, opts_vol_path, info_vol_path, 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-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe, 0},
     {NULL, NULL, NULL, NULL, 0}
index 8599f66e18bcf4d90119ba2e43e8d4d5c6116857..6622caf3e71da10ff6926ff24bb072509b1524a1 100644 (file)
@@ -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
 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
 
 =head1 SECRET COMMMANDS