When integrating the crypto support with qcow/qcow2, we don't
want to use the bare LUKS option names "hash-alg", "key-secret",
etc. We want to namespace them "luks-hash-alg", "luks-key-secret"
so that they don't clash with any general qcow options at a later
date.
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
block/crypto.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++--------
block/crypto.h | 42 +++++++++++-----------
2 files changed, 119 insertions(+), 34 deletions(-)
diff --git a/block/crypto.c b/block/crypto.c
index d281de6..876eabc 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -27,6 +27,7 @@
#include "qapi-visit.h"
#include "qapi/error.h"
#include "block/crypto.h"
+#include "qemu/cutils.h"
typedef struct BlockCrypto BlockCrypto;
@@ -128,7 +129,7 @@ static QemuOptsList block_crypto_runtime_opts_luks = {
.name = "crypto",
.head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
.desc = {
- BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET,
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
{ /* end of list */ }
},
};
@@ -143,31 +144,101 @@ static QemuOptsList block_crypto_create_opts_luks = {
.type = QEMU_OPT_SIZE,
.help = "Virtual disk size"
},
- BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET,
- BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG,
- BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE,
- BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG,
- BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG,
- BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG,
- BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME,
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
{ /* end of list */ }
},
};
+static QemuOptsList empty_opts = {
+ .name = "crypto-empty",
+ .merge_lists = false,
+ .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head),
+ .desc = {
+ /* no elements => accept any params */
+ { /* end of list */ }
+ },
+};
+
+
+struct BlockCryptoCopyData {
+ QemuOpts *opts;
+ const char *prefix;
+};
+
+static int block_crypto_copy_value(void *opaque, const char *name,
+ const char *value, Error **errp)
+{
+ struct BlockCryptoCopyData *data = opaque;
+ const char *newname;
+
+ if (strstart(name, data->prefix, &newname)) {
+ Error *local_err = NULL;
+
+ qemu_opt_set(data->opts, newname, value, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Create a copy of @opts containing only the fields with
+ * a prefix of @prefix, stripping the prefix in the returned
+ * opts
+ */
+static QemuOpts *
+block_crypto_copy_opts(QemuOpts *opts,
+ const char *prefix,
+ Error **errp)
+{
+ struct BlockCryptoCopyData data = {
+ .opts = qemu_opts_create(&empty_opts, NULL, false, errp),
+ .prefix = prefix
+ };
+ if (!data.opts) {
+ return NULL;
+ }
+
+ if (qemu_opt_foreach(opts, block_crypto_copy_value, &data, errp) < 0) {
+ qemu_opts_del(data.opts);
+ return NULL;
+ }
+
+ return data.opts;
+}
QCryptoBlockOpenOptions *
block_crypto_open_opts_init(QCryptoBlockFormat format,
QemuOpts *opts,
+ const char *prefix,
Error **errp)
{
- Visitor *v;
+ Visitor *v = NULL;
QCryptoBlockOpenOptions *ret = NULL;
Error *local_err = NULL;
+ QemuOpts *newopts = NULL;
ret = g_new0(QCryptoBlockOpenOptions, 1);
ret->format = format;
- v = opts_visitor_new(opts);
+ if (prefix != NULL) {
+ newopts = block_crypto_copy_opts(opts, prefix, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ v = opts_visitor_new(newopts);
+ } else {
+ v = opts_visitor_new(opts);
+ }
visit_start_struct(v, NULL, NULL, 0, &local_err);
if (local_err) {
@@ -196,6 +267,7 @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
qapi_free_QCryptoBlockOpenOptions(ret);
ret = NULL;
}
+ qemu_opts_del(newopts);
visit_free(v);
return ret;
}
@@ -204,16 +276,26 @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
QCryptoBlockCreateOptions *
block_crypto_create_opts_init(QCryptoBlockFormat format,
QemuOpts *opts,
+ const char *prefix,
Error **errp)
{
- Visitor *v;
+ Visitor *v = NULL;
QCryptoBlockCreateOptions *ret = NULL;
Error *local_err = NULL;
+ QemuOpts *newopts = NULL;
ret = g_new0(QCryptoBlockCreateOptions, 1);
ret->format = format;
- v = opts_visitor_new(opts);
+ if (prefix != NULL) {
+ newopts = block_crypto_copy_opts(opts, prefix, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ v = opts_visitor_new(newopts);
+ } else {
+ v = opts_visitor_new(opts);
+ }
visit_start_struct(v, NULL, NULL, 0, &local_err);
if (local_err) {
@@ -242,6 +324,7 @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
qapi_free_QCryptoBlockCreateOptions(ret);
ret = NULL;
}
+ qemu_opts_del(newopts);
visit_free(v);
return ret;
}
@@ -268,7 +351,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
goto cleanup;
}
- open_opts = block_crypto_open_opts_init(format, opts, errp);
+ open_opts = block_crypto_open_opts_init(format, opts, NULL, errp);
if (!open_opts) {
goto cleanup;
}
@@ -312,7 +395,7 @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
.filename = filename,
};
- create_opts = block_crypto_create_opts_init(format, opts, errp);
+ create_opts = block_crypto_create_opts_init(format, opts, NULL, errp);
if (!create_opts) {
return -1;
}
diff --git a/block/crypto.h b/block/crypto.h
index e42f20e..e70e2f0 100644
--- a/block/crypto.h
+++ b/block/crypto.h
@@ -29,51 +29,51 @@
#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \
{ \
- .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, \
.type = QEMU_OPT_STRING, \
.help = "ID of the secret that provides the keyslot passphrase", \
}
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(prefix) \
{ \
- .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, \
.type = QEMU_OPT_STRING, \
.help = "Name of encryption cipher algorithm", \
}
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE \
- { \
- .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, \
- .type = QEMU_OPT_STRING, \
- .help = "Name of encryption cipher mode", \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(prefix) \
+ { \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Name of encryption cipher mode", \
}
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG \
- { \
- .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, \
- .type = QEMU_OPT_STRING, \
- .help = "Name of IV generator algorithm", \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(prefix) \
+ { \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Name of IV generator algorithm", \
}
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(prefix) \
{ \
- .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, \
.type = QEMU_OPT_STRING, \
.help = "Name of IV generator hash algorithm", \
}
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(prefix) \
{ \
- .name = BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, \
.type = QEMU_OPT_STRING, \
.help = "Name of encryption hash algorithm", \
}
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME \
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(prefix) \
{ \
- .name = BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, \
.type = QEMU_OPT_NUMBER, \
.help = "Time to spend in PBKDF in milliseconds", \
}
@@ -81,11 +81,13 @@
QCryptoBlockCreateOptions *
block_crypto_create_opts_init(QCryptoBlockFormat format,
QemuOpts *opts,
+ const char *prefix,
Error **errp);
QCryptoBlockOpenOptions *
block_crypto_open_opts_init(QCryptoBlockFormat format,
QemuOpts *opts,
+ const char *prefix,
Error **errp);
#endif /* BLOCK_CRYPTO_H__ */
--
2.9.3
Am 21.02.2017 um 12:54 hat Daniel P. Berrange geschrieben: > When integrating the crypto support with qcow/qcow2, we don't > want to use the bare LUKS option names "hash-alg", "key-secret", > etc. We want to namespace them "luks-hash-alg", "luks-key-secret" > so that they don't clash with any general qcow options at a later > date. Or maybe "luks.key-secret", i.e. actually embed the LUKS options QAPI type into the qcow2 one? In that case, maybe qdict_extract_subqdict() can even be used before calling into this, so that we don't have to write a QemuOpts version of the function. However, the only option I can see at the end of this series in BlockdevOptionsQcow2 is luks-key-secret, so what happened with this plan? And if we really have only luks-key-secret (and that not in a separate sub-dict), I don't really see the need to have separate aes-key-secret and luks-key-secret options. > Reviewed-by: Max Reitz <mreitz@redhat.com> > Reviewed-by: Alberto Garcia <berto@igalia.com> > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Having said all that, while I'm not sure if the goal of the patch is completely right, it does seem to correctly implement what it promises. Kevin
On Wed, Feb 22, 2017 at 04:18:33PM +0100, Kevin Wolf wrote: > Am 21.02.2017 um 12:54 hat Daniel P. Berrange geschrieben: > > When integrating the crypto support with qcow/qcow2, we don't > > want to use the bare LUKS option names "hash-alg", "key-secret", > > etc. We want to namespace them "luks-hash-alg", "luks-key-secret" > > so that they don't clash with any general qcow options at a later > > date. > > Or maybe "luks.key-secret", i.e. actually embed the LUKS options QAPI > type into the qcow2 one? In that case, maybe qdict_extract_subqdict() > can even be used before calling into this, so that we don't have to > write a QemuOpts version of the function. Yeah, the use of '-' vs '.' is a significant decision point from a QAPI modelling POV. Currently as you see from earlier patch, I just add 'luks-key-secret' straight into BlockdevOptionsQcow2. ie I duplicate fields from QCryptoBlockOptionsLUKS straight into BlockdevOptionsQcow2. Likewise for fields from QCryptoBlockOptionsQCow. If we used '.', we could potentially have BlockdevOptionsQcow2 directly reference the QCryptoBlockOptionsLUKS & QCryptoBlockOptionsQCow structs. As a point of reference though, we didn't do this for the standalone 'luks' block driver - BlockdevOptionsLUKS contains a copy of the fields from QCryptoBlockOptionsLUKS because it needs to add inheritance from BlockdevOptionsGenericFormat. Both approaches have pluses & minuses and I don't have a particularly strong opinion either way, so interested to hear what others thing. > However, the only option I can see at the end of this series in > BlockdevOptionsQcow2 is luks-key-secret, so what happened with this > plan? > > And if we really have only luks-key-secret (and that not in a separate > sub-dict), I don't really see the need to have separate aes-key-secret > and luks-key-secret options. Currently, all except the key-secret are create time options, not runtime and blockdev hasn't qapi'ified create time options. So the bits like luks-cipher-alg, luks-cipher-mode, etc don't appear in the QAPI schema, only the QemuOpts runtime_opts variable. That both the legacy AES & LUKS modes only have a single runtime option is just a co-incidence that is likely to be a temporary state of affairs. It is quite possible that we'll gain more runtime LUKS options in the future. For example, options to specify which precise keyslot to load, or to provide the name of a separate image containing a standalone luks header, etc. Hence, I wanted to have separation between the legacy AES & LUKS namespaces, to make it clear what applies to what scenario. > > Reviewed-by: Max Reitz <mreitz@redhat.com> > > Reviewed-by: Alberto Garcia <berto@igalia.com> > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > > Having said all that, while I'm not sure if the goal of the patch is > completely right, it does seem to correctly implement what it promises. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|
On 02/22/2017 09:49 AM, Daniel P. Berrange wrote:
> On Wed, Feb 22, 2017 at 04:18:33PM +0100, Kevin Wolf wrote:
>> Am 21.02.2017 um 12:54 hat Daniel P. Berrange geschrieben:
>>> When integrating the crypto support with qcow/qcow2, we don't
>>> want to use the bare LUKS option names "hash-alg", "key-secret",
>>> etc. We want to namespace them "luks-hash-alg", "luks-key-secret"
>>> so that they don't clash with any general qcow options at a later
>>> date.
>>
>> Or maybe "luks.key-secret", i.e. actually embed the LUKS options QAPI
>> type into the qcow2 one? In that case, maybe qdict_extract_subqdict()
>> can even be used before calling into this, so that we don't have to
>> write a QemuOpts version of the function.
>
> Yeah, the use of '-' vs '.' is a significant decision point from
> a QAPI modelling POV. Currently as you see from earlier patch, I just
> add 'luks-key-secret' straight into BlockdevOptionsQcow2. ie I duplicate
> fields from QCryptoBlockOptionsLUKS straight into BlockdevOptionsQcow2.
> Likewise for fields from QCryptoBlockOptionsQCow.
>
> If we used '.', we could potentially have BlockdevOptionsQcow2 directly
> reference the QCryptoBlockOptionsLUKS & QCryptoBlockOptionsQCow structs.
Using '.' would mean a layer of {} nesting on the wire, maybe as in:
{ "driver": "qcow2", ..., "luks" : { "hash-alg": ... } }
but conceptually, I like that a bit better, as it consolidates all the
luks-related options in one place, and may indeed make it possible to
reuse the type rather than having two variants (one prefixed, one not,
depending on whether it is standalone or qcow2).
I'm also looking later in your series (13/18), where you have:
@@ -2344,7 +2348,8 @@
'*l2-cache-size': 'int',
'*refcount-cache-size': 'int',
'*cache-clean-interval': 'int',
- '*aes-key-secret': 'str' } }
+ '*aes-key-secret': 'str',
+ '*luks-key-secret': 'str' } }
Uggh - we have two optional parameters, that must not both be present at
once. I'm wondering if we can instead do this (hmm, my patches for
anonymous base/branches in a flat union haven't been taken yet, but you
get the idea):
...
'*cache-clean-interval': 'int',
'*encryption': 'Qcow2Encryption' } }
{ 'enum': 'Qcow2EncryptionType': [ 'aes', 'luks' ] }
{ 'union': 'Qcow2Encryption', 'base': { 'type': 'Qcow2EncryptionType' },
'discriminator': 'type', 'data': {
'aes': { 'key-secret': 'str' },
'luks': { 'key-secret': 'str', '*hash-alg': ..., '*slot': 'int' } } }
so that you can only provide one encryption type, but once you have that
type, you can then provide all the associated fields for that type. So
the QMP would look like:
{ "driver": "qcow2", ..., "encryption" : { "type": "luks", "hash-alg":
... } }
>
> As a point of reference though, we didn't do this for the standalone
> 'luks' block driver - BlockdevOptionsLUKS contains a copy of the
> fields from QCryptoBlockOptionsLUKS because it needs to add
> inheritance from BlockdevOptionsGenericFormat.
>
> Both approaches have pluses & minuses and I don't have a particularly
> strong opinion either way, so interested to hear what others thing.
I think there are enough potentials for alternative designs, especially
where we can reuse code/structs without having to do prefixes, that it
is worth exploring some of those possibilities to see if they turn out
nicer.
>
>> However, the only option I can see at the end of this series in
>> BlockdevOptionsQcow2 is luks-key-secret, so what happened with this
>> plan?
>>
>> And if we really have only luks-key-secret (and that not in a separate
>> sub-dict), I don't really see the need to have separate aes-key-secret
>> and luks-key-secret options.
>
> Currently, all except the key-secret are create time options, not
> runtime and blockdev hasn't qapi'ified create time options. So the
> bits like luks-cipher-alg, luks-cipher-mode, etc don't appear in
> the QAPI schema, only the QemuOpts runtime_opts variable.
>
> That both the legacy AES & LUKS modes only have a single runtime
> option is just a co-incidence that is likely to be a temporary
> state of affairs. It is quite possible that we'll gain more runtime
> LUKS options in the future. For example, options to specify which
> precise keyslot to load, or to provide the name of a separate image
> containing a standalone luks header, etc.
See my idea above about sticking a '*slot':'int' into the schema at the
right place; made easier if the qcow2-level member 'encryption' is a
nested flat union.
>
> Hence, I wanted to have separation between the legacy AES & LUKS
> namespaces, to make it clear what applies to what scenario.
Again, I think the idea of a flat union, with the discriminator, makes
it easier to enforce mutual exclusion, rather than having two top-level
optional fields that cannot both be specified at once. Maybe we should
also consider making qapi flat unions support a default discriminator,
so that the "type":"luks" can be omitted, but that's sugar.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
Am 22.02.2017 um 19:28 hat Eric Blake geschrieben:
> Using '.' would mean a layer of {} nesting on the wire, maybe as in:
>
> { "driver": "qcow2", ..., "luks" : { "hash-alg": ... } }
>
> but conceptually, I like that a bit better, as it consolidates all the
> luks-related options in one place, and may indeed make it possible to
> reuse the type rather than having two variants (one prefixed, one not,
> depending on whether it is standalone or qcow2).
Right, and this extra nesting to keep everything luks related in one
place is exactly what I wanted to achieve with it.
> I'm also looking later in your series (13/18), where you have:
>
>
> @@ -2344,7 +2348,8 @@
> '*l2-cache-size': 'int',
> '*refcount-cache-size': 'int',
> '*cache-clean-interval': 'int',
> - '*aes-key-secret': 'str' } }
> + '*aes-key-secret': 'str',
> + '*luks-key-secret': 'str' } }
>
>
> Uggh - we have two optional parameters, that must not both be present at
> once. I'm wondering if we can instead do this (hmm, my patches for
> anonymous base/branches in a flat union haven't been taken yet, but you
> get the idea):
>
> ...
> '*cache-clean-interval': 'int',
> '*encryption': 'Qcow2Encryption' } }
>
> { 'enum': 'Qcow2EncryptionType': [ 'aes', 'luks' ] }
> { 'union': 'Qcow2Encryption', 'base': { 'type': 'Qcow2EncryptionType' },
> 'discriminator': 'type', 'data': {
> 'aes': { 'key-secret': 'str' },
> 'luks': { 'key-secret': 'str', '*hash-alg': ..., '*slot': 'int' } } }
>
> so that you can only provide one encryption type, but once you have that
> type, you can then provide all the associated fields for that type. So
> the QMP would look like:
>
> { "driver": "qcow2", ..., "encryption" : { "type": "luks", "hash-alg":
> ... } }
That's actually even better, a more accurate description of the options
on the QAPI level. I like it.
> > Hence, I wanted to have separation between the legacy AES & LUKS
> > namespaces, to make it clear what applies to what scenario.
>
> Again, I think the idea of a flat union, with the discriminator, makes
> it easier to enforce mutual exclusion, rather than having two top-level
> optional fields that cannot both be specified at once. Maybe we should
> also consider making qapi flat unions support a default discriminator,
> so that the "type":"luks" can be omitted, but that's sugar.
With the default discriminator, I'm not sure if that's still "sugar" or
already "too much magic".
Kevin
On Thu, Feb 23, 2017 at 11:28:39AM +0100, Kevin Wolf wrote:
> Am 22.02.2017 um 19:28 hat Eric Blake geschrieben:
> > Using '.' would mean a layer of {} nesting on the wire, maybe as in:
> >
> > { "driver": "qcow2", ..., "luks" : { "hash-alg": ... } }
> >
> > but conceptually, I like that a bit better, as it consolidates all the
> > luks-related options in one place, and may indeed make it possible to
> > reuse the type rather than having two variants (one prefixed, one not,
> > depending on whether it is standalone or qcow2).
>
> Right, and this extra nesting to keep everything luks related in one
> place is exactly what I wanted to achieve with it.
>
> > I'm also looking later in your series (13/18), where you have:
> >
> >
> > @@ -2344,7 +2348,8 @@
> > '*l2-cache-size': 'int',
> > '*refcount-cache-size': 'int',
> > '*cache-clean-interval': 'int',
> > - '*aes-key-secret': 'str' } }
> > + '*aes-key-secret': 'str',
> > + '*luks-key-secret': 'str' } }
> >
> >
> > Uggh - we have two optional parameters, that must not both be present at
> > once. I'm wondering if we can instead do this (hmm, my patches for
> > anonymous base/branches in a flat union haven't been taken yet, but you
> > get the idea):
> >
> > ...
> > '*cache-clean-interval': 'int',
> > '*encryption': 'Qcow2Encryption' } }
> >
> > { 'enum': 'Qcow2EncryptionType': [ 'aes', 'luks' ] }
> > { 'union': 'Qcow2Encryption', 'base': { 'type': 'Qcow2EncryptionType' },
> > 'discriminator': 'type', 'data': {
> > 'aes': { 'key-secret': 'str' },
> > 'luks': { 'key-secret': 'str', '*hash-alg': ..., '*slot': 'int' } } }
> >
> > so that you can only provide one encryption type, but once you have that
> > type, you can then provide all the associated fields for that type. So
> > the QMP would look like:
> >
> > { "driver": "qcow2", ..., "encryption" : { "type": "luks", "hash-alg":
> > ... } }
>
> That's actually even better, a more accurate description of the options
> on the QAPI level. I like it.
Ok, I'll try implementing this approach, though I won't have time to do
this before soft-freeze, so the qcow2/luks feature is definitely 2.10
material now.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|
© 2016 - 2026 Red Hat, Inc.