[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 26 09:36:19 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.

After looking into the URI infra, I realized, it is better to have the 
new attribute name as 'query' since socket=</path/to/socket> in 
qemu-gluster commandline is nothing but a query in the whole URI 
following by a '?' character.

Since, the _virURI struct in libvirt also has a member 'query' for the 
query string in a URI, it makes sense to keep the XML attribute as 
generic as that so that it can be used by others for related purpose.

Needless to say, users will have to specify sockets as
<host name='example.org' port='6000' transport='unix' 
query='socket=/path/to/sock' />

Also, since the libvirt mandates the host element to be provided a name 
and port, but the qemu-gluster commandline doesnt allow server-port for 
the unix transport, it will have to be handled differently, otherwise 
the virURIFormat will add in the server, port info into the URI.

If no objections, I will shared the updated patches soon.

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 libvir-list mailing list