Qemu accepts gluster protocol as supported storage backend beside others. This patch allows users to specify disks on gluster backends like this: <disk type='network' device='disk'> <driver name='qemu' type='raw'/> <source protocol='gluster' name='Volume1/image'> <host name='example.org' port='6000' transport='tcp'/> </source> <target dev='vda' bus='virtio'/> </disk> <disk type='network' device='disk'> <driver name='qemu' type='raw'/> <source protocol='gluster' name='Volume2/image'> <host transport='unix' socket='/path/to/sock'/> </source> <target dev='vdb' bus='virtio'/> </disk> Signed-off-by: Harsh Prateek Bora <harsh@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_command.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 197 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 20730a9..df376d6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1940,6 +1940,10 @@ static int qemuAddRBDHost(virDomainDiskDefPtr disk, char *hostport) disk->hosts[disk->nhosts-1].name = strdup(hostport); if (!disk->hosts[disk->nhosts-1].name) goto no_memory; + + disk->hosts[disk->nhosts-1].transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; + disk->hosts[disk->nhosts-1].socket = NULL; + return 0; no_memory: @@ -2021,6 +2025,159 @@ no_memory: return -1; } +static int +qemuParseGlusterString(virDomainDiskDefPtr def) +{ + int ret = 0; + 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) { + ret = -1; + goto no_memory; + } + + if (STREQ(uri->scheme, "gluster")) { + def->hosts->transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; + } else if (STRPREFIX(uri->scheme, "gluster+")) { + transp = strstr(uri->scheme, "+"); + transp++; + def->hosts->transport = virDomainDiskProtocolTransportTypeFromString(transp); + if (def->hosts->transport < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid gluster transport type '%s'"), transp); + ret = -1; + goto cleanup; + + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid transport/scheme '%s'"), uri->scheme); + ret = -1; + goto cleanup; + } + 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) { + ret = -1; + goto no_memory; + } + + if (virAsprintf(&def->hosts->port, "%d", uri->port) < 0) { + ret = -1; + goto no_memory; + } + } else { + def->hosts->name = NULL; + def->hosts->port = 0; + if(uri->query) { + if(STRPREFIX(uri->query, "socket=")) { + sock = strstr(uri->query, "="); + sock++; + def->hosts->socket = strdup(sock); + if (!def->hosts->socket) { + ret = -1; + goto no_memory; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid query parameter '%s'"), uri->query); + goto cleanup; + } + } + } + volimg = uri->path; + volimg++; /* skip the prefix slash */ + def->src = strdup(volimg); + if (!def->src) { + ret = -1; + goto no_memory; + } + + def->nhosts = 1; + VIR_FREE(uri); + return ret; + +no_memory: + virReportOOMError(); +cleanup: + VIR_FREE(def->hosts); + VIR_FREE(uri); + + return ret; +} + +static int +qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt) +{ + int ret = 0, 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) { + ret = -1; + goto no_memory; + } + + if (virAsprintf(&volimg, "/%s", disk->src) < 0) { + ret = -1; + goto no_memory; + } + + if (disk->hosts->port) { + port = atoi(disk->hosts->port); + } + + if (disk->hosts->socket) { + if (virAsprintf(&sock, "socket=%s", disk->hosts->socket) < 0) { + ret = -1; + goto no_memory; + } + } + + uri.scheme = tmpscheme; /* gluster+<transport> */ + uri.server = disk->hosts->name; + uri.port = port; + uri.path = volimg; + uri.query = sock; + + builturi = virURIFormat(&uri); + virBufferEscape(opt, ',', ",", "%s", builturi); + goto cleanup; + +no_memory: + virReportOOMError(); +cleanup: + VIR_FREE(builturi); + VIR_FREE(tmpscheme); + VIR_FREE(volimg); + VIR_FREE(sock); + + return ret; +} + char * qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainDiskDefPtr disk, @@ -2162,6 +2319,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,", @@ -5242,6 +5405,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) { @@ -6919,7 +7094,8 @@ qemuParseCommandLineDisk(virCapsPtr caps, virReportOOMError(); goto cleanup; } - + def->hosts->transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; + def->hosts->socket = NULL; VIR_FREE(def->src); def->src = NULL; } else if (STRPREFIX(def->src, "rbd:")) { @@ -6937,6 +7113,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; @@ -6972,6 +7154,9 @@ qemuParseCommandLineDisk(virCapsPtr caps, virReportOOMError(); goto cleanup; } + def->hosts->transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; + def->hosts->socket = NULL; + def->src = strdup(vdi); if (!def->src) { virReportOOMError(); @@ -8126,6 +8311,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; @@ -8211,6 +8399,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, goto no_memory; } break; + case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER: + if (qemuParseGlusterString(disk) < 0) + goto error; + + break; } } @@ -8666,6 +8859,9 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, VIR_FREE(hosts); goto no_memory; } + first_rbd_disk->hosts[first_rbd_disk->nhosts].transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; + first_rbd_disk->hosts[first_rbd_disk->nhosts].socket = NULL; + first_rbd_disk->nhosts++; token = strtok_r(NULL, ",", &saveptr); } -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list