[libvirt] [PATCH v3 2/3] qemu: add support for multiple gluster hosts/servers

Prasanna Kumar Kalever prasanna.kalever at redhat.com
Fri Jul 22 08:20:30 UTC 2016


This patch adds support for gluster specific JSON formatter functionality

currently libvirt has the capability to parse only one host and convert that
into URI formatted string, with the help of this patch libvirt will be able
to parse multiple hosts from the domain xml and can convert that into JSON
formatted string

if the number of hosts supplied is only one, then we use existing URI format
for backward compatibility and if number of hosts is greater than one we switch
to the new JSON format

before:
------
example.xml:
...
    <disk type='network' device='disk'>
      <driver name='qemu' type='qcow2' cache='none'/>
      <source protocol='gluster' name='testvol/a.qcow2'>
        <host name='1.2.3.4' port='24007' transport="tcp"/>
      </source>
       <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>
...

resultant string:
file=gluster://1.2.3.4:24007/testvol/a.qcow2, \
                           if=none,id=drive-virtio-disk0,format=qcow2,cache=none

after:
-----
example.xml:
...
    <disk type='network' device='disk'>
      <driver name='qemu' type='qcow2' cache='none'/>
      <source protocol='gluster' name='testvol/a.qcow2'>
        <host name='1.2.3.4' port='24009' transport="tcp"/>
        <host socket='/var/run/glusterd.socket' transport="unix"/>
      </source>
       <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>
...

resultant string:
-drive file=json:{
    "file": {
        "driver": "gluster",,
        "volume": "testvol",,
        "path": "/a.qcow2",,
        "server": [
            {
                "type": "tcp"
                "host": "1.2.3.4",,
                "port": 24009,,
            },,
            {
                "transport": "unix"
                "socket": "/var/run/glusterd.socket",
            }
        ]
    },,
    "driver": "qcow2"
}
,if=none,id=drive-virtio-disk0,cache=none

credits: sincere thanks to all the supporters

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever at redhat.com>
---
 src/qemu/qemu_command.c | 219 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 174 insertions(+), 45 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4558b9f..fc38ecf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -481,10 +481,12 @@ qemuNetworkDriveGetPort(int protocol,
             return 10809;
 
         case VIR_STORAGE_NET_PROTOCOL_ISCSI:
-        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
             /* no default port specified */
             return 0;
 
+        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+            return 24007;
+
         case VIR_STORAGE_NET_PROTOCOL_RBD:
         case VIR_STORAGE_NET_PROTOCOL_LAST:
         case VIR_STORAGE_NET_PROTOCOL_NONE:
@@ -684,16 +686,172 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf,
     return 0;
 }
 
+static char*
+qemuBuildNetworkDriveURI(virStorageSourcePtr src,
+                         qemuDomainSecretInfoPtr secinfo)
+{
+    virURIPtr uri = NULL;
+    char *str = NULL;
+
+    if (VIR_ALLOC(uri) < 0)
+        goto cleanup;
+
+    if (src->hosts->transport == VIR_STORAGE_NET_HOST_TRANS_TCP) {
+        if (VIR_STRDUP(uri->scheme,
+                       virStorageNetProtocolTypeToString(src->protocol)) < 0)
+            goto cleanup;
+    } else {
+        if (virAsprintf(&uri->scheme, "%s+%s",
+                        virStorageNetProtocolTypeToString(src->protocol),
+                        virStorageNetHostTransportTypeToString(src->hosts->transport)) < 0)
+            goto cleanup;
+    }
+
+    if (src->path) {
+        if (src->volume) {
+            if (virAsprintf(&uri->path, "/%s%s",
+                            src->volume, src->path) < 0)
+                goto cleanup;
+        } else {
+            if (virAsprintf(&uri->path, "%s%s",
+                            src->path[0] == '/' ? "" : "/",
+                            src->path) < 0)
+                goto cleanup;
+        }
+    }
+
+    if (src->hosts->transport != VIR_STORAGE_NET_HOST_TRANS_UNIX) {
+        if (VIR_STRDUP(uri->server, src->hosts->name) < 0)
+            goto cleanup;
+
+        if ((uri->port = qemuNetworkDriveGetPort(src->protocol, src->hosts->port)) < 0)
+            goto cleanup;
+    } else {
+        if (src->hosts->socket &&
+                virAsprintf(&uri->query, "socket=%s", src->hosts->socket) < 0)
+            goto cleanup;
+    }
+
+    if (qemuBuildGeneralSecinfoURI(uri, secinfo) < 0)
+        goto cleanup;
+
+    str = virURIFormat(uri);
+
+ cleanup:
+    virURIFree(uri);
+
+    return str;
+}
+
+static char *
+qemuBuildGlusterDriveJSON(virStorageSourcePtr src)
+{
+    virJSONValuePtr file = NULL;
+    virJSONValuePtr object = NULL;
+    virJSONValuePtr server = NULL;
+    char *ret = NULL;
+    size_t i;
+
+    if (!(file = virJSONValueNewObject()))
+        return NULL;
+
+    /* 1. prepare { driver:"gluster", volume:"testvol", path:"/a.img"} */
+    if (virJSONValueObjectAdd(file,
+                              "s:driver", virStorageNetProtocolTypeToString(src->protocol),
+                              "s:volume", src->volume,
+                              "s:path", src->path,
+                              NULL) < 0)
+        goto cleanup;
+
+    if (!(server = virJSONValueNewArray()))
+        goto cleanup;
+
+    /* 2. prepare array [ {type:"tcp", host:"1.2.3.4", port:24007},
+     *                    {type:"unix", socket:"/tmp/glusterd.socket"},
+     *                    {}, ... ] */
+    for (i = 0; i < src->nhosts; i++) {
+        if (!(object = virJSONValueNewObject()))
+            goto cleanup;
+        if (src->hosts[i].transport == 0) {
+            if (virJSONValueObjectAdd(object,
+                                      "s:type",
+                                      virStorageNetHostTransportTypeToString(src->hosts[i].transport),
+                                      "s:host", src->hosts[i].name,
+                                      "i:port",
+                                      qemuNetworkDriveGetPort(src->protocol, src->hosts[i].port),
+                                      NULL) < 0)
+                goto cleanup;
+        } else if (src->hosts[i].transport == 1) {
+            if (virJSONValueObjectAdd(object,
+                                      "s:type",
+                                      virStorageNetHostTransportTypeToString(src->hosts[i].transport),
+                                      "s:socket", src->hosts[i].socket,
+                                      NULL) < 0)
+                goto cleanup;
+        } else {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("protocol '%s' accepts only tranport tcp|unix"),
+                               virStorageNetProtocolTypeToString(src->protocol));
+                goto cleanup;
+        }
+
+        if (virJSONValueArrayAppend(server, object) < 0)
+            goto cleanup;
+    }
+
+    /* 3. append 1 and 2
+     * { driver:"gluster", volume:"testvol", path:"/a.img",
+     * server :[ {type:"tcp", host:"1.2.3.4", port:24007},
+     *           {type:"unix", socket:"/tmp/glusterd.socket"},
+     *           {}, ... ] }
+     */
+    if (virJSONValueObjectAppend(file, "server", server) < 0)
+        goto cleanup;
+
+    /* 4. assign key to 3
+     * { file: { driver:"gluster", volume:"testvol", path:"/a.img",
+     * server :[ {type:"tcp", host:"1.2.3.4", port:24007},
+     *           {type:"unix", socket:"/tmp/glusterd.socket"},
+     *            {}, ... ] } }
+     */
+    if (!(object = virJSONValueNewObject()))
+        goto cleanup;
+    if (virJSONValueObjectAppend(object, "file", file) < 0)
+        goto cleanup;
+
+    /* 5. append format to 4
+     * { file: { driver:"gluster", volume:"testvol", path:"/a.img",
+     * server :[ {type:"tcp", host:"1.2.3.4", port:24007},
+     *           {type:"unix", socket:"/tmp/glusterd.socket"},
+     *            {}, ... ] }, driver:"qcow2" }
+     */
+    if (virJSONValueObjectAdd(object,
+                              "s:driver", virStorageFileFormatTypeToString(src->format),
+                NULL) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&ret, "json:%s", virJSONValueToString(object, false)) < 0)
+        ret = NULL;
+
+    return ret;
+
+ cleanup:
+    virJSONValueFree(server);
+    virJSONValueFree(file);
+    virJSONValueFree(object);
+
+    return ret;
+}
+
 
 #define QEMU_DEFAULT_NBD_PORT "10809"
 
 static char *
-qemuBuildNetworkDriveURI(virStorageSourcePtr src,
+qemuBuildNetworkDriveStr(virStorageSourcePtr src,
                          qemuDomainSecretInfoPtr secinfo)
 {
     char *ret = NULL;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virURIPtr uri = NULL;
     size_t i;
 
     switch ((virStorageNetProtocol) src->protocol) {
@@ -758,57 +916,29 @@ qemuBuildNetworkDriveURI(virStorageSourcePtr src,
         case VIR_STORAGE_NET_PROTOCOL_FTPS:
         case VIR_STORAGE_NET_PROTOCOL_TFTP:
         case VIR_STORAGE_NET_PROTOCOL_ISCSI:
-        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
-            if (src->nhosts != 1) {
+            if (src->nhosts == 1) {
+                if (!(ret = qemuBuildNetworkDriveURI(src, secinfo)))
+                    goto cleanup;
+            } else {
                 virReportError(VIR_ERR_INTERNAL_ERROR,
                                _("protocol '%s' accepts only one host"),
                                virStorageNetProtocolTypeToString(src->protocol));
                 goto cleanup;
             }
 
-            if (VIR_ALLOC(uri) < 0)
-                goto cleanup;
+            break;
 
-            if (src->hosts->transport == VIR_STORAGE_NET_HOST_TRANS_TCP) {
-                if (VIR_STRDUP(uri->scheme,
-                               virStorageNetProtocolTypeToString(src->protocol)) < 0)
+        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+            if (src->nhosts == 1) {
+                /* URI formatted syntax */
+                if (!(ret = qemuBuildNetworkDriveURI(src, secinfo)))
                     goto cleanup;
             } else {
-                if (virAsprintf(&uri->scheme, "%s+%s",
-                                virStorageNetProtocolTypeToString(src->protocol),
-                                virStorageNetHostTransportTypeToString(src->hosts->transport)) < 0)
+                /* switch to new json formatted syntax */
+                if (!(ret = qemuBuildGlusterDriveJSON(src)))
                     goto cleanup;
             }
 
-            if ((uri->port = qemuNetworkDriveGetPort(src->protocol,
-                                                     src->hosts->port)) < 0)
-                goto cleanup;
-
-            if (src->path) {
-                if (src->volume) {
-                    if (virAsprintf(&uri->path, "/%s%s",
-                                    src->volume, src->path) < 0)
-                        goto cleanup;
-                } else {
-                    if (virAsprintf(&uri->path, "%s%s",
-                                    src->path[0] == '/' ? "" : "/",
-                                    src->path) < 0)
-                        goto cleanup;
-                }
-            }
-
-            if (src->hosts->socket &&
-                virAsprintf(&uri->query, "socket=%s", src->hosts->socket) < 0)
-                goto cleanup;
-
-            if (qemuBuildGeneralSecinfoURI(uri, secinfo) < 0)
-                goto cleanup;
-
-            if (VIR_STRDUP(uri->server, src->hosts->name) < 0)
-                goto cleanup;
-
-            ret = virURIFormat(uri);
-
             break;
 
         case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
@@ -889,7 +1019,6 @@ qemuBuildNetworkDriveURI(virStorageSourcePtr src,
 
  cleanup:
     virBufferFreeAndReset(&buf);
-    virURIFree(uri);
 
     return ret;
 }
@@ -919,7 +1048,7 @@ qemuGetDriveSourceString(virStorageSourcePtr src,
         break;
 
     case VIR_STORAGE_TYPE_NETWORK:
-        if (!(*source = qemuBuildNetworkDriveURI(src, secinfo)))
+        if (!(*source = qemuBuildNetworkDriveStr(src, secinfo)))
             goto cleanup;
         break;
 
@@ -4527,7 +4656,7 @@ qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev)
     src.nhosts = iscsisrc->nhosts;
 
     /* Rather than pull what we think we want - use the network disk code */
-    source = qemuBuildNetworkDriveURI(&src, hostdevPriv->secinfo);
+    source = qemuBuildNetworkDriveStr(&src, hostdevPriv->secinfo);
 
     return source;
 }
-- 
2.7.4




More information about the libvir-list mailing list