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

Jiri Denemark jdenemar at redhat.com
Tue Nov 27 09:31:00 UTC 2012


On Thu, Nov 22, 2012 at 23:40:39 +0530, Harsh Prateek Bora wrote:
> 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>

Move these XML examples to 1/4.

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

In libvirt, we rather initialize ret = -1 and set it to 0 at the end of the
function when we know it succeeded. That way you don't have to remember to set
ret = -1 on every error.

> +        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=")) {

make syntax-check requires space between "if" and "(".

> +                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);

And this is the evidence how easy it is to forget ret = -1 :-)

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

"cleanup" label is generally used for code which is common to both success and
error paths. Use "error" label for error-path-only code.

> +    VIR_FREE(def->hosts);

Before freeing def->hosts, all strings referenced from it need to be freed by
calling virDomainDiskHostDefFree.

> +    VIR_FREE(uri);
> +
> +    return ret;
> +}
> +
> +static int
> +qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt)
> +{
> +    int ret = 0, port = 0;

Initialize ret to -1.

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

We like to keep the success path linear...

> +}
> +
>  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:")) {

Unrelated whitespace change.

> @@ -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();

Unrelated.

> @@ -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;
>                  }
>              }
>  

ACK with the following patch squashed in:

    diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
    index 886347c..63e187a 100644
    --- a/src/libvirt_private.syms
    +++ b/src/libvirt_private.syms
    @@ -346,6 +346,7 @@ virDomainDiskErrorPolicyTypeToString;
     virDomainDiskFindControllerModel;
     virDomainDiskGeometryTransTypeFromString;
     virDomainDiskGeometryTransTypeToString;
    +virDomainDiskHostDefFree;
     virDomainDiskIndexByName;
     virDomainDiskInsert;
     virDomainDiskInsertPreAlloced;
    diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
    index 50693a9..e946336 100644
    --- a/src/qemu/qemu_command.c
    +++ b/src/qemu/qemu_command.c
    @@ -2043,93 +2043,85 @@ no_memory:
     static int
     qemuParseGlusterString(virDomainDiskDefPtr def)
     {
    -    int ret = 0;
    +    int ret = -1;
         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;
    +    if (VIR_ALLOC(def->hosts) < 0)
             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;
    +        transp = strchr(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;
    -
    +            goto error;
             }
         } else {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Invalid transport/scheme '%s'"), uri->scheme);
    -        ret = -1;
    -        goto cleanup;
    +        goto error;
         }
         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;
    +        if (!def->hosts->name)
                 goto no_memory;
    -        }
     
    -        if (virAsprintf(&def->hosts->port, "%d", uri->port) < 0) {
    -            ret = -1;
    +        if (virAsprintf(&def->hosts->port, "%d", uri->port) < 0)
                 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;
    +        if (uri->query) {
    +            if (STRPREFIX(uri->query, "socket=")) {
    +                sock = strchr(uri->query, '=') + 1;
                     def->hosts->socket = strdup(sock);
    -                if (!def->hosts->socket) {
    -                    ret = -1;
    +                if (!def->hosts->socket)
                         goto no_memory;
    -                }
                 } else {
                     virReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("Invalid query parameter '%s'"), uri->query);
    -                goto cleanup;
    +                goto error;
                 }
             }
         }
         volimg = uri->path + 1; /* skip the prefix slash */
         def->src = strdup(volimg);
    -    if (!def->src) {
    -        ret = -1;
    +    if (!def->src)
             goto no_memory;
    -    }
     
         def->nhosts = 1;
    -    VIR_FREE(uri);
    +    ret = 0;
    +
    +cleanup:
    +    virURIFree(uri);
    +
         return ret;
     
     no_memory:
         virReportOOMError();
    -cleanup:
    +error:
    +    virDomainDiskHostDefFree(def->hosts);
         VIR_FREE(def->hosts);
    -    VIR_FREE(uri);
    -
    -    return ret;
    +    goto cleanup;
     }
     
     static int
     qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt)
     {
    -    int ret = 0, port = 0;
    +    int ret = -1;
    +    int port = 0;
         char *tmpscheme = NULL;
         char *volimg = NULL;
         char *sock = NULL;
    @@ -2148,26 +2140,19 @@ qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt)
         virBufferAddLit(opt, "file=");
         transp = virDomainDiskProtocolTransportTypeToString(disk->hosts->transport);
     
    -    if (virAsprintf(&tmpscheme, "gluster+%s", transp) < 0) {
    -        ret = -1;
    +    if (virAsprintf(&tmpscheme, "gluster+%s", transp) < 0)
             goto no_memory;
    -    }
     
    -    if (virAsprintf(&volimg, "/%s", disk->src) < 0) {
    -        ret = -1;
    +    if (virAsprintf(&volimg, "/%s", disk->src) < 0)
             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;
    -        }
    -    }
    +    if (disk->hosts->socket &&
    +        virAsprintf(&sock, "socket=%s", disk->hosts->socket) < 0)
    +        goto no_memory;
     
         uri.scheme = tmpscheme; /* gluster+<transport> */
         uri.server = disk->hosts->name;
    @@ -2177,10 +2162,9 @@ qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt)
     
         builturi = virURIFormat(&uri);
         virBufferEscape(opt, ',', ",", "%s", builturi);
    -    goto cleanup;
     
    -no_memory:
    -    virReportOOMError();
    +    ret = 0;
    +
     cleanup:
         VIR_FREE(builturi);
         VIR_FREE(tmpscheme);
    @@ -2188,6 +2172,10 @@ cleanup:
         VIR_FREE(sock);
     
         return ret;
    +
    +no_memory:
    +    virReportOOMError();
    +    goto cleanup;
     }
     
     char *




More information about the libvir-list mailing list