From c33c36d28f8551937ed218cc0ee7b51b0d605072 Mon Sep 17 00:00:00 2001 From: Harsh Prateek Bora Date: Thu, 22 Nov 2012 23:40:39 +0530 Subject: [PATCH] qemu: Add support for gluster protocol based network storage backend. Qemu accepts gluster protocol as supported storage backend beside others. Signed-off-by: Harsh Prateek Bora --- src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 170 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 886347cfa3..63e187a45c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -346,6 +346,7 @@ virDomainDiskErrorPolicyTypeToString; virDomainDiskFindControllerModel; virDomainDiskGeometryTransTypeFromString; virDomainDiskGeometryTransTypeToString; +virDomainDiskHostDefFree; virDomainDiskIndexByName; virDomainDiskInsert; virDomainDiskInsertPreAlloced; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8af42256cf..77365751b6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2040,6 +2040,144 @@ no_memory: return -1; } +static int +qemuParseGlusterString(virDomainDiskDefPtr def) +{ + int ret = -1; + char *transp = NULL; + char *sock = NULL; + char *volimg = NULL; + virURIPtr uri = NULL; + + if (!(uri = virURIParse(def->src))) { + return -1; + } + + if (VIR_ALLOC(def->hosts) < 0) + goto no_memory; + + if (STREQ(uri->scheme, "gluster")) { + def->hosts->transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; + } else if (STRPREFIX(uri->scheme, "gluster+")) { + transp = strchr(uri->scheme, '+') + 1; + def->hosts->transport = virDomainDiskProtocolTransportTypeFromString(transp); + if (def->hosts->transport < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid gluster transport type '%s'"), transp); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid transport/scheme '%s'"), uri->scheme); + goto error; + } + def->nhosts = 0; /* set to 1 once everything succeeds */ + + if (def->hosts->transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) { + def->hosts->name = strdup(uri->server); + if (!def->hosts->name) + goto no_memory; + + if (virAsprintf(&def->hosts->port, "%d", uri->port) < 0) + goto no_memory; + } else { + def->hosts->name = NULL; + def->hosts->port = 0; + if (uri->query) { + if (STRPREFIX(uri->query, "socket=")) { + sock = strchr(uri->query, '=') + 1; + def->hosts->socket = strdup(sock); + if (!def->hosts->socket) + goto no_memory; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid query parameter '%s'"), uri->query); + goto error; + } + } + } + volimg = uri->path + 1; /* skip the prefix slash */ + def->src = strdup(volimg); + if (!def->src) + goto no_memory; + + def->nhosts = 1; + ret = 0; + +cleanup: + virURIFree(uri); + + return ret; + +no_memory: + virReportOOMError(); +error: + virDomainDiskHostDefFree(def->hosts); + VIR_FREE(def->hosts); + goto cleanup; +} + +static int +qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt) +{ + int ret = -1; + int port = 0; + char *tmpscheme = NULL; + char *volimg = NULL; + char *sock = NULL; + char *builturi = NULL; + const char *transp = NULL; + virURI uri = { + .port = port /* just to clear rest of bits */ + }; + + if (disk->nhosts != 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("gluster accepts only one host")); + return -1; + } + + virBufferAddLit(opt, "file="); + transp = virDomainDiskProtocolTransportTypeToString(disk->hosts->transport); + + if (virAsprintf(&tmpscheme, "gluster+%s", transp) < 0) + goto no_memory; + + if (virAsprintf(&volimg, "/%s", disk->src) < 0) + goto no_memory; + + if (disk->hosts->port) { + port = atoi(disk->hosts->port); + } + + if (disk->hosts->socket && + virAsprintf(&sock, "socket=%s", disk->hosts->socket) < 0) + goto no_memory; + + uri.scheme = tmpscheme; /* gluster+ */ + uri.server = disk->hosts->name; + uri.port = port; + uri.path = volimg; + uri.query = sock; + + builturi = virURIFormat(&uri); + virBufferEscape(opt, ',', ",", "%s", builturi); + + ret = 0; + +cleanup: + VIR_FREE(builturi); + VIR_FREE(tmpscheme); + VIR_FREE(volimg); + VIR_FREE(sock); + + return ret; + +no_memory: + virReportOOMError(); + goto cleanup; +} + char * qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainDiskDefPtr disk, @@ -2180,6 +2318,12 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; virBufferAddChar(&opt, ','); break; + case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER: + if (qemuBuildGlusterString(disk, &opt) < 0) + goto error; + virBufferAddChar(&opt, ','); + break; + case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG: if (disk->nhosts == 0) { virBufferEscape(&opt, ',', ",", "file=sheepdog:%s,", @@ -5667,6 +5811,18 @@ qemuBuildCommandLine(virConnectPtr conn, file = virBufferContentAndReset(&opt); } break; + case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER: + { + virBuffer opt = VIR_BUFFER_INITIALIZER; + if (qemuBuildGlusterString(disk, &opt) < 0) + goto error; + if (virBufferError(&opt)) { + virReportOOMError(); + goto error; + } + file = virBufferContentAndReset(&opt); + } + break; case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG: if (disk->nhosts == 0) { if (virAsprintf(&file, "sheepdog:%s,", disk->src) < 0) { @@ -7074,6 +7230,12 @@ qemuParseCommandLineDisk(virCapsPtr caps, goto cleanup; VIR_FREE(p); + } else if (STRPREFIX(def->src, "gluster")) { + def->type = VIR_DOMAIN_DISK_TYPE_NETWORK; + def->protocol = VIR_DOMAIN_DISK_PROTOCOL_GLUSTER; + + if (qemuParseGlusterString(def) < 0) + goto cleanup; } else if (STRPREFIX(def->src, "sheepdog:")) { char *p = def->src; char *port, *vdi; @@ -8299,6 +8461,9 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK; disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_RBD; val += strlen("rbd:"); + } else if (STRPREFIX(val, "gluster")) { + disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK; + disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_GLUSTER; } else if (STRPREFIX(val, "sheepdog:")) { disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK; disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG; @@ -8384,6 +8549,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, goto no_memory; } break; + case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER: + if (qemuParseGlusterString(disk) < 0) + goto error; + + break; } }