mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
libxl: add support for rbd qdisk
xl/libxl already supports qemu's network-based block backends such as nbd and rbd. libvirt has supported configuring such <disk>s for long time too. This patch adds support for rbd disks in the libxl driver by generating a rbd device URL from the virDomainDiskDef object. The URL is passed to libxl via the pdev_path field of libxl_device_disk struct. libxl then passes the URL to qemu for cosumption by the rbd backend. Signed-off-by: Jim Fehlig <jfehlig@suse.com>
This commit is contained in:
parent
6604a3dd9f
commit
fb2bd208e5
@ -46,6 +46,7 @@
|
|||||||
#include "libxl_conf.h"
|
#include "libxl_conf.h"
|
||||||
#include "libxl_utils.h"
|
#include "libxl_utils.h"
|
||||||
#include "virstoragefile.h"
|
#include "virstoragefile.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
||||||
@ -920,17 +921,206 @@ libxlDomainGetEmulatorType(const virDomainDef *def)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
libxlGetSecretString(virConnectPtr conn,
|
||||||
|
const char *scheme,
|
||||||
|
bool encoded,
|
||||||
|
virStorageAuthDefPtr authdef,
|
||||||
|
virSecretUsageType secretUsageType)
|
||||||
|
{
|
||||||
|
size_t secret_size;
|
||||||
|
virSecretPtr sec = NULL;
|
||||||
|
char *secret = NULL;
|
||||||
|
char uuidStr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
|
||||||
|
/* look up secret */
|
||||||
|
switch (authdef->secretType) {
|
||||||
|
case VIR_STORAGE_SECRET_TYPE_UUID:
|
||||||
|
sec = virSecretLookupByUUID(conn, authdef->secret.uuid);
|
||||||
|
virUUIDFormat(authdef->secret.uuid, uuidStr);
|
||||||
|
break;
|
||||||
|
case VIR_STORAGE_SECRET_TYPE_USAGE:
|
||||||
|
sec = virSecretLookupByUsage(conn, secretUsageType,
|
||||||
|
authdef->secret.usage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sec) {
|
||||||
|
if (authdef->secretType == VIR_STORAGE_SECRET_TYPE_UUID) {
|
||||||
|
virReportError(VIR_ERR_NO_SECRET,
|
||||||
|
_("%s no secret matches uuid '%s'"),
|
||||||
|
scheme, uuidStr);
|
||||||
|
} else {
|
||||||
|
virReportError(VIR_ERR_NO_SECRET,
|
||||||
|
_("%s no secret matches usage value '%s'"),
|
||||||
|
scheme, authdef->secret.usage);
|
||||||
|
}
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
secret = (char *)conn->secretDriver->secretGetValue(sec, &secret_size, 0,
|
||||||
|
VIR_SECRET_GET_VALUE_INTERNAL_CALL);
|
||||||
|
if (!secret) {
|
||||||
|
if (authdef->secretType == VIR_STORAGE_SECRET_TYPE_UUID) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("could not get value of the secret for "
|
||||||
|
"username '%s' using uuid '%s'"),
|
||||||
|
authdef->username, uuidStr);
|
||||||
|
} else {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("could not get value of the secret for "
|
||||||
|
"username '%s' using usage value '%s'"),
|
||||||
|
authdef->username, authdef->secret.usage);
|
||||||
|
}
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoded) {
|
||||||
|
char *base64 = NULL;
|
||||||
|
|
||||||
|
base64_encode_alloc(secret, secret_size, &base64);
|
||||||
|
VIR_FREE(secret);
|
||||||
|
if (!base64) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
secret = base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnref(sec);
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
libxlMakeNetworkDiskSrcStr(virStorageSourcePtr src,
|
||||||
|
const char *username,
|
||||||
|
const char *secret)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
switch ((virStorageNetProtocol) src->protocol) {
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_FTPS:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_TFTP:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT,
|
||||||
|
_("Unsupported network block protocol '%s'"),
|
||||||
|
virStorageNetProtocolTypeToString(src->protocol));
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
if (strchr(src->path, ':')) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("':' not allowed in RBD source volume name '%s'"),
|
||||||
|
src->path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferStrcat(&buf, "rbd:", src->path, NULL);
|
||||||
|
|
||||||
|
if (username) {
|
||||||
|
virBufferEscape(&buf, '\\', ":", ":id=%s", username);
|
||||||
|
virBufferEscape(&buf, '\\', ":",
|
||||||
|
":key=%s:auth_supported=cephx\\;none",
|
||||||
|
secret);
|
||||||
|
} else {
|
||||||
|
virBufferAddLit(&buf, ":auth_supported=none");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->nhosts > 0) {
|
||||||
|
virBufferAddLit(&buf, ":mon_host=");
|
||||||
|
for (i = 0; i < src->nhosts; i++) {
|
||||||
|
if (i)
|
||||||
|
virBufferAddLit(&buf, "\\;");
|
||||||
|
|
||||||
|
/* assume host containing : is ipv6 */
|
||||||
|
if (strchr(src->hosts[i].name, ':'))
|
||||||
|
virBufferEscape(&buf, '\\', ":", "[%s]",
|
||||||
|
src->hosts[i].name);
|
||||||
|
else
|
||||||
|
virBufferAsprintf(&buf, "%s", src->hosts[i].name);
|
||||||
|
|
||||||
|
if (src->hosts[i].port)
|
||||||
|
virBufferAsprintf(&buf, "\\:%s", src->hosts[i].port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->configFile)
|
||||||
|
virBufferEscape(&buf, '\\', ":", ":conf=%s", src->configFile);
|
||||||
|
|
||||||
|
if (virBufferCheckError(&buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = virBufferContentAndReset(&buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virBufferFreeAndReset(&buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
libxlMakeNetworkDiskSrc(virStorageSourcePtr src, char **srcstr)
|
||||||
|
{
|
||||||
|
virConnectPtr conn = NULL;
|
||||||
|
char *secret = NULL;
|
||||||
|
char *username = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
*srcstr = NULL;
|
||||||
|
if (src->auth && src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
|
||||||
|
const char *protocol = virStorageNetProtocolTypeToString(src->protocol);
|
||||||
|
|
||||||
|
username = src->auth->username;
|
||||||
|
if (!(conn = virConnectOpen("xen:///system")))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(secret = libxlGetSecretString(conn,
|
||||||
|
protocol,
|
||||||
|
true,
|
||||||
|
src->auth,
|
||||||
|
VIR_SECRET_USAGE_TYPE_CEPH)))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(*srcstr = libxlMakeNetworkDiskSrcStr(src, username, secret)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(secret);
|
||||||
|
virObjectUnref(conn);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
|
libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
|
||||||
{
|
{
|
||||||
const char *driver;
|
const char *driver;
|
||||||
int format;
|
int format;
|
||||||
|
int actual_type = virStorageSourceGetActualType(l_disk->src);
|
||||||
|
|
||||||
libxl_device_disk_init(x_disk);
|
libxl_device_disk_init(x_disk);
|
||||||
|
|
||||||
if (VIR_STRDUP(x_disk->pdev_path, virDomainDiskGetSource(l_disk)) < 0)
|
if (actual_type == VIR_STORAGE_TYPE_NETWORK) {
|
||||||
|
if (libxlMakeNetworkDiskSrc(l_disk->src, &x_disk->pdev_path) < 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (VIR_STRDUP(x_disk->pdev_path, virDomainDiskGetSource(l_disk)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0)
|
if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user