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

Harsh Bora harsh at linux.vnet.ibm.com
Fri Oct 5 12:03:38 UTC 2012


On 10/05/2012 05:27 PM, Paolo Bonzini wrote:
> 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.

Yeh, that makes perfect sense.

~ Harsh

>
> 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 Gluster-devel mailing list