[libvirt] [PATCH v2 1/2] Qemu/Gluster: Add Gluster protocol as supported network disk formats.

Paolo Bonzini pbonzini at redhat.com
Fri Oct 5 11:57:08 UTC 2012


Il 04/10/2012 15:31, Harsh Prateek Bora ha scritto:
> 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='volume/image'>
>         <host name='example.org' port='6000' transport='tcp'/>
>       </source>
>       <target dev='vda' bus='virtio'/>
>     </disk>
> 
> Note: In the <host> element above, transport is an optional attribute.
> Valid transport values are tcp, unix or rdma. If none specified, tcp is assumed.
> If transport type is unix, host name specifies path to unix socket.

I would rather add a new attribute "socket" than overload the host name.
 The host name for Unix sockets is really localhost.

Paolo

> Signed-off-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
> ---
>  docs/schemas/domaincommon.rng |   8 ++
>  src/conf/domain_conf.c        |  28 +++++-
>  src/conf/domain_conf.h        |  11 +++
>  src/libvirt_private.syms      |   2 +
>  src/qemu/qemu_command.c       | 204 ++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 251 insertions(+), 2 deletions(-)
> 
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index f47fdad..89d9b9f 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -1048,6 +1048,7 @@
>                      <value>nbd</value>
>                      <value>rbd</value>
>                      <value>sheepdog</value>
> +                    <value>gluster</value>
>                    </choice>
>                  </attribute>
>                  <optional>
> @@ -1061,6 +1062,13 @@
>                      <attribute name="port">
>                        <ref name="unsignedInt"/>
>                      </attribute>
> +                    <attribute name="transport">
> +                      <choice>
> +                        <value>tcp</value>
> +                        <value>unix</value>
> +                        <value>rdma</value>
> +                      </choice>
> +                    </attribute>
>                    </element>
>                  </zeroOrMore>
>                  <empty/>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 33e1e7f..838f079 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -214,7 +214,13 @@ VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
>  VIR_ENUM_IMPL(virDomainDiskProtocol, VIR_DOMAIN_DISK_PROTOCOL_LAST,
>                "nbd",
>                "rbd",
> -              "sheepdog")
> +              "sheepdog",
> +              "gluster")
> +
> +VIR_ENUM_IMPL(virDomainDiskProtocolTransport, VIR_DOMAIN_DISK_PROTO_TRANS_LAST,
> +              "tcp",
> +              "unix",
> +              "rdma")
>  
>  VIR_ENUM_IMPL(virDomainDiskSecretType, VIR_DOMAIN_DISK_SECRET_TYPE_LAST,
>                "none",
> @@ -3460,6 +3466,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
>      char *source = NULL;
>      char *target = NULL;
>      char *protocol = NULL;
> +    char *protocol_transport;
>      char *trans = NULL;
>      virDomainDiskHostDefPtr hosts = NULL;
>      int nhosts = 0;
> @@ -3566,6 +3573,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
>                              }
>                              hosts[nhosts].name = NULL;
>                              hosts[nhosts].port = NULL;
> +                            hosts[nhosts].transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP;
>                              nhosts++;
>  
>                              hosts[nhosts - 1].name = virXMLPropString(child, "name");
> @@ -3580,6 +3588,17 @@ virDomainDiskDefParseXML(virCapsPtr caps,
>                                                 "%s", _("missing port for host"));
>                                  goto error;
>                              }
> +                            /* transport can be tcp (default), unix or rdma.  */
> +                            protocol_transport = virXMLPropString(child, "transport");
> +                            if (protocol_transport != NULL) {
> +                                hosts[nhosts - 1].transport = virDomainDiskProtocolTransportTypeFromString(protocol_transport);
> +                                if (hosts[nhosts - 1].transport < 0) {
> +                                    virReportError(VIR_ERR_INTERNAL_ERROR,
> +                                                   _("unknown protocol transport type '%s'"),
> +                                                   protocol_transport);
> +                                    goto error;
> +                                }
> +                            }
>                          }
>                          child = child->next;
>                      }
> @@ -11756,8 +11775,13 @@ virDomainDiskDefFormat(virBufferPtr buf,
>                  for (i = 0; i < def->nhosts; i++) {
>                      virBufferEscapeString(buf, "        <host name='%s'",
>                                            def->hosts[i].name);
> -                    virBufferEscapeString(buf, " port='%s'/>\n",
> +                    virBufferEscapeString(buf, " port='%s'",
>                                            def->hosts[i].port);
> +                    if (def->hosts[i].transport) {
> +                        virBufferAsprintf(buf, " transport='%s'",
> +                                          virDomainDiskProtocolTransportTypeToString(def->hosts[i].transport));
> +                    }
> +                    virBufferAddLit(buf, "/>\n");
>                  }
>                  virBufferAddLit(buf, "      </source>\n");
>              }
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 14dead3..7ba7e9b 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -456,10 +456,19 @@ enum virDomainDiskProtocol {
>      VIR_DOMAIN_DISK_PROTOCOL_NBD,
>      VIR_DOMAIN_DISK_PROTOCOL_RBD,
>      VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG,
> +    VIR_DOMAIN_DISK_PROTOCOL_GLUSTER,
>  
>      VIR_DOMAIN_DISK_PROTOCOL_LAST
>  };
>  
> +enum virDomainDiskProtocolTransport {
> +    VIR_DOMAIN_DISK_PROTO_TRANS_TCP,
> +    VIR_DOMAIN_DISK_PROTO_TRANS_UNIX,
> +    VIR_DOMAIN_DISK_PROTO_TRANS_RDMA,
> +
> +    VIR_DOMAIN_DISK_PROTO_TRANS_LAST
> +};
> +
>  enum virDomainDiskTray {
>      VIR_DOMAIN_DISK_TRAY_CLOSED,
>      VIR_DOMAIN_DISK_TRAY_OPEN,
> @@ -481,6 +490,7 @@ typedef virDomainDiskHostDef *virDomainDiskHostDefPtr;
>  struct _virDomainDiskHostDef {
>      char *name;
>      char *port;
> +    int transport; /* enum virDomainDiskProtocolTransport */
>  };
>  
>  enum  virDomainDiskIo {
> @@ -2166,6 +2176,7 @@ VIR_ENUM_DECL(virDomainDiskBus)
>  VIR_ENUM_DECL(virDomainDiskCache)
>  VIR_ENUM_DECL(virDomainDiskErrorPolicy)
>  VIR_ENUM_DECL(virDomainDiskProtocol)
> +VIR_ENUM_DECL(virDomainDiskProtocolTransport)
>  VIR_ENUM_DECL(virDomainDiskIo)
>  VIR_ENUM_DECL(virDomainDiskSecretType)
>  VIR_ENUM_DECL(virDomainDiskTray)
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index dab607a..8e70837 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -350,6 +350,8 @@ virDomainDiskInsertPreAlloced;
>  virDomainDiskIoTypeFromString;
>  virDomainDiskIoTypeToString;
>  virDomainDiskPathByName;
> +virDomainDiskProtocolTransportTypeFromString;
> +virDomainDiskProtocolTransportTypeToString;
>  virDomainDiskRemove;
>  virDomainDiskRemoveByName;
>  virDomainDiskTypeFromString;
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 20730a9..0bed2bc 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -2021,6 +2021,168 @@ no_memory:
>      return -1;
>  }
>  
> +static int qemuParseGlusterString(virDomainDiskDefPtr def)
> +{
> +    char *host = NULL, *port = NULL, *volimg, *transp = NULL, *marker;
> +
> +    if (STRPREFIX(def->src, "+")) {
> +        transp = def->src;
> +        transp++;
> +        marker = strstr(def->src, "://");
> +        *marker++ = '\0';
> +        marker += 2;
> +    } else {
> +        /* transport type not specified, use tcp as default */
> +        def->hosts->transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP;
> +        marker = strstr(def->src, "://");
> +        marker += 3;
> +    }
> +
> +    if (transp) {
> +        def->hosts->transport = virDomainDiskProtocolTransportTypeFromString(transp);
> +        if (def->hosts->transport < 0) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Invalid gluster transport type '%s'"), transp);
> +            return -1;
> +        }
> +    }
> +
> +    /* now marker points to string which can start with one of the following:
> +     * IPv6 address in square brackets followed by port (optional)
> +     * <hostname> or <IPv4 address> followed by port (optional)
> +     * '/' if its a unix socket followed by path to gluster disk volume/image
> +     */
> +
> +    /* parse server, port */
> +    if (def->hosts->transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) {
> +        if (STRPREFIX(marker, "[")) {
> +            /* IPv6 addr */
> +            host = ++marker;
> +            marker = strchr(host, ']');
> +            if (!marker) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("Cannot parse IPv6 addr for gluster host %s "), host);
> +                return -1;
> +            }
> +            *marker++ = '\0';
> +            /* parse port if specified */
> +            if (STRPREFIX(marker, ":")) {
> +                port = ++marker;
> +                marker = strchr(port, '/');
> +                if (!marker) {
> +                    virReportError(VIR_ERR_INTERNAL_ERROR,
> +                                   _("Cannot parse filename for gluster disk %s "), port);
> +                    return -1;
> +                }
> +                *marker++ = '\0';
> +            } else {
> +                marker++; /* port not specified, skip slash */
> +            }
> +        } else {
> +            /* IPv4 address / hostname followed by port (optional) */
> +            host = marker;
> +            marker = strchr(host, '/'); /* skip to path to gluster disk vol/img */
> +            if (!marker) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("Cannot parse filename for gluster disk %s "), port);
> +                return -1;
> +            }
> +            *marker++ = '\0';
> +            port = strchr(host, ':');
> +            if (port) {
> +                /* port was specified with host, separate both */
> +                *port++ = '\0';
> +            }
> +        }
> +
> +        /* host points to hostname / IPv4 / IPv6 addr
> +         * port points to port or NULL is port was not specified
> +         */
> +    } else {
> +        /* transport type is unix, expect one more slash
> +         * followed by path to gluster disk vol/img */
> +        if (STRPREFIX(marker, "/")) {
> +            marker++;
> +        } else {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Gluster unix transport url starts with 3 slashes i.e. gluster+unix:///"));
> +            return -1;
> +        }
> +    }
> +
> +    /* marker now points to path to gluster disk vol/img */
> +    volimg = marker;
> +
> +    /* if transport type = unix, path to gluster disk vol/img
> +     * is followed by ?socket=<path/to/socket> */
> +    if (def->hosts->transport == VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) {
> +        if (strstr(marker, "?socket=")) {
> +            /* In libvirt xml, socket path is to be provided as
> +             * <host name='/path/to/socket' port='0'>
> +             */
> +            host = strchr(marker, '=');
> +            *host++ = '\0';
> +        }
> +    }
> +
> +    if (VIR_ALLOC(def->hosts) < 0) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +    def->nhosts = 1;
> +    def->hosts->name = host;
> +    if (port) {
> +        def->hosts->port = port;
> +    } else {
> +        def->hosts->port = strdup("0");
> +    }
> +    if (!def->hosts->port) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +    def->src = strdup(volimg);
> +    if (!def->src) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +static int
> +qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt)
> +{
> +    int ret = 0;
> +    virBufferAddLit(opt, "file=");
> +    if (disk->nhosts != 1) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("gluster accepts only one host"));
> +        ret = -1;
> +    } else {
> +        virBufferAsprintf(opt, "gluster+%s://",
> +                          virDomainDiskProtocolTransportTypeToString(disk->hosts->transport));
> +
> +        /* if transport type is not unix, specify server:port */
> +        if (disk->hosts->transport != VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) {
> +            if (strstr(disk->hosts->name, ":")) {
> +                /* if IPv6 addr, use square brackets to enclose it */
> +                virBufferAsprintf(opt, "[%s]:%s", disk->hosts->name, disk->hosts->port);
> +            } else {
> +                virBufferAsprintf(opt, "%s:%s", disk->hosts->name, disk->hosts->port);
> +            }
> +        }
> +
> +        /* append source path to gluster disk image */
> +        virBufferAsprintf(opt, "/%s", disk->src);
> +
> +        /* if transport type is unix, server name is path to unix socket, ignore port */
> +        if (disk->hosts->transport == VIR_DOMAIN_DISK_PROTO_TRANS_UNIX) {
> +            virBufferAsprintf(opt, "?socket=%s", disk->hosts->name);
> +        }
> +    }
> +    return ret;
> +}
> +
>  char *
>  qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
>                    virDomainDiskDefPtr disk,
> @@ -2162,6 +2324,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 +5410,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) {
> @@ -6937,6 +7117,21 @@ qemuParseCommandLineDisk(virCapsPtr caps,
>                          goto cleanup;
>  
>                      VIR_FREE(p);
> +                } else if (STRPREFIX(def->src, "gluster")) {
> +                    char *p = def->src;
> +
> +                    def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
> +                    def->protocol = VIR_DOMAIN_DISK_PROTOCOL_GLUSTER;
> +                    def->src = strdup(p + strlen("gluster"));
> +                    if (!def->src) {
> +                        virReportOOMError();
> +                        goto cleanup;
> +                    }
> +
> +                    if (qemuParseGlusterString(def) < 0)
> +                        goto cleanup;
> +
> +                    VIR_FREE(p);
>                  } else if (STRPREFIX(def->src, "sheepdog:")) {
>                      char *p = def->src;
>                      char *port, *vdi;
> @@ -8126,6 +8321,10 @@ 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;
> +                val += strlen("gluster");
>              } else if (STRPREFIX(val, "sheepdog:")) {
>                  disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
>                  disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG;
> @@ -8211,6 +8410,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
>                              goto no_memory;
>                      }
>                      break;
> +                case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER:
> +                    if (qemuParseGlusterString(disk) < 0)
> +                        goto error;
> +
> +                    break;
>                  }
>              }
>  
> 




More information about the libvir-list mailing list