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

Harsh Prateek Bora harsh at linux.vnet.ibm.com
Thu Nov 22 18:10:39 UTC 2012


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 at linux.vnet.ibm.com>
---
 src/qemu/qemu_command.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 183 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 20730a9..a377744 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2021,6 +2021,156 @@ 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, "+") + 1;
+        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, "=") + 1;
+                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 + 1; /* 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 +2312,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 +5398,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 +7087,6 @@ qemuParseCommandLineDisk(virCapsPtr caps,
                         virReportOOMError();
                         goto cleanup;
                     }
-
                     VIR_FREE(def->src);
                     def->src = NULL;
                 } else if (STRPREFIX(def->src, "rbd:")) {
@@ -6937,6 +7104,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 +7145,7 @@ qemuParseCommandLineDisk(virCapsPtr caps,
                             virReportOOMError();
                             goto cleanup;
                         }
+
                         def->src = strdup(vdi);
                         if (!def->src) {
                             virReportOOMError();
@@ -8126,6 +8300,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 +8388,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
                             goto no_memory;
                     }
                     break;
+                case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER:
+                    if (qemuParseGlusterString(disk) < 0)
+                        goto error;
+
+                    break;
                 }
             }
 
-- 
1.7.11.7




More information about the libvir-list mailing list