|
|
6ae9ed |
From 0e29f2d3041b0ab8dfcbc6bd4032aba6a69b56f6 Mon Sep 17 00:00:00 2001
|
|
|
6ae9ed |
Message-Id: <0e29f2d3041b0ab8dfcbc6bd4032aba6a69b56f6@dist-git>
|
|
|
6ae9ed |
From: John Ferlan <jferlan@redhat.com>
|
|
|
6ae9ed |
Date: Mon, 25 Jul 2016 12:42:57 -0400
|
|
|
6ae9ed |
Subject: [PATCH] storage: Add support to create a luks volume
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Partially resolves:
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1301021
|
|
|
6ae9ed |
|
|
|
6ae9ed |
If the volume xml was looking to create a luks volume take the necessary
|
|
|
6ae9ed |
steps in order to make that happen.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
The processing will be:
|
|
|
6ae9ed |
1. create a temporary file (virStorageBackendCreateQemuImgSecretPath)
|
|
|
6ae9ed |
1a. use the storage driver state dir path that uses the pool and
|
|
|
6ae9ed |
volume name as a base.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
2. create a secret object (virStorageBackendCreateQemuImgSecretObject)
|
|
|
6ae9ed |
2a. use an alias combinding the volume name and "_luks0"
|
|
|
6ae9ed |
2b. add the file to the object
|
|
|
6ae9ed |
|
|
|
6ae9ed |
3. create/add luks options to the commandline (virQEMUBuildLuksOpts)
|
|
|
6ae9ed |
3a. at the very least a "key-secret=%s" using the secret object alias
|
|
|
6ae9ed |
3b. if found in the XML the various "cipher" and "ivgen" options
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
|
|
6ae9ed |
(cherry picked from commit 5e46d7d6b693c1e3c9197c182302ac7125a856d9)
|
|
|
6ae9ed |
---
|
|
|
6ae9ed |
src/libvirt_private.syms | 1 +
|
|
|
6ae9ed |
src/storage/storage_backend.c | 214 ++++++++++++++++++++++++++++++++++++++---
|
|
|
6ae9ed |
src/storage/storage_backend.h | 3 +-
|
|
|
6ae9ed |
src/util/virqemu.c | 58 +++++++++++
|
|
|
6ae9ed |
src/util/virqemu.h | 6 ++
|
|
|
6ae9ed |
tests/storagevolxml2argvtest.c | 3 +-
|
|
|
6ae9ed |
6 files changed, 271 insertions(+), 14 deletions(-)
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
6ae9ed |
index c205fd8..f73cfa2 100644
|
|
|
6ae9ed |
--- a/src/libvirt_private.syms
|
|
|
6ae9ed |
+++ b/src/libvirt_private.syms
|
|
|
6ae9ed |
@@ -2193,6 +2193,7 @@ virProcessWait;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
# util/virqemu.h
|
|
|
6ae9ed |
virQEMUBuildBufferEscapeComma;
|
|
|
6ae9ed |
+virQEMUBuildLuksOpts;
|
|
|
6ae9ed |
virQEMUBuildObjectCommandlineFromJSON;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
|
|
|
6ae9ed |
index 97f6ffe..84ef4f2 100644
|
|
|
6ae9ed |
--- a/src/storage/storage_backend.c
|
|
|
6ae9ed |
+++ b/src/storage/storage_backend.c
|
|
|
6ae9ed |
@@ -55,11 +55,14 @@
|
|
|
6ae9ed |
#include "viralloc.h"
|
|
|
6ae9ed |
#include "internal.h"
|
|
|
6ae9ed |
#include "secret_conf.h"
|
|
|
6ae9ed |
+#include "secret_util.h"
|
|
|
6ae9ed |
#include "viruuid.h"
|
|
|
6ae9ed |
#include "virstoragefile.h"
|
|
|
6ae9ed |
#include "storage_backend.h"
|
|
|
6ae9ed |
#include "virlog.h"
|
|
|
6ae9ed |
#include "virfile.h"
|
|
|
6ae9ed |
+#include "virjson.h"
|
|
|
6ae9ed |
+#include "virqemu.h"
|
|
|
6ae9ed |
#include "stat-time.h"
|
|
|
6ae9ed |
#include "virstring.h"
|
|
|
6ae9ed |
#include "virxml.h"
|
|
|
6ae9ed |
@@ -907,6 +910,7 @@ virStorageBackendQemuImgSupportsCompat(const char *qemuimg)
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
static int
|
|
|
6ae9ed |
virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
@@ -925,6 +929,10 @@ virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+/* The _virStorageBackendQemuImgInfo separates the command line building from
|
|
|
6ae9ed |
+ * the volume definition so that qemuDomainSnapshotCreateInactiveExternal can
|
|
|
6ae9ed |
+ * use it without needing to deal with a volume.
|
|
|
6ae9ed |
+ */
|
|
|
6ae9ed |
struct _virStorageBackendQemuImgInfo {
|
|
|
6ae9ed |
int format;
|
|
|
6ae9ed |
const char *path;
|
|
|
6ae9ed |
@@ -941,21 +949,36 @@ struct _virStorageBackendQemuImgInfo {
|
|
|
6ae9ed |
const char *inputPath;
|
|
|
6ae9ed |
const char *inputFormatStr;
|
|
|
6ae9ed |
int inputFormat;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ char *secretAlias;
|
|
|
6ae9ed |
+ const char *secretPath;
|
|
|
6ae9ed |
};
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
static int
|
|
|
6ae9ed |
-virStorageBackendCreateQemuImgOpts(char **opts,
|
|
|
6ae9ed |
+virStorageBackendCreateQemuImgOpts(virStorageEncryptionInfoDefPtr enc,
|
|
|
6ae9ed |
+ char **opts,
|
|
|
6ae9ed |
struct _virStorageBackendQemuImgInfo info)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- if (info.backingPath)
|
|
|
6ae9ed |
- virBufferAsprintf(&buf, "backing_fmt=%s,",
|
|
|
6ae9ed |
- virStorageFileFormatTypeToString(info.backingFormat));
|
|
|
6ae9ed |
- if (info.encryption)
|
|
|
6ae9ed |
- virBufferAddLit(&buf, "encryption=on,");
|
|
|
6ae9ed |
- if (info.preallocate)
|
|
|
6ae9ed |
- virBufferAddLit(&buf, "preallocation=metadata,");
|
|
|
6ae9ed |
+ if (info.format == VIR_STORAGE_FILE_LUKS) {
|
|
|
6ae9ed |
+ if (!enc) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("missing luks encryption information"));
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ virQEMUBuildLuksOpts(&buf, enc, info.secretAlias);
|
|
|
6ae9ed |
+ } else {
|
|
|
6ae9ed |
+ if (info.backingPath)
|
|
|
6ae9ed |
+ virBufferAsprintf(&buf, "backing_fmt=%s,",
|
|
|
6ae9ed |
+ virStorageFileFormatTypeToString(info.backingFormat));
|
|
|
6ae9ed |
+ if (info.encryption)
|
|
|
6ae9ed |
+ virBufferAddLit(&buf, "encryption=on,");
|
|
|
6ae9ed |
+ if (info.preallocate)
|
|
|
6ae9ed |
+ virBufferAddLit(&buf, "preallocation=metadata,");
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
if (info.nocow)
|
|
|
6ae9ed |
virBufferAddLit(&buf, "nocow=on,");
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -1025,6 +1048,22 @@ virStorageBackendCreateQemuImgCheckEncryption(int format,
|
|
|
6ae9ed |
if (virStorageGenerateQcowEncryption(conn, vol) < 0)
|
|
|
6ae9ed |
return -1;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
+ } else if (format == VIR_STORAGE_FILE_LUKS) {
|
|
|
6ae9ed |
+ if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
6ae9ed |
+ _("unsupported volume encryption format %d"),
|
|
|
6ae9ed |
+ vol->target.encryption->format);
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (enc->nsecrets > 1) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
6ae9ed |
+ _("too many secrets for luks encryption"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (enc->nsecrets == 0) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
6ae9ed |
+ _("no secret provided for luks encryption"));
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
} else {
|
|
|
6ae9ed |
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
6ae9ed |
_("volume encryption unsupported with format %s"), type);
|
|
|
6ae9ed |
@@ -1069,6 +1108,12 @@ virStorageBackendCreateQemuImgSetBacking(virStoragePoolObjPtr pool,
|
|
|
6ae9ed |
int accessRetCode = -1;
|
|
|
6ae9ed |
char *absolutePath = NULL;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (info->format == VIR_STORAGE_FILE_LUKS) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("cannot set backing store for luks volume"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
info->backingFormat = vol->target.backingStore->format;
|
|
|
6ae9ed |
info->backingPath = vol->target.backingStore->path;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -1122,6 +1167,7 @@ virStorageBackendCreateQemuImgSetBacking(virStoragePoolObjPtr pool,
|
|
|
6ae9ed |
static int
|
|
|
6ae9ed |
virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
|
|
|
6ae9ed |
int imgformat,
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr enc,
|
|
|
6ae9ed |
struct _virStorageBackendQemuImgInfo info)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
char *opts = NULL;
|
|
|
6ae9ed |
@@ -1130,7 +1176,7 @@ virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
|
|
|
6ae9ed |
imgformat >= QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT)
|
|
|
6ae9ed |
info.compat = "0.10";
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- if (virStorageBackendCreateQemuImgOpts(&opts, info) < 0)
|
|
|
6ae9ed |
+ if (virStorageBackendCreateQemuImgOpts(enc, &opts, info) < 0)
|
|
|
6ae9ed |
return -1;
|
|
|
6ae9ed |
if (opts)
|
|
|
6ae9ed |
virCommandAddArgList(cmd, "-o", opts, NULL);
|
|
|
6ae9ed |
@@ -1140,6 +1186,39 @@ virStorageBackendCreateQemuImgSetOptions(virCommandPtr cmd,
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+/* Add a secret object to the command line:
|
|
|
6ae9ed |
+ * --object secret,id=$secretAlias,file=$secretPath
|
|
|
6ae9ed |
+ *
|
|
|
6ae9ed |
+ * NB: format=raw is assumed
|
|
|
6ae9ed |
+ */
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+virStorageBackendCreateQemuImgSecretObject(virCommandPtr cmd,
|
|
|
6ae9ed |
+ virStorageVolDefPtr vol,
|
|
|
6ae9ed |
+ struct _virStorageBackendQemuImgInfo *info)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
6ae9ed |
+ char *commandStr = NULL;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (virAsprintf(&info->secretAlias, "%s_luks0", vol->name) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virBufferAsprintf(&buf, "secret,id=%s,file=", info->secretAlias);
|
|
|
6ae9ed |
+ virQEMUBuildBufferEscapeComma(&buf, info->secretPath);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (virBufferCheckError(&buf) < 0) {
|
|
|
6ae9ed |
+ virBufferFreeAndReset(&buf;;
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ commandStr = virBufferContentAndReset(&buf;;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virCommandAddArgList(cmd, "--object", commandStr, NULL);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ VIR_FREE(commandStr);
|
|
|
6ae9ed |
+ return 0;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
/* Create a qemu-img virCommand from the supplied binary path,
|
|
|
6ae9ed |
* volume definitions and imgformat
|
|
|
6ae9ed |
*/
|
|
|
6ae9ed |
@@ -1150,7 +1229,8 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
6ae9ed |
virStorageVolDefPtr inputvol,
|
|
|
6ae9ed |
unsigned int flags,
|
|
|
6ae9ed |
const char *create_tool,
|
|
|
6ae9ed |
- int imgformat)
|
|
|
6ae9ed |
+ int imgformat,
|
|
|
6ae9ed |
+ const char *secretPath)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
virCommandPtr cmd = NULL;
|
|
|
6ae9ed |
const char *type;
|
|
|
6ae9ed |
@@ -1162,7 +1242,10 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
6ae9ed |
.compat = vol->target.compat,
|
|
|
6ae9ed |
.features = vol->target.features,
|
|
|
6ae9ed |
.nocow = vol->target.nocow,
|
|
|
6ae9ed |
+ .secretPath = secretPath,
|
|
|
6ae9ed |
+ .secretAlias = NULL,
|
|
|
6ae9ed |
};
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr enc = NULL;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -1192,6 +1275,18 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
6ae9ed |
_("format features only available with qcow2"));
|
|
|
6ae9ed |
return NULL;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
+ if (info.format == VIR_STORAGE_FILE_LUKS) {
|
|
|
6ae9ed |
+ if (inputvol) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("cannot use inputvol with luks volume"));
|
|
|
6ae9ed |
+ return NULL;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (!info.encryption) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("missing encryption description"));
|
|
|
6ae9ed |
+ return NULL;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
|
|
|
6ae9ed |
if (inputvol &&
|
|
|
6ae9ed |
virStorageBackendCreateQemuImgSetInput(inputvol, &info) < 0)
|
|
|
6ae9ed |
@@ -1226,10 +1321,22 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
6ae9ed |
if (info.backingPath)
|
|
|
6ae9ed |
virCommandAddArgList(cmd, "-b", info.backingPath, NULL);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- if (virStorageBackendCreateQemuImgSetOptions(cmd, imgformat, info) < 0) {
|
|
|
6ae9ed |
+ if (info.format == VIR_STORAGE_FILE_LUKS) {
|
|
|
6ae9ed |
+ if (virStorageBackendCreateQemuImgSecretObject(cmd, vol, &info) < 0) {
|
|
|
6ae9ed |
+ VIR_FREE(info.secretAlias);
|
|
|
6ae9ed |
+ virCommandFree(cmd);
|
|
|
6ae9ed |
+ return NULL;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ enc = &vol->target.encryption->encinfo;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (virStorageBackendCreateQemuImgSetOptions(cmd, imgformat,
|
|
|
6ae9ed |
+ enc, info) < 0) {
|
|
|
6ae9ed |
+ VIR_FREE(info.secretAlias);
|
|
|
6ae9ed |
virCommandFree(cmd);
|
|
|
6ae9ed |
return NULL;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
+ VIR_FREE(info.secretAlias);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
if (info.inputPath)
|
|
|
6ae9ed |
virCommandAddArg(cmd, info.inputPath);
|
|
|
6ae9ed |
@@ -1240,6 +1347,77 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
6ae9ed |
return cmd;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static char *
|
|
|
6ae9ed |
+virStorageBackendCreateQemuImgSecretPath(virConnectPtr conn,
|
|
|
6ae9ed |
+ virStoragePoolObjPtr pool,
|
|
|
6ae9ed |
+ virStorageVolDefPtr vol)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virStorageEncryptionPtr enc = vol->target.encryption;
|
|
|
6ae9ed |
+ char *secretPath = NULL;
|
|
|
6ae9ed |
+ int fd = -1;
|
|
|
6ae9ed |
+ uint8_t *secret = NULL;
|
|
|
6ae9ed |
+ size_t secretlen = 0;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!enc) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("missing encryption description"));
|
|
|
6ae9ed |
+ return NULL;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!conn || !conn->secretDriver ||
|
|
|
6ae9ed |
+ !conn->secretDriver->secretLookupByUUID ||
|
|
|
6ae9ed |
+ !conn->secretDriver->secretLookupByUsage ||
|
|
|
6ae9ed |
+ !conn->secretDriver->secretGetValue) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("unable to look up encryption secret"));
|
|
|
6ae9ed |
+ return NULL;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(secretPath = virStoragePoolObjBuildTempFilePath(pool, vol)))
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((fd = mkostemp(secretPath, O_CLOEXEC)) < 0) {
|
|
|
6ae9ed |
+ virReportSystemError(errno, "%s",
|
|
|
6ae9ed |
+ _("failed to open luks secret file for write"));
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (virSecretGetSecretString(conn, &enc->secrets[0]->seclookupdef,
|
|
|
6ae9ed |
+ VIR_SECRET_USAGE_TYPE_VOLUME,
|
|
|
6ae9ed |
+ &secret, &secretlen) < 0)
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (safewrite(fd, secret, secretlen) < 0) {
|
|
|
6ae9ed |
+ virReportSystemError(errno, "%s",
|
|
|
6ae9ed |
+ _("failed to write luks secret file"));
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ VIR_FORCE_CLOSE(fd);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((vol->target.perms->uid != (uid_t) -1) &&
|
|
|
6ae9ed |
+ (vol->target.perms->gid != (gid_t) -1)) {
|
|
|
6ae9ed |
+ if (chown(secretPath, vol->target.perms->uid,
|
|
|
6ae9ed |
+ vol->target.perms->gid) < 0) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("failed to chown luks secret file"));
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ cleanup:
|
|
|
6ae9ed |
+ VIR_DISPOSE_N(secret, secretlen);
|
|
|
6ae9ed |
+ VIR_FORCE_CLOSE(fd);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return secretPath;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ error:
|
|
|
6ae9ed |
+ unlink(secretPath);
|
|
|
6ae9ed |
+ VIR_FREE(secretPath);
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
int
|
|
|
6ae9ed |
virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|
|
6ae9ed |
virStoragePoolObjPtr pool,
|
|
|
6ae9ed |
@@ -1251,6 +1429,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|
|
6ae9ed |
char *create_tool;
|
|
|
6ae9ed |
int imgformat;
|
|
|
6ae9ed |
virCommandPtr cmd;
|
|
|
6ae9ed |
+ char *secretPath = NULL;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -1266,8 +1445,15 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|
|
6ae9ed |
if (imgformat < 0)
|
|
|
6ae9ed |
goto cleanup;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (vol->target.format == VIR_STORAGE_FILE_LUKS) {
|
|
|
6ae9ed |
+ if (!(secretPath =
|
|
|
6ae9ed |
+ virStorageBackendCreateQemuImgSecretPath(conn, pool, vol)))
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
cmd = virStorageBackendCreateQemuImgCmdFromVol(conn, pool, vol, inputvol,
|
|
|
6ae9ed |
- flags, create_tool, imgformat);
|
|
|
6ae9ed |
+ flags, create_tool,
|
|
|
6ae9ed |
+ imgformat, secretPath);
|
|
|
6ae9ed |
if (!cmd)
|
|
|
6ae9ed |
goto cleanup;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -1275,6 +1461,10 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|
|
6ae9ed |
|
|
|
6ae9ed |
virCommandFree(cmd);
|
|
|
6ae9ed |
cleanup:
|
|
|
6ae9ed |
+ if (secretPath) {
|
|
|
6ae9ed |
+ unlink(secretPath);
|
|
|
6ae9ed |
+ VIR_FREE(secretPath);
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
VIR_FREE(create_tool);
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
|
|
|
6ae9ed |
index 5bc622c..28e1a65 100644
|
|
|
6ae9ed |
--- a/src/storage/storage_backend.h
|
|
|
6ae9ed |
+++ b/src/storage/storage_backend.h
|
|
|
6ae9ed |
@@ -241,7 +241,8 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
6ae9ed |
virStorageVolDefPtr inputvol,
|
|
|
6ae9ed |
unsigned int flags,
|
|
|
6ae9ed |
const char *create_tool,
|
|
|
6ae9ed |
- int imgformat);
|
|
|
6ae9ed |
+ int imgformat,
|
|
|
6ae9ed |
+ const char *secretPath);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
/* ------- virStorageFile backends ------------ */
|
|
|
6ae9ed |
typedef struct _virStorageFileBackend virStorageFileBackend;
|
|
|
6ae9ed |
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
|
|
|
6ae9ed |
index 79a4292..7d181e1 100644
|
|
|
6ae9ed |
--- a/src/util/virqemu.c
|
|
|
6ae9ed |
+++ b/src/util/virqemu.c
|
|
|
6ae9ed |
@@ -155,3 +155,61 @@ virQEMUBuildBufferEscapeComma(virBufferPtr buf, const char *str)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
virBufferEscape(buf, ',', ",", "%s", str);
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+/**
|
|
|
6ae9ed |
+ * virQEMUBuildLuksOpts:
|
|
|
6ae9ed |
+ * @buf: buffer to build the string into
|
|
|
6ae9ed |
+ * @enc: pointer to encryption info
|
|
|
6ae9ed |
+ * @alias: alias to use
|
|
|
6ae9ed |
+ *
|
|
|
6ae9ed |
+ * Generate the string for id=$alias and any encryption options for
|
|
|
6ae9ed |
+ * into the buffer.
|
|
|
6ae9ed |
+ *
|
|
|
6ae9ed |
+ * Important note, a trailing comma (",") is built into the return since
|
|
|
6ae9ed |
+ * it's expected other arguments are appended after the id=$alias string.
|
|
|
6ae9ed |
+ * So either turn something like:
|
|
|
6ae9ed |
+ *
|
|
|
6ae9ed |
+ * "key-secret=$alias,"
|
|
|
6ae9ed |
+ *
|
|
|
6ae9ed |
+ * or
|
|
|
6ae9ed |
+ * "key-secret=$alias,cipher-alg=twofish-256,cipher-mode=cbc,
|
|
|
6ae9ed |
+ * hash-alg=sha256,ivgen-alg=plain64,igven-hash-alg=sha256,"
|
|
|
6ae9ed |
+ *
|
|
|
6ae9ed |
+ */
|
|
|
6ae9ed |
+void
|
|
|
6ae9ed |
+virQEMUBuildLuksOpts(virBufferPtr buf,
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr enc,
|
|
|
6ae9ed |
+ const char *alias)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virBufferAsprintf(buf, "key-secret=%s,", alias);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!enc->cipher_name)
|
|
|
6ae9ed |
+ return;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "cipher-alg=");
|
|
|
6ae9ed |
+ virQEMUBuildBufferEscapeComma(buf, enc->cipher_name);
|
|
|
6ae9ed |
+ virBufferAsprintf(buf, "-%u,", enc->cipher_size);
|
|
|
6ae9ed |
+ if (enc->cipher_mode) {
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "cipher-mode=");
|
|
|
6ae9ed |
+ virQEMUBuildBufferEscapeComma(buf, enc->cipher_mode);
|
|
|
6ae9ed |
+ virBufferAddLit(buf, ",");
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (enc->cipher_hash) {
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "hash-alg=");
|
|
|
6ae9ed |
+ virQEMUBuildBufferEscapeComma(buf, enc->cipher_hash);
|
|
|
6ae9ed |
+ virBufferAddLit(buf, ",");
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (!enc->ivgen_name)
|
|
|
6ae9ed |
+ return;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "ivgen-alg=");
|
|
|
6ae9ed |
+ virQEMUBuildBufferEscapeComma(buf, enc->ivgen_name);
|
|
|
6ae9ed |
+ virBufferAddLit(buf, ",");
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (enc->ivgen_hash) {
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "ivgen-hash-alg=");
|
|
|
6ae9ed |
+ virQEMUBuildBufferEscapeComma(buf, enc->ivgen_hash);
|
|
|
6ae9ed |
+ virBufferAddLit(buf, ",");
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
|
|
|
6ae9ed |
index 1033412..eb75d1b 100644
|
|
|
6ae9ed |
--- a/src/util/virqemu.h
|
|
|
6ae9ed |
+++ b/src/util/virqemu.h
|
|
|
6ae9ed |
@@ -27,10 +27,16 @@
|
|
|
6ae9ed |
# include "internal.h"
|
|
|
6ae9ed |
# include "virbuffer.h"
|
|
|
6ae9ed |
# include "virjson.h"
|
|
|
6ae9ed |
+# include "virstorageencryption.h"
|
|
|
6ae9ed |
|
|
|
6ae9ed |
char *virQEMUBuildObjectCommandlineFromJSON(const char *type,
|
|
|
6ae9ed |
const char *alias,
|
|
|
6ae9ed |
virJSONValuePtr props);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
void virQEMUBuildBufferEscapeComma(virBufferPtr buf, const char *str);
|
|
|
6ae9ed |
+void virQEMUBuildLuksOpts(virBufferPtr buf,
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr enc,
|
|
|
6ae9ed |
+ const char *alias)
|
|
|
6ae9ed |
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
#endif /* __VIR_QEMU_H_ */
|
|
|
6ae9ed |
diff --git a/tests/storagevolxml2argvtest.c b/tests/storagevolxml2argvtest.c
|
|
|
6ae9ed |
index ccfe9ab..e300821 100644
|
|
|
6ae9ed |
--- a/tests/storagevolxml2argvtest.c
|
|
|
6ae9ed |
+++ b/tests/storagevolxml2argvtest.c
|
|
|
6ae9ed |
@@ -83,7 +83,8 @@ testCompareXMLToArgvFiles(bool shouldFail,
|
|
|
6ae9ed |
|
|
|
6ae9ed |
cmd = virStorageBackendCreateQemuImgCmdFromVol(conn, &poolobj, vol,
|
|
|
6ae9ed |
inputvol, flags,
|
|
|
6ae9ed |
- create_tool, imgformat);
|
|
|
6ae9ed |
+ create_tool, imgformat,
|
|
|
6ae9ed |
+ NULL);
|
|
|
6ae9ed |
if (!cmd) {
|
|
|
6ae9ed |
if (shouldFail) {
|
|
|
6ae9ed |
virResetLastError();
|
|
|
6ae9ed |
--
|
|
|
6ae9ed |
2.9.2
|
|
|
6ae9ed |
|