Signed-off-by: Vasiliy Tolstov <v.tolstov(a)selfip.ru>
---
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