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(a)linux.vnet.ibm.com>
---
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