[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