[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v4 2/3] qemu: Add support for gluster protocol based network storage backend.



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 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]