mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 11:35:19 +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_utils.h"
|
||||
#include "virstoragefile.h"
|
||||
#include "base64.h"
|
||||
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
||||
@ -920,17 +921,206 @@ libxlDomainGetEmulatorType(const virDomainDef *def)
|
||||
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
|
||||
libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
|
||||
{
|
||||
const char *driver;
|
||||
int format;
|
||||
int actual_type = virStorageSourceGetActualType(l_disk->src);
|
||||
|
||||
libxl_device_disk_init(x_disk);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0)
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user