Signed-off-by: Vasiliy Tolstov <v.tolstov@xxxxxxxxx> --- include/libvirt/libvirt-storage.h | 3 ++ m4/virt-storage-lvm.m4 | 3 ++ src/libvirt-storage.c | 39 +++++++++++++++++++++ src/libvirt_private.syms | 1 + src/libvirt_public.syms | 8 ++++- src/remote/remote_driver.c | 1 + src/storage/storage_backend_fs.c | 3 ++ src/storage/storage_backend_logical.c | 27 +++++++++++++++ src/storage/storage_backend_rbd.c | 28 +++++++++++++++ src/storage/storage_backend_vstorage.c | 1 + src/storage/storage_driver.c | 63 ++++------------------------------ src/storage/storage_util.c | 13 +++++++ src/storage/storage_util.h | 5 +++ src/util/virstoragefile.c | 39 +++++++++++++++++++++ tools/virsh-volume.c | 53 ++++++++++++++++++++++++++++ 15 files changed, 229 insertions(+), 58 deletions(-) diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index 736e2e3b80bd..9c75957879e4 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -395,6 +395,9 @@ int virStorageVolResize (virStorageVolPtr vol, unsigned long long capacity, unsigned int flags); +int virStorageVolRename (virStorageVolPtr vol, + const char *name); + int virStoragePoolIsActive(virStoragePoolPtr pool); int virStoragePoolIsPersistent(virStoragePoolPtr pool); diff --git a/m4/virt-storage-lvm.m4 b/m4/virt-storage-lvm.m4 index a0ccca7a00ab..74330c8ecb15 100644 --- a/m4/virt-storage-lvm.m4 +++ b/m4/virt-storage-lvm.m4 @@ -30,6 +30,7 @@ AC_DEFUN([LIBVIRT_STORAGE_CHECK_LVM], [ AC_PATH_PROG([VGREMOVE], [vgremove], [], [$LIBVIRT_SBIN_PATH]) AC_PATH_PROG([LVREMOVE], [lvremove], [], [$LIBVIRT_SBIN_PATH]) AC_PATH_PROG([LVCHANGE], [lvchange], [], [$LIBVIRT_SBIN_PATH]) + AC_PATH_PROG([LVRENAME], [lvrename], [], [$LIBVIRT_SBIN_PATH]) AC_PATH_PROG([VGCHANGE], [vgchange], [], [$LIBVIRT_SBIN_PATH]) AC_PATH_PROG([VGSCAN], [vgscan], [], [$LIBVIRT_SBIN_PATH]) AC_PATH_PROG([PVS], [pvs], [], [$LIBVIRT_SBIN_PATH]) @@ -44,6 +45,7 @@ AC_DEFUN([LIBVIRT_STORAGE_CHECK_LVM], [ if test -z "$VGREMOVE" ; then AC_MSG_ERROR([We need vgremove for LVM storage driver]) ; fi if test -z "$LVREMOVE" ; then AC_MSG_ERROR([We need lvremove for LVM storage driver]) ; fi if test -z "$LVCHANGE" ; then AC_MSG_ERROR([We need lvchange for LVM storage driver]) ; fi + if test -z "$LVRENAME" ; then AC_MSG_ERROR([We need lvrename for LVM storage driver]) ; fi if test -z "$VGCHANGE" ; then AC_MSG_ERROR([We need vgchange for LVM storage driver]) ; fi if test -z "$VGSCAN" ; then AC_MSG_ERROR([We need vgscan for LVM storage driver]) ; fi if test -z "$PVS" ; then AC_MSG_ERROR([We need pvs for LVM storage driver]) ; fi @@ -75,6 +77,7 @@ AC_DEFUN([LIBVIRT_STORAGE_CHECK_LVM], [ AC_DEFINE_UNQUOTED([VGREMOVE],["$VGREMOVE"],[Location of vgremove program]) AC_DEFINE_UNQUOTED([LVREMOVE],["$LVREMOVE"],[Location of lvremove program]) AC_DEFINE_UNQUOTED([LVCHANGE],["$LVCHANGE"],[Location of lvchange program]) + AC_DEFINE_UNQUOTED([LVRENAME],["$LVRENAME"],[Location of lvrename program]) AC_DEFINE_UNQUOTED([VGCHANGE],["$VGCHANGE"],[Location of vgchange program]) AC_DEFINE_UNQUOTED([VGSCAN],["$VGSCAN"],[Location of vgscan program]) AC_DEFINE_UNQUOTED([PVS],["$PVS"],[Location of pvs program]) diff --git a/src/libvirt-storage.c b/src/libvirt-storage.c index e4646cb80ff9..754adedcb21e 100644 --- a/src/libvirt-storage.c +++ b/src/libvirt-storage.c @@ -2122,6 +2122,45 @@ virStorageVolResize(virStorageVolPtr vol, } +/** + * virStorageVolRename: + * @vol: pointer to storage volume + * @name: new volume name + * + * Changes the nmae of the storage volume @vol to @name. + * + * Returns 0 on success, or -1 on error. + */ +int +virStorageVolRename(virStorageVolPtr vol, + const char *name) +{ + virConnectPtr conn; + VIR_DEBUG("vol=%p name=%s", vol, name); + + virResetLastError(); + + virCheckStorageVolReturn(vol, -1); + conn = vol->conn; + + virCheckReadOnlyGoto(conn->flags, error); + + if (conn->storageDriver && conn->storageDriver->storageVolRename) { + int ret; + ret = conn->storageDriver->storageVolRename(vol, name); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(vol->conn); + return -1; +} + + /** * virStoragePoolIsActive: * @pool: pointer to the storage pool object diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f2a2c8650d97..3052b04d5282 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2720,6 +2720,7 @@ virStorageFileParseBackingStoreStr; virStorageFileParseChainIndex; virStorageFileProbeFormat; virStorageFileResize; +virStorageFileRename; virStorageIsFile; virStorageIsRelative; virStorageNetHostDefClear; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0efde25a7f76..a828d0a7ce5c 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -777,6 +777,12 @@ LIBVIRT_3.7.0 { LIBVIRT_3.9.0 { global: - virDomainSetLifecycleAction; + virDomainSetLifecycleAction; } LIBVIRT_3.7.0; + +LIBVIRT_4.0.1 { + global: + virStorageVolRename; +} LIBVIRT_3.9.0; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index f8fa64af998e..cf6bdf233ed8 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8587,6 +8587,7 @@ static virStorageDriver storage_driver = { .storageVolGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */ .storageVolGetPath = remoteStorageVolGetPath, /* 0.4.1 */ .storageVolResize = remoteStorageVolResize, /* 0.9.10 */ + .storageVolRename = remoteStorageVolRename, /* 3.9.0 */ .storagePoolIsActive = remoteStoragePoolIsActive, /* 0.7.3 */ .storagePoolIsPersistent = remoteStoragePoolIsPersistent, /* 0.7.3 */ }; diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index f54759983ceb..d19e83726bf7 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -664,6 +664,7 @@ virStorageBackend virStorageBackendDirectory = { .refreshVol = virStorageBackendVolRefreshLocal, .deleteVol = virStorageBackendVolDeleteLocal, .resizeVol = virStorageBackendVolResizeLocal, + .renameVol = virStorageBackendVolRenameLocal, .uploadVol = virStorageBackendVolUploadLocal, .downloadVol = virStorageBackendVolDownloadLocal, .wipeVol = virStorageBackendVolWipeLocal, @@ -685,6 +686,7 @@ virStorageBackend virStorageBackendFileSystem = { .refreshVol = virStorageBackendVolRefreshLocal, .deleteVol = virStorageBackendVolDeleteLocal, .resizeVol = virStorageBackendVolResizeLocal, + .renameVol = virStorageBackendVolRenameLocal, .uploadVol = virStorageBackendVolUploadLocal, .downloadVol = virStorageBackendVolDownloadLocal, .wipeVol = virStorageBackendVolWipeLocal, @@ -705,6 +707,7 @@ virStorageBackend virStorageBackendNetFileSystem = { .refreshVol = virStorageBackendVolRefreshLocal, .deleteVol = virStorageBackendVolDeleteLocal, .resizeVol = virStorageBackendVolResizeLocal, + .renameVol = virStorageBackendVolRenameLocal, .uploadVol = virStorageBackendVolUploadLocal, .downloadVol = virStorageBackendVolDownloadLocal, .wipeVol = virStorageBackendVolWipeLocal, diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c index 5df30de29d17..015188508123 100644 --- a/src/storage/storage_backend_logical.c +++ b/src/storage/storage_backend_logical.c @@ -902,6 +902,32 @@ virStorageBackendLogicalDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED, } +static int +virStorageBackendLogicalRenameVol(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, + const char *name) +{ + int ret = -1; + virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool); + virCommandPtr lvrename_cmd = NULL; + + virCheckFlags(0, -1); + + virWaitForDevices(); + + lvrename_cmd = virCommandNewArgList(LVRENAME, "%s", def->target.path, vol->name, name, NULL); + + if (virCommandRun(lvrename_cmd, NULL) < 0) { + goto cleanup; + } + + ret = 0; + cleanup: + virCommandFree(lvrename_cmd); + return ret; +} + static int virStorageBackendLogicalDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, @@ -1107,6 +1133,7 @@ virStorageBackend virStorageBackendLogical = { .buildVolFrom = virStorageBackendLogicalBuildVolFrom, .createVol = virStorageBackendLogicalCreateVol, .deleteVol = virStorageBackendLogicalDeleteVol, + .renameVol = virStorageBackendLogicalRenameVol, .uploadVol = virStorageBackendVolUploadLocal, .downloadVol = virStorageBackendVolDownloadLocal, .wipeVol = virStorageBackendLogicalVolWipe, diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c index 7f9597cabea3..ddc28904c76c 100644 --- a/src/storage/storage_backend_rbd.c +++ b/src/storage/storage_backend_rbd.c @@ -1091,6 +1091,34 @@ virStorageBackendRBDRefreshVol(virConnectPtr conn, return ret; } +static int +virStorageBackendRBDRenameVol(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, + virStorageVolDefPtr vol, + const char *name) +{ + virStorageBackendRBDStatePtr ptr = NULL; + int ret = -1; + int r = 0; + + virCheckFlags(0, -1); + + if (!(ptr = virStorageBackendRBDNewState(conn, pool))) + goto cleanup; + + if ((r = rbd_rename(ptr->ioctx, vol->name, name)) < 0) { + virReportSystemError(-r, _("failed to rename the RBD image '%s' to '%s'"), + vol->name, name); + goto cleanup; + } + + ret = 0; + + cleanup: + virStorageBackendRBDFreeState(&ptr); + return ret; +} + static int virStorageBackendRBDResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, diff --git a/src/storage/storage_backend_vstorage.c b/src/storage/storage_backend_vstorage.c index 2dc26af38706..3607312ae486 100644 --- a/src/storage/storage_backend_vstorage.c +++ b/src/storage/storage_backend_vstorage.c @@ -182,6 +182,7 @@ virStorageBackend virStorageBackendVstorage = { .refreshVol = virStorageBackendVolRefreshLocal, .deleteVol = virStorageBackendVolDeleteLocal, .resizeVol = virStorageBackendVolResizeLocal, + .renameVol = virStorageBackendVolRenameLocal, .uploadVol = virStorageBackendVolUploadLocal, .downloadVol = virStorageBackendVolDownloadLocal, .wipeVol = virStorageBackendVolWipeLocal, diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 3b66d517191b..e68f158288ca 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -2358,21 +2358,15 @@ storageVolUpload(virStorageVolPtr vol, } static int -storageVolResize(virStorageVolPtr vol, - unsigned long long capacity, - unsigned int flags) +storageVolRename(virStorageVolPtr vol, + const char *name) { virStorageBackendPtr backend; virStoragePoolObjPtr obj = NULL; virStoragePoolDefPtr def; virStorageVolDefPtr voldef = NULL; - unsigned long long abs_capacity, delta = 0; int ret = -1; - virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE | - VIR_STORAGE_VOL_RESIZE_DELTA | - VIR_STORAGE_VOL_RESIZE_SHRINK, -1); - if (!(voldef = virStorageVolDefFromVol(vol, &obj, &backend))) return -1; def = virStoragePoolObjGetDef(obj); @@ -2394,61 +2388,16 @@ storageVolResize(virStorageVolPtr vol, goto cleanup; } - if (flags & VIR_STORAGE_VOL_RESIZE_DELTA) { - if (flags & VIR_STORAGE_VOL_RESIZE_SHRINK) - abs_capacity = voldef->target.capacity - MIN(capacity, voldef->target.capacity); - else - abs_capacity = voldef->target.capacity + capacity; - flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA; - } else { - abs_capacity = capacity; - } - - if (abs_capacity < voldef->target.allocation) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("can't shrink capacity below " - "existing allocation")); - goto cleanup; - } - - if (abs_capacity < voldef->target.capacity && - !(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("Can't shrink capacity below current " - "capacity unless shrink flag explicitly specified")); - goto cleanup; - } - - if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE) - delta = abs_capacity - voldef->target.allocation; - - if (delta > def->available) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("Not enough space left in storage pool")); - goto cleanup; - } - - if (!backend->resizeVol) { + if (!backend->renameVol) { virReportError(VIR_ERR_NO_SUPPORT, "%s", _("storage pool does not support changing of " - "volume capacity")); + "volume name")); goto cleanup; } - if (backend->resizeVol(vol->conn, obj, voldef, abs_capacity, flags) < 0) + if (backend->renameVol(vol->conn, obj, voldef, name) < 0) goto cleanup; - voldef->target.capacity = abs_capacity; - /* Only update the allocation and pool values if we actually did the - * allocation; otherwise, this is akin to a create operation with a - * capacity value different and potentially much larger than available - */ - if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE) { - voldef->target.allocation = abs_capacity; - def->allocation += delta; - def->available -= delta; - } - ret = 0; cleanup: @@ -2732,7 +2681,7 @@ static virStorageDriver storageDriver = { .storageVolGetXMLDesc = storageVolGetXMLDesc, /* 0.4.0 */ .storageVolGetPath = storageVolGetPath, /* 0.4.0 */ .storageVolResize = storageVolResize, /* 0.9.10 */ - + .storageVolRename = storageVolRename, /* 3.9.0 */ .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */ .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */ }; diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index 9e1b63a43609..528286b145d5 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -2475,6 +2475,19 @@ virStorageBackendVolResizeLocal(virConnectPtr conn, } +/** + * Rename a volume + */ +int +virStorageBackendVolRenameLocal(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, + virStorageVolDefPtr vol, + const char *name) +{ + return virStorageFileRename(vol->target.path, name); +} + + /* * Check whether the ploop image has snapshots. * return: -1 - failed to check diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h index dc7e62517b4f..0e90a762df8a 100644 --- a/src/storage/storage_util.h +++ b/src/storage/storage_util.h @@ -69,6 +69,11 @@ int virStorageBackendVolResizeLocal(virConnectPtr conn, unsigned long long capacity, unsigned int flags); +int virStorageBackendVolRenameLocal(virConnectPtr conn, + virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, + const char *name); + int virStorageBackendVolUploadLocal(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 5780180a94ef..c5da169194fd 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1359,6 +1359,45 @@ virStorageFileResize(const char *path, } +/** + * virStorageFileRename: + * + * Change the name file at 'path'. + */ +int +virStorageFileRename(const char *path, + const char *name) +{ + int ret = -1; + int rc; + char *opath = NULL; + char *npath = NULL; + char *base = NULL; + + VIR_STRDUP(*opath, path) < 0) + goto cleanup; + + base = dirname(npath); + if (virAsprintf(npath, "%s/%s", base, name) < 0) + goto cleanup; + + + if (rename(path, name) < 0) { + virReportSystemError(errno, + _("Failed to rename file '%s' to '%s'"), opath, npath); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(opath); + VIR_FREE(npath); + return ret; +} + + + int virStorageFileIsClusterFS(const char *path) { /* These are coherent cluster filesystems known to be safe for diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c index bacbec0d27b7..00a1468feb52 100644 --- a/tools/virsh-volume.c +++ b/tools/virsh-volume.c @@ -1189,6 +1189,59 @@ cmdVolResize(vshControl *ctl, const vshCmd *cmd) return ret; } +/* + * "vol-rename" command + */ +static const vshCmdInfo info_vol_rename[] = { + {.name = "help", + .data = N_("rename a vol") + }, + {.name = "desc", + .data = N_("Renames a storage volume") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_vol_rename[] = { + VIRSH_COMMON_OPT_VOLUME_VOL, + {.name = "name", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("new name for the vol") + }, + {.name = NULL} +}; + + +static bool +cmdVolRename(vshControl *ctl, const vshCmd *cmd) +{ + virStorageVolPtr vol; + const char *name = NULL; + bool ret = false; + + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + return false; + + if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0) + goto cleanup; + virSkipSpaces(&name); + + if (virStorageVolRename(vol, name) == 0) { + vshPrintExtra(ctl, _("Name of volume '%s' successfully changed to %s\n"), + virStorageVolGetName(vol), name); + ret = true; + } else { + vshError(ctl, _("Failed to change name of volume '%s' to %s"), + virStorageVolGetName(vol), name); + ret = false; + } + + cleanup: + virStorageVolFree(vol); + return ret; +} + /* * "vol-dumpxml" command */ -- 2.14.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list