mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
storage: Properly resize a local volume using LUKS
https://bugzilla.redhat.com/show_bug.cgi?id=1490279 Turns out the virStorageBackendVolResizeLocal did not differentiate whether the target volume was a LUKS volume or not and just blindly did the ftruncate() on the target volume. Follow the volume creation logic (in general) and create a qemu-img resize command to resize the target volume for LUKS ensuring that the --object secret is provided as well as the '--image-opts' used by the qemu-img resize logic to describe the path and secret ensuring that it's using the luks driver on the volume of course.
This commit is contained in:
parent
03984ae543
commit
becb383a63
@ -1143,6 +1143,37 @@ storageBackendCreateQemuImgSecretObject(virCommandPtr cmd,
|
||||
}
|
||||
|
||||
|
||||
/* Add a --image-opts to the qemu-img resize command line:
|
||||
* --image-opts driver=luks,file.filename=$volpath,key-secret=$secretAlias
|
||||
*
|
||||
* NB: format=raw is assumed
|
||||
*/
|
||||
static int
|
||||
storageBackendResizeQemuImgImageOpts(virCommandPtr cmd,
|
||||
const char *path,
|
||||
const char *secretAlias)
|
||||
{
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
char *commandStr = NULL;
|
||||
|
||||
virBufferAsprintf(&buf, "driver=luks,key-secret=%s,file.filename=",
|
||||
secretAlias);
|
||||
virQEMUBuildBufferEscapeComma(&buf, path);
|
||||
|
||||
if (virBufferCheckError(&buf) < 0) {
|
||||
virBufferFreeAndReset(&buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
commandStr = virBufferContentAndReset(&buf);
|
||||
|
||||
virCommandAddArgList(cmd, "--image-opts", commandStr, NULL);
|
||||
|
||||
VIR_FREE(commandStr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Create a qemu-img virCommand from the supplied binary path,
|
||||
* volume definitions and imgformat
|
||||
*/
|
||||
@ -2286,12 +2317,17 @@ virStorageBackendVolRefreshLocal(virConnectPtr conn,
|
||||
|
||||
|
||||
static int
|
||||
storageBackendResizeQemuImg(virStorageVolDefPtr vol,
|
||||
storageBackendResizeQemuImg(virConnectPtr conn,
|
||||
virStoragePoolObjPtr pool,
|
||||
virStorageVolDefPtr vol,
|
||||
unsigned long long capacity)
|
||||
{
|
||||
int ret = -1;
|
||||
char *img_tool;
|
||||
char *img_tool = NULL;
|
||||
virCommandPtr cmd = NULL;
|
||||
const char *type;
|
||||
char *secretPath = NULL;
|
||||
char *secretAlias = NULL;
|
||||
|
||||
img_tool = virFindFileInPath("qemu-img");
|
||||
if (!img_tool) {
|
||||
@ -2300,19 +2336,56 @@ storageBackendResizeQemuImg(virStorageVolDefPtr vol,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vol->target.encryption) {
|
||||
if (vol->target.format == VIR_STORAGE_FILE_RAW)
|
||||
type = "luks";
|
||||
else
|
||||
type = virStorageFileFormatTypeToString(vol->target.format);
|
||||
|
||||
storageBackendLoadDefaultSecrets(conn, vol);
|
||||
|
||||
if (storageBackendCreateQemuImgCheckEncryption(vol->target.format,
|
||||
type, NULL, vol) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!(secretPath =
|
||||
storageBackendCreateQemuImgSecretPath(conn, pool, vol)))
|
||||
goto cleanup;
|
||||
|
||||
if (virAsprintf(&secretAlias, "%s_luks0", vol->name) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* 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", vol->target.path, NULL);
|
||||
if (!vol->target.encryption) {
|
||||
virCommandAddArgList(cmd, "resize", vol->target.path, NULL);
|
||||
} else {
|
||||
virCommandAddArg(cmd, "resize");
|
||||
|
||||
if (storageBackendCreateQemuImgSecretObject(cmd, secretPath,
|
||||
secretAlias) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (storageBackendResizeQemuImgImageOpts(cmd, vol->target.path,
|
||||
secretAlias) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
virCommandAddArgFormat(cmd, "%llu", capacity);
|
||||
|
||||
ret = virCommandRun(cmd, NULL);
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(img_tool);
|
||||
if (secretPath) {
|
||||
unlink(secretPath);
|
||||
VIR_FREE(secretPath);
|
||||
}
|
||||
VIR_FREE(secretAlias);
|
||||
virCommandFree(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2321,8 +2394,8 @@ storageBackendResizeQemuImg(virStorageVolDefPtr vol,
|
||||
* Resize a volume
|
||||
*/
|
||||
int
|
||||
virStorageBackendVolResizeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
||||
virStorageBackendVolResizeLocal(virConnectPtr conn,
|
||||
virStoragePoolObjPtr pool,
|
||||
virStorageVolDefPtr vol,
|
||||
unsigned long long capacity,
|
||||
unsigned int flags)
|
||||
@ -2332,8 +2405,17 @@ virStorageBackendVolResizeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
|
||||
VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
|
||||
|
||||
if (vol->target.format == VIR_STORAGE_FILE_RAW) {
|
||||
if (vol->target.format == VIR_STORAGE_FILE_RAW && !vol->target.encryption) {
|
||||
return virStorageFileResize(vol->target.path, capacity, pre_allocate);
|
||||
} else if (vol->target.format == VIR_STORAGE_FILE_RAW && vol->target.encryption) {
|
||||
if (pre_allocate) {
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||
_("preallocate is only supported for raw "
|
||||
"type volume"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return storageBackendResizeQemuImg(conn, pool, vol, capacity);
|
||||
} else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
|
||||
return storagePloopResize(vol, capacity);
|
||||
} else {
|
||||
@ -2344,7 +2426,7 @@ virStorageBackendVolResizeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
return -1;
|
||||
}
|
||||
|
||||
return storageBackendResizeQemuImg(vol, capacity);
|
||||
return storageBackendResizeQemuImg(conn, pool, vol, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user