Move all the volume functions to storage_util to create local/common helpers
using the same naming syntax as the existing upload, download, and wipe
virStorageBackend*Local API's.
In the process of doing so, found more API's that can now become local
to storage_util. In order to distinguish between local/external - I
changed the names of the now local only ones from "virStorageBackend..."
to just "storageBackend..."
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/storage/storage_backend_fs.c | 372 ++--------------------------
src/storage/storage_util.c | 511 ++++++++++++++++++++++++++++++++-------
src/storage/storage_util.h | 44 ++--
3 files changed, 465 insertions(+), 462 deletions(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 6f331d6..9710648 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -625,342 +625,6 @@ virStorageBackendFileSystemBuild(virConnectPtr conn
ATTRIBUTE_UNUSED,
}
-/**
- * Set up a volume definition to be added to a pool's volume list, but
- * don't do any file creation or allocation. By separating the two processes,
- * we allow allocation progress reporting (by polling the volume's 'info'
- * function), and can drop the parent pool lock during the (slow) allocation.
- */
-static int
-virStorageBackendFileSystemVolCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol)
-{
-
- if (vol->target.format == VIR_STORAGE_FILE_DIR)
- vol->type = VIR_STORAGE_VOL_DIR;
- else if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
- vol->type = VIR_STORAGE_VOL_PLOOP;
- else
- vol->type = VIR_STORAGE_VOL_FILE;
-
- /* Volumes within a directory pools are not recursive; do not
- * allow escape to ../ or a subdir */
- if (strchr(vol->name, '/')) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("volume name '%s' cannot contain
'/'"), vol->name);
- return -1;
- }
-
- VIR_FREE(vol->target.path);
- if (virAsprintf(&vol->target.path, "%s/%s",
- pool->def->target.path,
- vol->name) == -1)
- return -1;
-
- if (virFileExists(vol->target.path)) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("volume target path '%s' already exists"),
- vol->target.path);
- return -1;
- }
-
- VIR_FREE(vol->key);
- return VIR_STRDUP(vol->key, vol->target.path);
-}
-
-static int createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
-{
- int err;
-
- virCheckFlags(0, -1);
-
- if (inputvol) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s",
- _("cannot copy from volume to a directory volume"));
- return -1;
- }
-
- if (vol->target.backingStore) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("backing storage not supported for directories
volumes"));
- return -1;
- }
-
-
- if ((err = virDirCreate(vol->target.path,
- (vol->target.perms->mode == (mode_t) -1 ?
- VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
- vol->target.perms->mode),
- vol->target.perms->uid,
- vol->target.perms->gid,
- (pool->def->type == VIR_STORAGE_POOL_NETFS
- ? VIR_DIR_CREATE_AS_UID : 0))) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-static int
-_virStorageBackendFileSystemVolBuild(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
-{
- virStorageBackendBuildVolFrom create_func;
-
- if (inputvol) {
- if (vol->target.encryption != NULL) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("storage pool does not support "
- "building encrypted volumes from "
- "other volumes"));
- return -1;
- }
- create_func = virStorageBackendGetBuildVolFromFunction(vol,
- inputvol);
- if (!create_func)
- return -1;
- } else if (vol->target.format == VIR_STORAGE_FILE_RAW &&
- vol->target.encryption == NULL) {
- create_func = virStorageBackendCreateRaw;
- } else if (vol->target.format == VIR_STORAGE_FILE_DIR) {
- create_func = createFileDir;
- } else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
- create_func = virStorageBackendCreatePloop;
- } else {
- create_func = virStorageBackendCreateQemuImg;
- }
-
- if (create_func(conn, pool, vol, inputvol, flags) < 0)
- return -1;
- return 0;
-}
-
-/**
- * Allocate a new file as a volume. This is either done directly
- * for raw/sparse files, or by calling qemu-img for
- * special kinds of files
- */
-static int
-virStorageBackendFileSystemVolBuild(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- unsigned int flags)
-{
- virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
- VIR_STORAGE_VOL_CREATE_REFLINK,
- -1);
-
- return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL, flags);
-}
-
-/*
- * Create a storage vol using 'inputvol' as input
- */
-static int
-virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
-{
- virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
- VIR_STORAGE_VOL_CREATE_REFLINK,
- -1);
-
- return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol, flags);
-}
-
-/**
- * Remove a volume - no support for BLOCK and NETWORK yet
- */
-static int
-virStorageBackendFileSystemVolDelete(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
- virStorageVolDefPtr vol,
- unsigned int flags)
-{
- virCheckFlags(0, -1);
-
- switch ((virStorageVolType) vol->type) {
- case VIR_STORAGE_VOL_FILE:
- case VIR_STORAGE_VOL_DIR:
- if (virFileRemove(vol->target.path, vol->target.perms->uid,
- vol->target.perms->gid) < 0) {
- /* Silently ignore failures where the vol has already gone away */
- if (errno != ENOENT) {
- if (vol->type == VIR_STORAGE_VOL_FILE)
- virReportSystemError(errno,
- _("cannot unlink file '%s'"),
- vol->target.path);
- else
- virReportSystemError(errno,
- _("cannot remove directory
'%s'"),
- vol->target.path);
- return -1;
- }
- }
- break;
- case VIR_STORAGE_VOL_PLOOP:
- if (virFileDeleteTree(vol->target.path) < 0)
- return -1;
- break;
- case VIR_STORAGE_VOL_BLOCK:
- case VIR_STORAGE_VOL_NETWORK:
- case VIR_STORAGE_VOL_NETDIR:
- case VIR_STORAGE_VOL_LAST:
- virReportError(VIR_ERR_NO_SUPPORT,
- _("removing block or network volumes is not supported:
%s"),
- vol->target.path);
- return -1;
- }
- return 0;
-}
-
-
-/* virStorageBackendFileSystemLoadDefaultSecrets:
- * @conn: Connection pointer to fetch secret
- * @vol: volume being refreshed
- *
- * If the volume had a secret generated, we need to regenerate the
- * encryption secret information
- *
- * Returns 0 if no secret or secret setup was successful,
- * -1 on failures w/ error message set
- */
-static int
-virStorageBackendFileSystemLoadDefaultSecrets(virConnectPtr conn,
- virStorageVolDefPtr vol)
-{
- virSecretPtr sec;
- virStorageEncryptionSecretPtr encsec = NULL;
-
- if (!vol->target.encryption || vol->target.encryption->nsecrets != 0)
- return 0;
-
- /* The encryption secret for qcow2 and luks volumes use the path
- * to the volume, so look for a secret with the path. If not found,
- * then we cannot generate the secret after a refresh (or restart).
- * This may be the case if someone didn't follow instructions and created
- * a usage string that although matched with the secret usage string,
- * didn't contain the path to the volume. We won't error in that case,
- * but we also cannot find the secret. */
- if (!(sec = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_VOLUME,
- vol->target.path)))
- return 0;
-
- if (VIR_ALLOC_N(vol->target.encryption->secrets, 1) < 0 ||
- VIR_ALLOC(encsec) < 0) {
- VIR_FREE(vol->target.encryption->secrets);
- virObjectUnref(sec);
- return -1;
- }
-
- vol->target.encryption->nsecrets = 1;
- vol->target.encryption->secrets[0] = encsec;
-
- encsec->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
- encsec->seclookupdef.type = VIR_SECRET_LOOKUP_TYPE_UUID;
- virSecretGetUUID(sec, encsec->seclookupdef.u.uuid);
- virObjectUnref(sec);
-
- return 0;
-}
-
-
-/**
- * Update info about a volume's capacity/allocation
- */
-static int
-virStorageBackendFileSystemVolRefresh(virConnectPtr conn,
- virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
- virStorageVolDefPtr vol)
-{
- int ret;
-
- /* Refresh allocation / capacity / permissions info in case its changed */
- if ((ret = virStorageBackendUpdateVolInfo(vol, false,
- VIR_STORAGE_VOL_FS_OPEN_FLAGS,
- 0)) < 0)
- return ret;
-
- /* Load any secrets if possible */
- return virStorageBackendFileSystemLoadDefaultSecrets(conn, vol);
-}
-
-static int
-virStorageBackendFilesystemResizeQemuImg(const char *path,
- unsigned long long capacity)
-{
- int ret = -1;
- char *img_tool;
- virCommandPtr cmd = NULL;
-
- img_tool = virFindFileInPath("qemu-img");
- if (!img_tool) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unable to find qemu-img"));
- return -1;
- }
-
- /* Round capacity as qemu-img resize errors out on sizes which are not
- * a multiple of 512 */
- capacity = VIR_ROUND_UP(capacity, 512);
-
- cmd = virCommandNew(img_tool);
- virCommandAddArgList(cmd, "resize", path, NULL);
- virCommandAddArgFormat(cmd, "%llu", capacity);
-
- ret = virCommandRun(cmd, NULL);
-
- VIR_FREE(img_tool);
- virCommandFree(cmd);
-
- return ret;
-}
-
-/**
- * Resize a volume
- */
-static int
-virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
- virStorageVolDefPtr vol,
- unsigned long long capacity,
- unsigned int flags)
-{
- virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
- VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
-
- bool pre_allocate = flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE;
-
- if (vol->target.format == VIR_STORAGE_FILE_RAW) {
- return virStorageFileResize(vol->target.path, capacity,
- vol->target.allocation, pre_allocate);
- } else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
- return virStoragePloopResize(vol, capacity);
- } else {
- if (pre_allocate) {
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("preallocate is only supported for raw "
- "type volume"));
- return -1;
- }
-
- return virStorageBackendFilesystemResizeQemuImg(vol->target.path,
- capacity);
- }
-}
-
-
virStorageBackend virStorageBackendDirectory = {
.type = VIR_STORAGE_POOL_DIR,
@@ -968,12 +632,12 @@ virStorageBackend virStorageBackendDirectory = {
.checkPool = virStorageBackendFileSystemCheck,
.refreshPool = virStorageBackendRefreshLocal,
.deletePool = virStorageBackendDeleteLocal,
- .buildVol = virStorageBackendFileSystemVolBuild,
- .buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
- .createVol = virStorageBackendFileSystemVolCreate,
- .refreshVol = virStorageBackendFileSystemVolRefresh,
- .deleteVol = virStorageBackendFileSystemVolDelete,
- .resizeVol = virStorageBackendFileSystemVolResize,
+ .buildVol = virStorageBackendVolBuildLocal,
+ .buildVolFrom = virStorageBackendVolBuildFromLocal,
+ .createVol = virStorageBackendVolCreateLocal,
+ .refreshVol = virStorageBackendVolRefreshLocal,
+ .deleteVol = virStorageBackendVolDeleteLocal,
+ .resizeVol = virStorageBackendVolResizeLocal,
.uploadVol = virStorageBackendVolUploadLocal,
.downloadVol = virStorageBackendVolDownloadLocal,
.wipeVol = virStorageBackendVolWipeLocal,
@@ -989,12 +653,12 @@ virStorageBackend virStorageBackendFileSystem = {
.refreshPool = virStorageBackendRefreshLocal,
.stopPool = virStorageBackendFileSystemStop,
.deletePool = virStorageBackendDeleteLocal,
- .buildVol = virStorageBackendFileSystemVolBuild,
- .buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
- .createVol = virStorageBackendFileSystemVolCreate,
- .refreshVol = virStorageBackendFileSystemVolRefresh,
- .deleteVol = virStorageBackendFileSystemVolDelete,
- .resizeVol = virStorageBackendFileSystemVolResize,
+ .buildVol = virStorageBackendVolBuildLocal,
+ .buildVolFrom = virStorageBackendVolBuildFromLocal,
+ .createVol = virStorageBackendVolCreateLocal,
+ .refreshVol = virStorageBackendVolRefreshLocal,
+ .deleteVol = virStorageBackendVolDeleteLocal,
+ .resizeVol = virStorageBackendVolResizeLocal,
.uploadVol = virStorageBackendVolUploadLocal,
.downloadVol = virStorageBackendVolDownloadLocal,
.wipeVol = virStorageBackendVolWipeLocal,
@@ -1009,12 +673,12 @@ virStorageBackend virStorageBackendNetFileSystem = {
.refreshPool = virStorageBackendRefreshLocal,
.stopPool = virStorageBackendFileSystemStop,
.deletePool = virStorageBackendDeleteLocal,
- .buildVol = virStorageBackendFileSystemVolBuild,
- .buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
- .createVol = virStorageBackendFileSystemVolCreate,
- .refreshVol = virStorageBackendFileSystemVolRefresh,
- .deleteVol = virStorageBackendFileSystemVolDelete,
- .resizeVol = virStorageBackendFileSystemVolResize,
+ .buildVol = virStorageBackendVolBuildLocal,
+ .buildVolFrom = virStorageBackendVolBuildFromLocal,
+ .createVol = virStorageBackendVolCreateLocal,
+ .refreshVol = virStorageBackendVolRefreshLocal,
+ .deleteVol = virStorageBackendVolDeleteLocal,
+ .resizeVol = virStorageBackendVolResizeLocal,
.uploadVol = virStorageBackendVolUploadLocal,
.downloadVol = virStorageBackendVolDownloadLocal,
.wipeVol = virStorageBackendVolWipeLocal,
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index 6c2678d..fbe1844 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -222,11 +222,11 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
}
static int
-virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
+storageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
{
int fd = -1;
int ret = -1;
@@ -389,12 +389,12 @@ createRawFile(int fd, virStorageVolDefPtr vol,
return ret;
}
-int
-virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
+static int
+storageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
{
int ret = -1;
int fd = -1;
@@ -692,12 +692,12 @@ virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
/* Create ploop directory with ploop image and DiskDescriptor.xml
* if function fails to create image file the directory will be deleted.*/
-int
-virStorageBackendCreatePloop(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
+static int
+storageBackendCreatePloop(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
{
int ret = -1;
virCommandPtr cmd = NULL;
@@ -767,9 +767,10 @@ virStorageBackendCreatePloop(virConnectPtr conn ATTRIBUTE_UNUSED,
return ret;
}
-int
-virStoragePloopResize(virStorageVolDefPtr vol,
- unsigned long long capacity)
+
+static int
+storagePloopResize(virStorageVolDefPtr vol,
+ unsigned long long capacity)
{
int ret = -1;
virCommandPtr cmd = NULL;
@@ -875,9 +876,9 @@ struct _virStorageBackendQemuImgInfo {
static int
-virStorageBackendCreateQemuImgOpts(virStorageEncryptionInfoDefPtr enc,
- char **opts,
- struct _virStorageBackendQemuImgInfo info)
+storageBackendCreateQemuImgOpts(virStorageEncryptionInfoDefPtr enc,
+ char **opts,
+ struct _virStorageBackendQemuImgInfo info)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -927,7 +928,7 @@ virStorageBackendCreateQemuImgOpts(virStorageEncryptionInfoDefPtr
enc,
}
-/* virStorageBackendCreateQemuImgCheckEncryption:
+/* storageBackendCreateQemuImgCheckEncryption:
* @format: format of file found
* @conn: pointer to connection
* @vol: pointer to volume def
@@ -937,10 +938,10 @@ virStorageBackendCreateQemuImgOpts(virStorageEncryptionInfoDefPtr
enc,
* Returns 0 on success, -1 on failure w/ error set
*/
static int
-virStorageBackendCreateQemuImgCheckEncryption(int format,
- const char *type,
- virConnectPtr conn,
- virStorageVolDefPtr vol)
+storageBackendCreateQemuImgCheckEncryption(int format,
+ const char *type,
+ virConnectPtr conn,
+ virStorageVolDefPtr vol)
{
virStorageEncryptionPtr enc = vol->target.encryption;
@@ -996,8 +997,8 @@ virStorageBackendCreateQemuImgCheckEncryption(int format,
static int
-virStorageBackendCreateQemuImgSetInput(virStorageVolDefPtr inputvol,
- struct _virStorageBackendQemuImgInfo *info)
+storageBackendCreateQemuImgSetInput(virStorageVolDefPtr inputvol,
+ struct _virStorageBackendQemuImgInfo *info)
{
if (!(info->inputPath = inputvol->target.path)) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -1021,10 +1022,10 @@ virStorageBackendCreateQemuImgSetInput(virStorageVolDefPtr
inputvol,
static int
-virStorageBackendCreateQemuImgSetBacking(virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- struct _virStorageBackendQemuImgInfo *info)
+storageBackendCreateQemuImgSetBacking(virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ struct _virStorageBackendQemuImgInfo *info)
{
int accessRetCode = -1;
char *absolutePath = NULL;
@@ -1086,10 +1087,10 @@ virStorageBackendCreateQemuImgSetBacking(virStoragePoolObjPtr
pool,
static int
-virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
- int imgformat,
- virStorageEncryptionInfoDefPtr enc,
- struct _virStorageBackendQemuImgInfo info)
+storageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
+ int imgformat,
+ virStorageEncryptionInfoDefPtr enc,
+ struct _virStorageBackendQemuImgInfo info)
{
char *opts = NULL;
@@ -1097,7 +1098,7 @@ virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
imgformat >= QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT)
info.compat = "0.10";
- if (virStorageBackendCreateQemuImgOpts(enc, &opts, info) < 0)
+ if (storageBackendCreateQemuImgOpts(enc, &opts, info) < 0)
return -1;
if (opts)
virCommandAddArgList(cmd, "-o", opts, NULL);
@@ -1113,9 +1114,9 @@ virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
* NB: format=raw is assumed
*/
static int
-virStorageBackendCreateQemuImgSecretObject(virCommandPtr cmd,
- virStorageVolDefPtr vol,
- struct _virStorageBackendQemuImgInfo *info)
+storageBackendCreateQemuImgSecretObject(virCommandPtr cmd,
+ virStorageVolDefPtr vol,
+ struct _virStorageBackendQemuImgInfo *info)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
char *commandStr = NULL;
@@ -1218,17 +1219,16 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
}
if (inputvol &&
- virStorageBackendCreateQemuImgSetInput(inputvol, &info) < 0)
+ storageBackendCreateQemuImgSetInput(inputvol, &info) < 0)
return NULL;
if (vol->target.backingStore &&
- virStorageBackendCreateQemuImgSetBacking(pool, vol, inputvol,
- &info) < 0)
+ storageBackendCreateQemuImgSetBacking(pool, vol, inputvol, &info) < 0)
return NULL;
if (info.encryption &&
- virStorageBackendCreateQemuImgCheckEncryption(info.format, type,
- conn, vol) < 0)
+ storageBackendCreateQemuImgCheckEncryption(info.format, type,
+ conn, vol) < 0)
return NULL;
@@ -1253,7 +1253,7 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
if (info.format == VIR_STORAGE_FILE_RAW &&
vol->target.encryption != NULL &&
vol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
- if (virStorageBackendCreateQemuImgSecretObject(cmd, vol, &info) < 0) {
+ if (storageBackendCreateQemuImgSecretObject(cmd, vol, &info) < 0) {
VIR_FREE(info.secretAlias);
virCommandFree(cmd);
return NULL;
@@ -1261,8 +1261,7 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
enc = &vol->target.encryption->encinfo;
}
- if (virStorageBackendCreateQemuImgSetOptions(cmd, imgformat,
- enc, info) < 0) {
+ if (storageBackendCreateQemuImgSetOptions(cmd, imgformat, enc, info) < 0) {
VIR_FREE(info.secretAlias);
virCommandFree(cmd);
return NULL;
@@ -1280,9 +1279,9 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
static char *
-virStorageBackendCreateQemuImgSecretPath(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol)
+storageBackendCreateQemuImgSecretPath(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
{
virStorageEncryptionPtr enc = vol->target.encryption;
char *secretPath = NULL;
@@ -1349,12 +1348,12 @@ virStorageBackendCreateQemuImgSecretPath(virConnectPtr conn,
}
-int
-virStorageBackendCreateQemuImg(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags)
+static int
+storageBackendCreateQemuImg(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
{
int ret = -1;
char *create_tool;
@@ -1380,7 +1379,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
vol->target.encryption &&
vol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
if (!(secretPath =
- virStorageBackendCreateQemuImgSecretPath(conn, pool, vol)))
+ storageBackendCreateQemuImgSecretPath(conn, pool, vol)))
goto cleanup;
}
@@ -1418,15 +1417,15 @@ virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
(inputvol->type == VIR_STORAGE_VOL_FILE &&
(inputvol->target.format != VIR_STORAGE_FILE_RAW ||
inputvol->target.encryption != NULL))) {
- return virStorageBackendCreateQemuImg;
+ return storageBackendCreateQemuImg;
}
if (vol->type == VIR_STORAGE_VOL_PLOOP)
- return virStorageBackendCreatePloop;
+ return storageBackendCreatePloop;
if (vol->type == VIR_STORAGE_VOL_BLOCK)
- return virStorageBackendCreateBlockFrom;
+ return storageBackendCreateBlockFrom;
else
- return virStorageBackendCreateRaw;
+ return storageBackendCreateRaw;
}
@@ -2008,6 +2007,340 @@ virStorageBackendStablePath(virStoragePoolObjPtr pool,
return stablepath;
}
+/* Common/Local File System/Directory Volume API's */
+static int
+createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
+{
+ int err;
+
+ virCheckFlags(0, -1);
+
+ if (inputvol) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("cannot copy from volume to a directory volume"));
+ return -1;
+ }
+
+ if (vol->target.backingStore) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("backing storage not supported for directories
volumes"));
+ return -1;
+ }
+
+
+ if ((err = virDirCreate(vol->target.path,
+ (vol->target.perms->mode == (mode_t) -1 ?
+ VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
+ vol->target.perms->mode),
+ vol->target.perms->uid,
+ vol->target.perms->gid,
+ (pool->def->type == VIR_STORAGE_POOL_NETFS
+ ? VIR_DIR_CREATE_AS_UID : 0))) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Set up a volume definition to be added to a pool's volume list, but
+ * don't do any file creation or allocation. By separating the two processes,
+ * we allow allocation progress reporting (by polling the volume's 'info'
+ * function), and can drop the parent pool lock during the (slow) allocation.
+ */
+int
+virStorageBackendVolCreateLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+ if (vol->target.format == VIR_STORAGE_FILE_DIR)
+ vol->type = VIR_STORAGE_VOL_DIR;
+ else if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
+ vol->type = VIR_STORAGE_VOL_PLOOP;
+ else
+ vol->type = VIR_STORAGE_VOL_FILE;
+
+ /* Volumes within a directory pools are not recursive; do not
+ * allow escape to ../ or a subdir */
+ if (strchr(vol->name, '/')) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("volume name '%s' cannot contain
'/'"), vol->name);
+ return -1;
+ }
+
+ VIR_FREE(vol->target.path);
+ if (virAsprintf(&vol->target.path, "%s/%s",
+ pool->def->target.path,
+ vol->name) == -1)
+ return -1;
+
+ if (virFileExists(vol->target.path)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("volume target path '%s' already exists"),
+ vol->target.path);
+ return -1;
+ }
+
+ VIR_FREE(vol->key);
+ return VIR_STRDUP(vol->key, vol->target.path);
+}
+
+
+static int
+storageBackendVolBuildLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
+{
+ virStorageBackendBuildVolFrom create_func;
+
+ if (inputvol) {
+ if (vol->target.encryption != NULL) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("storage pool does not support "
+ "building encrypted volumes from "
+ "other volumes"));
+ return -1;
+ }
+ if (!(create_func =
+ virStorageBackendGetBuildVolFromFunction(vol, inputvol)))
+ return -1;
+ } else if (vol->target.format == VIR_STORAGE_FILE_RAW &&
+ vol->target.encryption == NULL) {
+ create_func = storageBackendCreateRaw;
+ } else if (vol->target.format == VIR_STORAGE_FILE_DIR) {
+ create_func = createFileDir;
+ } else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
+ create_func = storageBackendCreatePloop;
+ } else {
+ create_func = storageBackendCreateQemuImg;
+ }
+
+ if (create_func(conn, pool, vol, inputvol, flags) < 0)
+ return -1;
+ return 0;
+}
+
+
+/**
+ * Allocate a new file as a volume. This is either done directly
+ * for raw/sparse files, or by calling qemu-img for
+ * special kinds of files
+ */
+int
+virStorageBackendVolBuildLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned int flags)
+{
+ return storageBackendVolBuildLocal(conn, pool, vol, NULL, flags);
+}
+
+
+/*
+ * Create a storage vol using 'inputvol' as input
+ */
+int
+virStorageBackendVolBuildFromLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags)
+{
+ return storageBackendVolBuildLocal(conn, pool, vol, inputvol, flags);
+}
+
+
+/**
+ * Remove a volume - no support for BLOCK and NETWORK yet
+ */
+int
+virStorageBackendVolDeleteLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ virStorageVolDefPtr vol,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ switch ((virStorageVolType) vol->type) {
+ case VIR_STORAGE_VOL_FILE:
+ case VIR_STORAGE_VOL_DIR:
+ if (virFileRemove(vol->target.path, vol->target.perms->uid,
+ vol->target.perms->gid) < 0) {
+ /* Silently ignore failures where the vol has already gone away */
+ if (errno != ENOENT) {
+ if (vol->type == VIR_STORAGE_VOL_FILE)
+ virReportSystemError(errno,
+ _("cannot unlink file '%s'"),
+ vol->target.path);
+ else
+ virReportSystemError(errno,
+ _("cannot remove directory
'%s'"),
+ vol->target.path);
+ return -1;
+ }
+ }
+ break;
+ case VIR_STORAGE_VOL_PLOOP:
+ if (virFileDeleteTree(vol->target.path) < 0)
+ return -1;
+ break;
+ case VIR_STORAGE_VOL_BLOCK:
+ case VIR_STORAGE_VOL_NETWORK:
+ case VIR_STORAGE_VOL_NETDIR:
+ case VIR_STORAGE_VOL_LAST:
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("removing block or network volumes is not supported:
%s"),
+ vol->target.path);
+ return -1;
+ }
+ return 0;
+}
+
+
+/* storageBackendLoadDefaultSecrets:
+ * @conn: Connection pointer to fetch secret
+ * @vol: volume being refreshed
+ *
+ * If the volume had a secret generated, we need to regenerate the
+ * encryption secret information
+ *
+ * Returns 0 if no secret or secret setup was successful,
+ * -1 on failures w/ error message set
+ */
+static int
+storageBackendLoadDefaultSecrets(virConnectPtr conn,
+ virStorageVolDefPtr vol)
+{
+ virSecretPtr sec;
+ virStorageEncryptionSecretPtr encsec = NULL;
+
+ if (!vol->target.encryption || vol->target.encryption->nsecrets != 0)
+ return 0;
+
+ /* The encryption secret for qcow2 and luks volumes use the path
+ * to the volume, so look for a secret with the path. If not found,
+ * then we cannot generate the secret after a refresh (or restart).
+ * This may be the case if someone didn't follow instructions and created
+ * a usage string that although matched with the secret usage string,
+ * didn't contain the path to the volume. We won't error in that case,
+ * but we also cannot find the secret. */
+ if (!(sec = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_VOLUME,
+ vol->target.path)))
+ return 0;
+
+ if (VIR_ALLOC_N(vol->target.encryption->secrets, 1) < 0 ||
+ VIR_ALLOC(encsec) < 0) {
+ VIR_FREE(vol->target.encryption->secrets);
+ virObjectUnref(sec);
+ return -1;
+ }
+
+ vol->target.encryption->nsecrets = 1;
+ vol->target.encryption->secrets[0] = encsec;
+
+ encsec->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
+ encsec->seclookupdef.type = VIR_SECRET_LOOKUP_TYPE_UUID;
+ virSecretGetUUID(sec, encsec->seclookupdef.u.uuid);
+ virObjectUnref(sec);
+
+ return 0;
+}
+
+
+/**
+ * Update info about a volume's capacity/allocation
+ */
+int
+virStorageBackendVolRefreshLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ virStorageVolDefPtr vol)
+{
+ int ret;
+
+ /* Refresh allocation / capacity / permissions info in case its changed */
+ if ((ret = virStorageBackendUpdateVolInfo(vol, false,
+ VIR_STORAGE_VOL_FS_OPEN_FLAGS,
+ 0)) < 0)
+ return ret;
+
+ /* Load any secrets if possible */
+ return storageBackendLoadDefaultSecrets(conn, vol);
+}
+
+
+static int
+storageBackendResizeQemuImg(const char *path,
+ unsigned long long capacity)
+{
+ int ret = -1;
+ char *img_tool;
+ virCommandPtr cmd = NULL;
+
+ img_tool = virFindFileInPath("qemu-img");
+ if (!img_tool) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("unable to find qemu-img"));
+ return -1;
+ }
+
+ /* Round capacity as qemu-img resize errors out on sizes which are not
+ * a multiple of 512 */
+ capacity = VIR_ROUND_UP(capacity, 512);
+
+ cmd = virCommandNew(img_tool);
+ virCommandAddArgList(cmd, "resize", path, NULL);
+ virCommandAddArgFormat(cmd, "%llu", capacity);
+
+ ret = virCommandRun(cmd, NULL);
+
+ VIR_FREE(img_tool);
+ virCommandFree(cmd);
+
+ return ret;
+}
+
+
+/**
+ * Resize a volume
+ */
+int
+virStorageBackendVolResizeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ virStorageVolDefPtr vol,
+ unsigned long long capacity,
+ unsigned int flags)
+{
+ virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
+ VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
+
+ bool pre_allocate = flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE;
+
+ if (vol->target.format == VIR_STORAGE_FILE_RAW) {
+ return virStorageFileResize(vol->target.path, capacity,
+ vol->target.allocation, pre_allocate);
+ } else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
+ return storagePloopResize(vol, capacity);
+ } else {
+ if (pre_allocate) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("preallocate is only supported for raw "
+ "type volume"));
+ return -1;
+ }
+
+ return storageBackendResizeQemuImg(vol->target.path, capacity);
+ }
+}
+
+
/*
* Check whether the ploop image has snapshots.
* return: -1 - failed to check
@@ -2015,7 +2348,7 @@ virStorageBackendStablePath(virStoragePoolObjPtr pool,
* 1 - at least one snapshot
*/
static int
-virStorageBackendPloopHasSnapshots(char *path)
+storageBackendPloopHasSnapshots(char *path)
{
virCommandPtr cmd = NULL;
char *output = NULL;
@@ -2049,6 +2382,7 @@ virStorageBackendPloopHasSnapshots(char *path)
return ret;
}
+
int
virStorageBackendVolUploadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
@@ -2070,7 +2404,7 @@ virStorageBackendVolUploadLocal(virConnectPtr conn
ATTRIBUTE_UNUSED,
* when volUpload is fully finished. */
if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
/* Fail if the volume contains snapshots or we failed to check it.*/
- has_snap = virStorageBackendPloopHasSnapshots(vol->target.path);
+ has_snap = storageBackendPloopHasSnapshots(vol->target.path);
if (has_snap < 0) {
goto cleanup;
} else if (!has_snap) {
@@ -2111,7 +2445,7 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn
ATTRIBUTE_UNUSED,
virCheckFlags(0, -1);
if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
- has_snap = virStorageBackendPloopHasSnapshots(vol->target.path);
+ has_snap = storageBackendPloopHasSnapshots(vol->target.path);
if (has_snap < 0) {
goto cleanup;
} else if (!has_snap) {
@@ -2149,9 +2483,9 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn
ATTRIBUTE_UNUSED,
* appear as if it were zero-filled.
*/
static int
-virStorageBackendVolZeroSparseFileLocal(const char *path,
- off_t size,
- int fd)
+storageBackendVolZeroSparseFileLocal(const char *path,
+ off_t size,
+ int fd)
{
if (ftruncate(fd, 0) < 0) {
virReportSystemError(errno,
@@ -2174,10 +2508,10 @@ virStorageBackendVolZeroSparseFileLocal(const char *path,
static int
-virStorageBackendWipeLocal(const char *path,
- int fd,
- unsigned long long wipe_len,
- size_t writebuf_length)
+storageBackendWipeLocal(const char *path,
+ int fd,
+ unsigned long long wipe_len,
+ size_t writebuf_length)
{
int ret = -1, written = 0;
unsigned long long remaining = 0;
@@ -2232,9 +2566,9 @@ virStorageBackendWipeLocal(const char *path,
static int
-virStorageBackendVolWipeLocalFile(const char *path,
- unsigned int algorithm,
- unsigned long long allocation)
+storageBackendVolWipeLocalFile(const char *path,
+ unsigned int algorithm,
+ unsigned long long allocation)
{
int ret = -1, fd = -1;
const char *alg_char = NULL;
@@ -2307,12 +2641,9 @@ virStorageBackendVolWipeLocalFile(const char *path,
ret = 0;
} else {
if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
- ret = virStorageBackendVolZeroSparseFileLocal(path, st.st_size, fd);
+ ret = storageBackendVolZeroSparseFileLocal(path, st.st_size, fd);
} else {
- ret = virStorageBackendWipeLocal(path,
- fd,
- allocation,
- st.st_blksize);
+ ret = storageBackendWipeLocal(path, fd, allocation, st.st_blksize);
}
if (ret < 0)
goto cleanup;
@@ -2326,8 +2657,8 @@ virStorageBackendVolWipeLocalFile(const char *path,
static int
-virStorageBackendVolWipePloop(virStorageVolDefPtr vol,
- unsigned int algorithm)
+storageBackendVolWipePloop(virStorageVolDefPtr vol,
+ unsigned int algorithm)
{
virCommandPtr cmd = NULL;
char *target_path = NULL;
@@ -2349,9 +2680,8 @@ virStorageBackendVolWipePloop(virStorageVolDefPtr vol,
if (virAsprintf(&disk_desc, "%s/DiskDescriptor.xml",
vol->target.path) < 0)
goto cleanup;
- if (virStorageBackendVolWipeLocalFile(target_path,
- algorithm,
- vol->target.allocation) < 0)
+ if (storageBackendVolWipeLocalFile(target_path, algorithm,
+ vol->target.allocation) < 0)
goto cleanup;
if (virFileRemove(disk_desc, 0, 0) < 0) {
@@ -2397,11 +2727,10 @@ virStorageBackendVolWipeLocal(virConnectPtr conn
ATTRIBUTE_UNUSED,
vol->target.path, algorithm);
if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
- ret = virStorageBackendVolWipePloop(vol, algorithm);
+ ret = storageBackendVolWipePloop(vol, algorithm);
} else {
- ret = virStorageBackendVolWipeLocalFile(vol->target.path,
- algorithm,
- vol->target.allocation);
+ ret = storageBackendVolWipeLocalFile(vol->target.path, algorithm,
+ vol->target.allocation);
}
return ret;
diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h
index f5a1b5b..49df530 100644
--- a/src/storage/storage_util.h
+++ b/src/storage/storage_util.h
@@ -28,30 +28,39 @@
# include "storage_backend.h"
/* File creation/cloning functions used for cloning between backends */
-int virStorageBackendCreateRaw(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags);
+virStorageBackendBuildVolFrom
+virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol);
+
+int virStorageBackendVolCreateLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol);
-int virStorageBackendCreateQemuImg(virConnectPtr conn,
+int virStorageBackendVolBuildLocal(virConnectPtr conn,
virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
unsigned int flags);
-int virStorageBackendCreatePloop(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol,
- unsigned int flags);
+int virStorageBackendVolBuildFromLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ virStorageVolDefPtr inputvol,
+ unsigned int flags);
+
+int virStorageBackendVolDeleteLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned int flags);
-int virStoragePloopResize(virStorageVolDefPtr vol,
- unsigned long long capacity);
+int virStorageBackendVolRefreshLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol);
-virStorageBackendBuildVolFrom
-virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
- virStorageVolDefPtr inputvol);
+int virStorageBackendVolResizeLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned long long capacity,
+ unsigned int flags);
int virStorageBackendVolUploadLocal(virConnectPtr conn,
virStoragePoolObjPtr pool,
@@ -60,6 +69,7 @@ int virStorageBackendVolUploadLocal(virConnectPtr conn,
unsigned long long offset,
unsigned long long len,
unsigned int flags);
+
int virStorageBackendVolDownloadLocal(virConnectPtr conn,
virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
--
2.7.4