[libvirt] [PATCH v4 4/7] storage: Add support to create a luks volume

Ján Tomko jtomko at redhat.com
Thu Jul 14 13:13:56 UTC 2016


On Mon, Jul 11, 2016 at 02:07:55PM -0400, John Ferlan wrote:
>Partially resolves:
>https://bugzilla.redhat.com/show_bug.cgi?id=1301021
>
>If the volume xml was looking to create a luks volume take the necessary
>steps in order to make that happen.
>
>The processing will be:
> 1. create a temporary file (virStorageBackendCreateQemuImgSecretPath)
>   1a. use the storage driver state dir path that uses the pool and
>       volume name as a base.
>
> 2. create a secret object (virStorageBackendCreateQemuImgSecretObject)
>   2a. use an alias combinding the volume name and "_luks0"
>   2b. add the file to the object
>
> 3. create/add luks options to the commandline (virQEMUBuildLuksOpts)
>   3a. at the very least a "key-secret=%s" using the secret object alias
>   3b. if found in the XML the various "cipher" and "ivgen" options
>
>Signed-off-by: John Ferlan <jferlan at redhat.com>
>---
> src/libvirt_private.syms       |   1 +
> src/storage/storage_backend.c  | 218 ++++++++++++++++++++++++++++++++++++++---
> src/storage/storage_backend.h  |   3 +-
> src/util/virqemu.c             |  23 +++++
> src/util/virqemu.h             |   6 ++
> tests/storagevolxml2argvtest.c |   3 +-
> 6 files changed, 240 insertions(+), 14 deletions(-)
>

>@@ -1140,6 +1186,43 @@ virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
> }
>
>
>+/* Add a secret object to the command line:
>+ *    --object secret,id=$secretAlias,file=$secretPath
>+ *
>+ *    NB: format=raw is assumed
>+ */
>+static int
>+virStorageBackendCreateQemuImgSecretObject(virCommandPtr cmd,
>+                                           virStorageVolDefPtr vol,
>+                                           struct _virStorageBackendQemuImgInfo *info)
>+{
>+    char *str = NULL;

This variable is unused.

>+    virJSONValuePtr props = NULL;
>+    char *commandStr = NULL;
>+

>+    if (virAsprintf(&info->secretAlias, "%s_luks0", vol->name) < 0) {
>+        VIR_FREE(str);
>+        return -1;
>+    }
>+    VIR_FREE(str);
>+
>+    if (virJSONValueObjectCreate(&props, "s:file", info->secretPath, NULL) < 0)
>+        return -1;
>+
>+    if (!(commandStr = virQEMUBuildObjectCommandlineFromJSON("secret",
>+                                                             info->secretAlias,
>+                                                             props))) {
>+        virJSONValueFree(props);
>+        return -1;
>+    }
>+    virJSONValueFree(props);
>+

So, this will generate:
--object secret,id=volume_luks0,file=/path/to/tmp/luksfile

Since we only have one property and one alias here, there is no need to
go through JSON, it can be just a single virCommandAddArgFormat call.

(or we need to go through a virBuffer to use qemuBufferEscapeComma in
case we allow commas in storage pool names).

>+    virCommandAddArgList(cmd, "--object", commandStr, NULL);
>+ 
>+    return 0;
>+}
>+
>+
> /* Create a qemu-img virCommand from the supplied binary path,
>  * volume definitions and imgformat
>  */
>@@ -1150,7 +1233,8 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
>                                          virStorageVolDefPtr inputvol,
>                                          unsigned int flags,
>                                          const char *create_tool,
>-                                         int imgformat)
>+                                         int imgformat,
>+                                         const char *secretPath)
> {
>     virCommandPtr cmd = NULL;
>     const char *type;
>@@ -1162,7 +1246,10 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
>         .compat = vol->target.compat,
>         .features = vol->target.features,
>         .nocow = vol->target.nocow,
>+        .secretPath = secretPath,
>+        .secretAlias = NULL,

Since we only ever give one secret on the command line, this can be a
static string.

>     };
>+    virStorageEncryptionInfoDefPtr enc = NULL;
>
>     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
>

>diff --git a/src/util/virqemu.c b/src/util/virqemu.c
>index 895168e..dd7a59f 100644
>--- a/src/util/virqemu.c
>+++ b/src/util/virqemu.c
>@@ -140,3 +140,26 @@ virQEMUBuildObjectCommandlineFromJSON(const char *type,
>     virBufferFreeAndReset(&buf);
>     return ret;
> }
>+
>+
>+void
>+virQEMUBuildLuksOpts(virBufferPtr buf,
>+                     virStorageEncryptionInfoDefPtr enc,
>+                     const char *alias)
>+{
>+    virBufferAsprintf(buf, "key-secret=%s,", alias);
>+
>+    /* If there's any cipher, then add that to the command line */

>+    if (enc->cipher_name) {
>+        virBufferEscapeString(buf, "cipher-alg=%s-", enc->cipher_name);
>+        virBufferAsprintf(buf, "%u,", enc->cipher_size);
>+        if (enc->cipher_mode)
>+            virBufferEscapeString(buf, "cipher-mode=%s,", enc->cipher_mode);
>+        if (enc->cipher_hash)
>+            virBufferEscapeString(buf, "hash-alg=%s,", enc->cipher_hash);
>+        if (enc->ivgen_name)
>+            virBufferEscapeString(buf, "ivgen-alg=%s,", enc->ivgen_name);
>+        if (enc->ivgen_hash)
>+            virBufferEscapeString(buf, "ivgen-hash-alg=%s,", enc->ivgen_hash);

s/virBufferEscapeString/qemuBufferEscapeComma/

This is QEMU command line, not XML. Also, both of the functions are
no-ops if the string is NULL, so the ifs are not necessary.

ACK with that fixed and the unused 'str' variable removed.

Jan




More information about the libvir-list mailing list