mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-07 06:45:45 +00:00
5e46d7d6b6
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@redhat.com>
216 lines
6.3 KiB
C
216 lines
6.3 KiB
C
/*
|
|
* virqemu.c: utilities for working with qemu and its tools
|
|
*
|
|
* Copyright (C) 2016 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include "virbuffer.h"
|
|
#include "virerror.h"
|
|
#include "virlog.h"
|
|
#include "virqemu.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
VIR_LOG_INIT("util.qemu");
|
|
|
|
|
|
static int
|
|
virQEMUBuildObjectCommandLinePropsInternal(const char *key,
|
|
const virJSONValue *value,
|
|
virBufferPtr buf,
|
|
bool nested)
|
|
{
|
|
virJSONValuePtr elem;
|
|
virBitmapPtr bitmap = NULL;
|
|
ssize_t pos = -1;
|
|
ssize_t end;
|
|
size_t i;
|
|
|
|
switch ((virJSONType) value->type) {
|
|
case VIR_JSON_TYPE_STRING:
|
|
virBufferAsprintf(buf, ",%s=%s", key, value->data.string);
|
|
break;
|
|
|
|
case VIR_JSON_TYPE_NUMBER:
|
|
virBufferAsprintf(buf, ",%s=%s", key, value->data.number);
|
|
break;
|
|
|
|
case VIR_JSON_TYPE_BOOLEAN:
|
|
if (value->data.boolean)
|
|
virBufferAsprintf(buf, ",%s=yes", key);
|
|
else
|
|
virBufferAsprintf(buf, ",%s=no", key);
|
|
|
|
break;
|
|
|
|
case VIR_JSON_TYPE_ARRAY:
|
|
if (nested) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
_("nested -object property arrays are not supported"));
|
|
return -1;
|
|
}
|
|
|
|
if (virJSONValueGetArrayAsBitmap(value, &bitmap) == 0) {
|
|
while ((pos = virBitmapNextSetBit(bitmap, pos)) > -1) {
|
|
if ((end = virBitmapNextClearBit(bitmap, pos)) < 0)
|
|
end = virBitmapLastSetBit(bitmap) + 1;
|
|
|
|
if (end - 1 > pos) {
|
|
virBufferAsprintf(buf, ",%s=%zd-%zd", key, pos, end - 1);
|
|
pos = end;
|
|
} else {
|
|
virBufferAsprintf(buf, ",%s=%zd", key, pos);
|
|
}
|
|
}
|
|
} else {
|
|
/* fallback, treat the array as a non-bitmap, adding the key
|
|
* for each member */
|
|
for (i = 0; i < virJSONValueArraySize(value); i++) {
|
|
elem = virJSONValueArrayGet((virJSONValuePtr)value, i);
|
|
|
|
/* recurse to avoid duplicating code */
|
|
if (virQEMUBuildObjectCommandLinePropsInternal(key, elem, buf,
|
|
true) < 0)
|
|
return -1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VIR_JSON_TYPE_OBJECT:
|
|
case VIR_JSON_TYPE_NULL:
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
_("NULL and OBJECT JSON types can't be converted to "
|
|
"commandline string"));
|
|
return -1;
|
|
}
|
|
|
|
virBitmapFree(bitmap);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
virQEMUBuildObjectCommandLineProps(const char *key,
|
|
const virJSONValue *value,
|
|
void *opaque)
|
|
{
|
|
return virQEMUBuildObjectCommandLinePropsInternal(key, value, opaque, false);
|
|
}
|
|
|
|
|
|
char *
|
|
virQEMUBuildObjectCommandlineFromJSON(const char *type,
|
|
const char *alias,
|
|
virJSONValuePtr props)
|
|
{
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
char *ret = NULL;
|
|
|
|
virBufferAsprintf(&buf, "%s,id=%s", type, alias);
|
|
|
|
if (virJSONValueObjectForeachKeyValue(props,
|
|
virQEMUBuildObjectCommandLineProps,
|
|
&buf) < 0)
|
|
goto cleanup;
|
|
|
|
if (virBufferCheckError(&buf) < 0)
|
|
goto cleanup;
|
|
|
|
ret = virBufferContentAndReset(&buf);
|
|
|
|
cleanup:
|
|
virBufferFreeAndReset(&buf);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* virQEMUBuildBufferEscapeComma:
|
|
* @buf: buffer to append the escaped string
|
|
* @str: the string to escape
|
|
*
|
|
* qemu requires that any values passed on the command line which contain
|
|
* a ',' must escape it using an extra ',' as the escape character
|
|
*/
|
|
void
|
|
virQEMUBuildBufferEscapeComma(virBufferPtr buf, const char *str)
|
|
{
|
|
virBufferEscape(buf, ',', ",", "%s", str);
|
|
}
|
|
|
|
|
|
/**
|
|
* virQEMUBuildLuksOpts:
|
|
* @buf: buffer to build the string into
|
|
* @enc: pointer to encryption info
|
|
* @alias: alias to use
|
|
*
|
|
* Generate the string for id=$alias and any encryption options for
|
|
* into the buffer.
|
|
*
|
|
* Important note, a trailing comma (",") is built into the return since
|
|
* it's expected other arguments are appended after the id=$alias string.
|
|
* So either turn something like:
|
|
*
|
|
* "key-secret=$alias,"
|
|
*
|
|
* or
|
|
* "key-secret=$alias,cipher-alg=twofish-256,cipher-mode=cbc,
|
|
* hash-alg=sha256,ivgen-alg=plain64,igven-hash-alg=sha256,"
|
|
*
|
|
*/
|
|
void
|
|
virQEMUBuildLuksOpts(virBufferPtr buf,
|
|
virStorageEncryptionInfoDefPtr enc,
|
|
const char *alias)
|
|
{
|
|
virBufferAsprintf(buf, "key-secret=%s,", alias);
|
|
|
|
if (!enc->cipher_name)
|
|
return;
|
|
|
|
virBufferAddLit(buf, "cipher-alg=");
|
|
virQEMUBuildBufferEscapeComma(buf, enc->cipher_name);
|
|
virBufferAsprintf(buf, "-%u,", enc->cipher_size);
|
|
if (enc->cipher_mode) {
|
|
virBufferAddLit(buf, "cipher-mode=");
|
|
virQEMUBuildBufferEscapeComma(buf, enc->cipher_mode);
|
|
virBufferAddLit(buf, ",");
|
|
}
|
|
if (enc->cipher_hash) {
|
|
virBufferAddLit(buf, "hash-alg=");
|
|
virQEMUBuildBufferEscapeComma(buf, enc->cipher_hash);
|
|
virBufferAddLit(buf, ",");
|
|
}
|
|
if (!enc->ivgen_name)
|
|
return;
|
|
|
|
virBufferAddLit(buf, "ivgen-alg=");
|
|
virQEMUBuildBufferEscapeComma(buf, enc->ivgen_name);
|
|
virBufferAddLit(buf, ",");
|
|
|
|
if (enc->ivgen_hash) {
|
|
virBufferAddLit(buf, "ivgen-hash-alg=");
|
|
virQEMUBuildBufferEscapeComma(buf, enc->ivgen_hash);
|
|
virBufferAddLit(buf, ",");
|
|
}
|
|
}
|