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@xxxxxxxxxxxxxxxxxx> > --- > 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; > } > } > > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list