From nobody Thu May 15 08:46:28 2025
Delivered-To: importer@patchew.org
Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28
as permitted sender) client-ip=209.132.183.28;
envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com;
Authentication-Results: mx.zohomail.com;
spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as
permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com;
dmarc=pass(p=none dis=none) header.from=redhat.com
Return-Path: uuid
.
+ Since 4.4.0, the command line generated
+ by libvirt to create a default
or qcow
+ encrypted volume has changed. This is a result of changes made
+ to qemu-img in QEMU 2.9 which requires different arguments to be
+ provided in order to create a qcow encrypted volume. This change
+ is not compatible with older qemu-img images and there is no plan
+ to provide backwards compatibility. It is strongly recommended
+ to use the "luks" encryption format.
+
<encryption format=3D"default"/>
can be specified=
only
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index a8a6a3e401..29adf0cdbe 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -943,12 +943,15 @@ storageBackendCreateQemuImgCheckEncryption(int format,
=20
static int
storageBackendCreateQemuImgSetInput(virStorageVolDefPtr inputvol,
+ virStorageVolEncryptConvertStep conver=
tStep,
struct _virStorageBackendQemuImgInfo *=
info)
{
- if (!(info->inputPath =3D inputvol->target.path)) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("missing input volume target path"));
- return -1;
+ if (convertStep !=3D VIR_STORAGE_VOL_ENCRYPT_CREATE) {
+ if (!(info->inputPath =3D inputvol->target.path)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("missing input volume target path"));
+ return -1;
+ }
}
=20
info->inputFormat =3D inputvol->target.format;
@@ -1119,6 +1122,7 @@ static int
virStorageBackendCreateQemuImgSetInfo(virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol,
+ virStorageVolEncryptConvertStep conv=
ertStep,
struct _virStorageBackendQemuImgInfo=
*info)
{
/* Treat output block devices as 'raw' format */
@@ -1166,7 +1170,7 @@ virStorageBackendCreateQemuImgSetInfo(virStoragePoolO=
bjPtr pool,
}
=20
if (inputvol &&
- storageBackendCreateQemuImgSetInput(inputvol, info) < 0)
+ storageBackendCreateQemuImgSetInput(inputvol, convertStep, info) <=
0)
return -1;
=20
if (virStorageSourceHasBacking(&vol->target) &&
@@ -1185,6 +1189,27 @@ virStorageBackendCreateQemuImgSetInfo(virStoragePool=
ObjPtr pool,
}
=20
=20
+static void
+virStorageBackendCreateQemuImgCmdEncryptConvert(virCommandPtr cmd,
+ virStorageEncryptionPtr en=
c,
+ struct _virStorageBackendQ=
emuImgInfo info)
+{
+ /* source */
+ virCommandAddArgFormat(cmd, "driver=3Draw,file.filename=3D%s", info.in=
putPath);
+
+ /* dest */
+ if (enc->format =3D=3D VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
+ virCommandAddArgFormat(cmd,
+ "driver=3Dluks,file.filename=3D%s,key-secre=
t=3D%s",
+ info.path, info.secretAlias);
+ } else {
+ virCommandAddArgFormat(cmd,
+ "driver=3Dqcow2,file.filename=3D%s,encrypt.=
key-secret=3D%s",
+ info.path, info.secretAlias);
+ }
+}
+
+
/* Create a qemu-img virCommand from the supplied arguments */
virCommandPtr
virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool,
@@ -1192,7 +1217,8 @@ virStorageBackendCreateQemuImgCmdFromVol(virStoragePo=
olObjPtr pool,
virStorageVolDefPtr inputvol,
unsigned int flags,
const char *create_tool,
- const char *secretPath)
+ const char *secretPath,
+ virStorageVolEncryptConvertStep c=
onvertStep)
{
virCommandPtr cmd =3D NULL;
struct _virStorageBackendQemuImgInfo info =3D {
@@ -1208,22 +1234,30 @@ virStorageBackendCreateQemuImgCmdFromVol(virStorage=
PoolObjPtr pool,
.secretPath =3D secretPath,
.secretAlias =3D NULL,
};
- virStorageEncryptionInfoDefPtr enc =3D NULL;
+ virStorageEncryptionPtr enc =3D NULL;
+ virStorageEncryptionInfoDefPtr encinfo =3D NULL;
=20
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
=20
- if (virStorageBackendCreateQemuImgSetInfo(pool, vol, inputvol, &info) =
< 0)
+ if (virStorageBackendCreateQemuImgSetInfo(pool, vol, inputvol,
+ convertStep, &info) < 0)
goto error;
=20
cmd =3D virCommandNew(create_tool);
=20
- /* ignore the backing volume when we're converting a volume */
- if (info.inputPath)
+ /* ignore the backing volume when we're converting a volume
+ * including when we're doing a two step convert during create */
+ if (info.inputPath || convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_CREAT=
E)
info.backingPath =3D NULL;
=20
- if (info.inputPath)
+ /* Converting to use encryption is a two step process - step 1 is to
+ * create the image and step 2 is to convert it using special argument=
s */
+ if (info.inputPath && convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_NONE)
virCommandAddArgList(cmd, "convert", "-f", info.inputFormatStr,
"-O", info.type, NULL);
+ else if (info.inputPath && convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_=
CONVERT)
+ virCommandAddArgList(cmd, "convert", "--image-opts", "-n",
+ "--target-image-opts", NULL);
else
virCommandAddArgList(cmd, "create", "-f", info.type, NULL);
=20
@@ -1241,19 +1275,23 @@ virStorageBackendCreateQemuImgCmdFromVol(virStorage=
PoolObjPtr pool,
if (storageBackendCreateQemuImgSecretObject(cmd, info.secretPath,
info.secretAlias) < 0)
goto error;
- enc =3D &vol->target.encryption->encinfo;
+ enc =3D vol->target.encryption;
+ encinfo =3D &enc->encinfo;
}
=20
- if (storageBackendCreateQemuImgSetOptions(cmd, enc, info) < 0)
- goto error;
+ if (convertStep !=3D VIR_STORAGE_VOL_ENCRYPT_CONVERT) {
+ if (storageBackendCreateQemuImgSetOptions(cmd, encinfo, info) < 0)
+ goto error;
+ if (info.inputPath)
+ virCommandAddArg(cmd, info.inputPath);
+ virCommandAddArg(cmd, info.path);
+ if (!info.inputPath && (info.size_arg || !info.backingPath))
+ virCommandAddArgFormat(cmd, "%lluK", info.size_arg);
+ } else {
+ virStorageBackendCreateQemuImgCmdEncryptConvert(cmd, enc, info);
+ }
VIR_FREE(info.secretAlias);
=20
- if (info.inputPath)
- virCommandAddArg(cmd, info.inputPath);
- virCommandAddArg(cmd, info.path);
- if (!info.inputPath && (info.size_arg || !info.backingPath))
- virCommandAddArgFormat(cmd, "%lluK", info.size_arg);
-
return cmd;
=20
error:
@@ -1360,14 +1398,15 @@ storageBackendDoCreateQemuImg(virStoragePoolObjPtr =
pool,
virStorageVolDefPtr inputvol,
unsigned int flags,
const char *create_tool,
- const char *secretPath)
+ const char *secretPath,
+ virStorageVolEncryptConvertStep convertStep)
{
int ret;
virCommandPtr cmd;
=20
cmd =3D virStorageBackendCreateQemuImgCmdFromVol(pool, vol, inputvol,
flags, create_tool,
- secretPath);
+ secretPath, convertStep=
);
if (!cmd)
return -1;
=20
@@ -1388,6 +1427,7 @@ storageBackendCreateQemuImg(virStoragePoolObjPtr pool,
int ret =3D -1;
char *create_tool;
char *secretPath =3D NULL;
+ virStorageVolEncryptConvertStep convertStep =3D VIR_STORAGE_VOL_ENCRYP=
T_NONE;
=20
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
=20
@@ -1402,8 +1442,33 @@ storageBackendCreateQemuImg(virStoragePoolObjPtr poo=
l,
if (storageBackendGenerateSecretData(pool, vol, &secretPath) < 0)
goto cleanup;
=20
- ret =3D storageBackendDoCreateQemuImg(pool, vol, inputvol, flags,
- create_tool, secretPath);
+ /* Using an input file for encryption requires a multi-step process
+ * to create an image of the same size as the inputvol and then to
+ * convert the inputvol afterwards. */
+ if (secretPath && inputvol)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_CREATE;
+
+ do {
+ ret =3D storageBackendDoCreateQemuImg(pool, vol, inputvol, flags,
+ create_tool, secretPath,
+ convertStep);
+
+ /* Failure to convert, attempt to delete what we created */
+ if (ret < 0 && convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ ignore_value(virFileRemove(vol->target.path,
+ vol->target.perms->uid,
+ vol->target.perms->gid));
+
+ if (ret < 0 || convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_NONE)
+ goto cleanup;
+
+ if (convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_CREATE)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_CONVERT;
+ else if (convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_DONE;
+ } while (convertStep !=3D VIR_STORAGE_VOL_ENCRYPT_DONE);
+
+
cleanup:
if (secretPath) {
unlink(secretPath);
diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h
index 9307702754..6fc8e8972c 100644
--- a/src/storage/storage_util.h
+++ b/src/storage/storage_util.h
@@ -153,13 +153,21 @@ char *virStorageBackendStablePath(virStoragePoolObjPt=
r pool,
const char *devpath,
bool loop);
=20
+typedef enum {
+ VIR_STORAGE_VOL_ENCRYPT_NONE =3D 0,
+ VIR_STORAGE_VOL_ENCRYPT_CREATE,
+ VIR_STORAGE_VOL_ENCRYPT_CONVERT,
+ VIR_STORAGE_VOL_ENCRYPT_DONE,
+} virStorageVolEncryptConvertStep;
+
virCommandPtr
virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol,
unsigned int flags,
const char *create_tool,
- const char *secretPath);
+ const char *secretPath,
+ virStorageVolEncryptConvertStep c=
onvertStep);
=20
int virStorageBackendSCSIFindLUs(virStoragePoolObjPtr pool,
uint32_t scanhost);
diff --git a/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv b/=
tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv
index 849c5f0218..46d54d01c6 100644
--- a/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv
+++ b/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv
@@ -1,4 +1,9 @@
-qemu-img convert -f raw -O qcow2 \
+qemu-img create -f qcow2 \
--object secret,id=3DOtherDemo.img_encrypt0,file=3D/path/to/secretFile \
-o encrypt.format=3Daes,encrypt.key-secret=3DOtherDemo.img_encrypt0,compat=
=3D0.10 \
-/dev/HostVG/Swap /var/lib/libvirt/images/OtherDemo.img
+/var/lib/libvirt/images/OtherDemo.img 5242880K
+qemu-img convert --image-opts -n --target-image-opts \
+--object secret,id=3DOtherDemo.img_encrypt0,file=3D/path/to/secretFile \
+driver=3Draw,file.filename=3D/dev/HostVG/Swap \
+driver=3Dqcow2,file.filename=3D/var/lib/libvirt/images/OtherDemo.img,\
+encrypt.key-secret=3DOtherDemo.img_encrypt0
diff --git a/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-=
compat.argv b/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc=
-compat.argv
index a95749eafa..b755c1e9c4 100644
--- a/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.=
argv
+++ b/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.=
argv
@@ -1,5 +1,10 @@
-qemu-img convert -f raw -O qcow2 \
+qemu-img create -f qcow2 \
--object secret,id=3DOtherDemo.img_encrypt0,file=3D/path/to/secretFile \
-o encrypt.format=3Daes,encrypt.key-secret=3DOtherDemo.img_encrypt0,\
preallocation=3Dmetadata,compat=3D0.10 \
-/var/lib/libvirt/images/sparse.img /var/lib/libvirt/images/OtherDemo.img
+/var/lib/libvirt/images/OtherDemo.img 5242880K
+qemu-img convert --image-opts -n --target-image-opts \
+--object secret,id=3DOtherDemo.img_encrypt0,file=3D/path/to/secretFile \
+driver=3Draw,file.filename=3D/var/lib/libvirt/images/sparse.img \
+driver=3Dqcow2,file.filename=3D/var/lib/libvirt/images/OtherDemo.img,\
+encrypt.key-secret=3DOtherDemo.img_encrypt0
diff --git a/tests/storagevolxml2argvdata/qcow2-nocapacity-convert-prealloc=
.argv b/tests/storagevolxml2argvdata/qcow2-nocapacity-convert-prealloc.argv
index 51bdaaf684..fca8cba49b 100644
--- a/tests/storagevolxml2argvdata/qcow2-nocapacity-convert-prealloc.argv
+++ b/tests/storagevolxml2argvdata/qcow2-nocapacity-convert-prealloc.argv
@@ -1,5 +1,10 @@
-qemu-img convert -f raw -O qcow2 \
+qemu-img create -f qcow2 \
--object secret,id=3DOtherDemo.img_encrypt0,file=3D/path/to/secretFile \
-o encrypt.format=3Daes,encrypt.key-secret=3DOtherDemo.img_encrypt0,\
preallocation=3Dfalloc,compat=3D0.10 \
-/var/lib/libvirt/images/sparse.img /var/lib/libvirt/images/OtherDemo.img
+/var/lib/libvirt/images/OtherDemo.img 0K
+qemu-img convert --image-opts -n --target-image-opts \
+--object secret,id=3DOtherDemo.img_encrypt0,file=3D/path/to/secretFile \
+driver=3Draw,file.filename=3D/var/lib/libvirt/images/sparse.img \
+driver=3Dqcow2,file.filename=3D/var/lib/libvirt/images/OtherDemo.img,\
+encrypt.key-secret=3DOtherDemo.img_encrypt0
diff --git a/tests/storagevolxml2argvtest.c b/tests/storagevolxml2argvtest.c
index 4286c50c6e..e72e08a7d2 100644
--- a/tests/storagevolxml2argvtest.c
+++ b/tests/storagevolxml2argvtest.c
@@ -43,6 +43,7 @@ testCompareXMLToArgvFiles(bool shouldFail,
unsigned long parse_flags)
{
char *actualCmdline =3D NULL;
+ virStorageVolEncryptConvertStep convertStep =3D VIR_STORAGE_VOL_ENCRYP=
T_NONE;
int ret =3D -1;
=20
virCommandPtr cmd =3D NULL;
@@ -79,20 +80,56 @@ testCompareXMLToArgvFiles(bool shouldFail,
testSetVolumeType(vol, def);
testSetVolumeType(inputvol, inputpool);
=20
- cmd =3D virStorageBackendCreateQemuImgCmdFromVol(obj, vol,
- inputvol, flags,
- create_tool,
- "/path/to/secretFile");
- if (!cmd) {
- if (shouldFail) {
- virResetLastError();
- ret =3D 0;
+ /* Using an input file for encryption requires a multi-step process
+ * to create an image of the same size as the inputvol and then to
+ * convert the inputvol afterwards. Since we only care about the
+ * command line we have to copy code from storageBackendCreateQemuImg
+ * and adjust it for the test needs. */
+ if (inputvol && vol->target.encryption)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_CREATE;
+
+ do {
+ cmd =3D virStorageBackendCreateQemuImgCmdFromVol(obj, vol,
+ inputvol, flags,
+ create_tool,
+ "/path/to/secretFil=
e",
+ convertStep);
+ if (!cmd) {
+ if (shouldFail) {
+ virResetLastError();
+ ret =3D 0;
+ }
+ goto cleanup;
}
- goto cleanup;
- }
=20
- if (!(actualCmdline =3D virCommandToString(cmd)))
- goto cleanup;
+ if (convertStep !=3D VIR_STORAGE_VOL_ENCRYPT_CONVERT) {
+ if (!(actualCmdline =3D virCommandToString(cmd)))
+ goto cleanup;
+ } else {
+ char *createCmdline =3D actualCmdline;
+ char *cvtCmdline;
+ int rc;
+
+ if (!(cvtCmdline =3D virCommandToString(cmd)))
+ goto cleanup;
+
+ rc =3D virAsprintf(&actualCmdline, "%s\n%s",
+ createCmdline, cvtCmdline);
+
+ VIR_FREE(createCmdline);
+ VIR_FREE(cvtCmdline);
+ if (rc < 0)
+ goto cleanup;
+ }
+
+ if (convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_NONE)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_DONE;
+ else if (convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_CREATE)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_CONVERT;
+ else if (convertStep =3D=3D VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ convertStep =3D VIR_STORAGE_VOL_ENCRYPT_DONE;
+
+ } while (convertStep !=3D VIR_STORAGE_VOL_ENCRYPT_DONE);
=20
if (virTestCompareToFile(actualCmdline, cmdline) < 0)
goto cleanup;
--=20
2.14.3
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list