From eebbb232e65e555b7d358ca752c23d2bacaf4edf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 25 Feb 2013 18:44:25 +0100 Subject: [PATCH] qemu: support URI syntax for NBD QEMU 1.3 and newer support an alternative URI-based syntax to specify the location of an NBD server. Libvirt can keep on using the old syntax in general, but only the URI syntax supports IPv6 addresses. The URI syntax also supports relative paths to Unix sockets. These should never be used but aren't explicitly blocked either by the parser, so support it just in case. The URI syntax is intentionally compatible with Gluster's, and the code can be reused. Signed-off-by: Paolo Bonzini Signed-off-by: Eric Blake --- src/qemu/qemu_command.c | 93 +++++++++++++------ tests/qemuargv2xmltest.c | 2 + ...gv-disk-drive-network-nbd-ipv6-export.args | 5 + ...rgv-disk-drive-network-nbd-ipv6-export.xml | 33 +++++++ ...uxml2argv-disk-drive-network-nbd-ipv6.args | 5 + ...muxml2argv-disk-drive-network-nbd-ipv6.xml | 33 +++++++ tests/qemuxml2argvtest.c | 4 + tests/qemuxml2xmltest.c | 2 + 8 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 63478f72c..4891b6526 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2296,35 +2296,36 @@ no_memory: } static int -qemuParseGlusterString(virDomainDiskDefPtr def) +qemuParseDriveURIString(virDomainDiskDefPtr def, virURIPtr uri, + const char *scheme) { int ret = -1; char *transp = NULL; char *sock = NULL; char *volimg = NULL; - virURIPtr uri = NULL; - - if (!(uri = virURIParse(def->src))) { - return -1; - } if (VIR_ALLOC(def->hosts) < 0) goto no_memory; - if (STREQ(uri->scheme, "gluster")) { + transp = strchr(uri->scheme, '+'); + if (transp) + *transp++ = 0; + + if (!STREQ(uri->scheme, scheme)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid transport/scheme '%s'"), uri->scheme); + goto error; + } + + if (!transp) { def->hosts->transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP; - } else if (STRPREFIX(uri->scheme, "gluster+")) { - transp = strchr(uri->scheme, '+') + 1; + } else { def->hosts->transport = virDomainDiskProtocolTransportTypeFromString(transp); if (def->hosts->transport < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid gluster transport type '%s'"), transp); + _("Invalid %s transport type '%s'"), scheme, transp); goto error; } - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid transport/scheme '%s'"), uri->scheme); - goto error; } def->nhosts = 0; /* set to 1 once everything succeeds */ @@ -2351,11 +2352,16 @@ qemuParseGlusterString(virDomainDiskDefPtr def) } } } - volimg = uri->path + 1; /* skip the prefix slash */ - VIR_FREE(def->src); - def->src = strdup(volimg); - if (!def->src) - goto no_memory; + if (uri->path) { + volimg = uri->path + 1; /* skip the prefix slash */ + VIR_FREE(def->src); + def->src = strdup(volimg); + if (!def->src) + goto no_memory; + } else { + VIR_FREE(def->src); + def->src = NULL; + } def->nhosts = 1; ret = 0; @@ -2373,6 +2379,17 @@ error: goto cleanup; } +static int +qemuParseGlusterString(virDomainDiskDefPtr def) +{ + virURIPtr uri = NULL; + + if (!(uri = virURIParse(def->src))) + return -1; + + return qemuParseDriveURIString(def, uri, "gluster"); +} + static int qemuParseNBDString(virDomainDiskDefPtr disk) { @@ -2380,6 +2397,14 @@ qemuParseNBDString(virDomainDiskDefPtr disk) char *host, *port; char *src; + virURIPtr uri = NULL; + + if (strstr(disk->src, "://")) { + uri = virURIParse(disk->src); + if (uri) + return qemuParseDriveURIString(disk, uri, "nbd"); + } + if (VIR_ALLOC(h) < 0) goto no_memory; @@ -2436,7 +2461,8 @@ error: } static int -qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt) +qemuBuildDriveURIString(virDomainDiskDefPtr disk, virBufferPtr opt, + const char *scheme) { int ret = -1; int port = 0; @@ -2450,18 +2476,18 @@ qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt) }; if (disk->nhosts != 1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("gluster accepts only one host")); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%s accepts only one host"), scheme); return -1; } virBufferAddLit(opt, "file="); transp = virDomainDiskProtocolTransportTypeToString(disk->hosts->transport); - if (virAsprintf(&tmpscheme, "gluster+%s", transp) < 0) + if (virAsprintf(&tmpscheme, "%s+%s", scheme, transp) < 0) goto no_memory; - if (virAsprintf(&volimg, "/%s", disk->src) < 0) + if (disk->src && virAsprintf(&volimg, "/%s", disk->src) < 0) goto no_memory; if (disk->hosts->port) { @@ -2496,6 +2522,12 @@ no_memory: goto cleanup; } +static int +qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt) +{ + return qemuBuildDriveURIString(disk, opt, "gluster"); +} + #define QEMU_DEFAULT_NBD_PORT "10809" static int @@ -2509,6 +2541,13 @@ qemuBuildNBDString(virDomainDiskDefPtr disk, virBufferPtr opt) return -1; } + if ((disk->hosts->name && strchr(disk->hosts->name, ':')) + || (disk->hosts->transport == VIR_DOMAIN_DISK_PROTO_TRANS_TCP + && !disk->hosts->name) + || (disk->hosts->transport == VIR_DOMAIN_DISK_PROTO_TRANS_UNIX + && disk->hosts->socket && disk->hosts->socket[0] != '/')) + return qemuBuildDriveURIString(disk, opt, "nbd"); + virBufferAddLit(opt, "file=nbd:"); switch (disk->hosts->transport) { @@ -7832,7 +7871,8 @@ qemuParseCommandLineDisk(virCapsPtr qemuCaps, values[i] = NULL; if (STRPREFIX(def->src, "/dev/")) def->type = VIR_DOMAIN_DISK_TYPE_BLOCK; - else if (STRPREFIX(def->src, "nbd:")) { + else if (STRPREFIX(def->src, "nbd:") || + STRPREFIX(def->src, "nbd+")) { def->type = VIR_DOMAIN_DISK_TYPE_NETWORK; def->protocol = VIR_DOMAIN_DISK_PROTOCOL_NBD; @@ -7853,7 +7893,8 @@ qemuParseCommandLineDisk(virCapsPtr qemuCaps, goto cleanup; VIR_FREE(p); - } else if (STRPREFIX(def->src, "gluster")) { + } else if (STRPREFIX(def->src, "gluster:") || + STRPREFIX(def->src, "gluster+")) { def->type = VIR_DOMAIN_DISK_TYPE_NETWORK; def->protocol = VIR_DOMAIN_DISK_PROTOCOL_GLUSTER; diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index a28423377..d42198542 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -186,6 +186,8 @@ mymain(void) DO_TEST("disk-drive-cache-unsafe"); DO_TEST("disk-drive-network-nbd"); DO_TEST("disk-drive-network-nbd-export"); + DO_TEST("disk-drive-network-nbd-ipv6"); + DO_TEST("disk-drive-network-nbd-ipv6-export"); DO_TEST("disk-drive-network-nbd-unix"); DO_TEST("disk-drive-network-gluster"); DO_TEST("disk-drive-network-rbd"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args new file mode 100644 index 000000000..a942935d1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -drive file=/dev/HostVG/QEMUGuest1,if=ide,bus=0,unit=0 \ +-drive 'file=nbd+tcp://[::1]:6000/bar,if=virtio,format=raw' -net none \ +-serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.xml new file mode 100644 index 000000000..595d7ea39 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.xml @@ -0,0 +1,33 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args new file mode 100644 index 000000000..7cdbdd1e1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -drive file=/dev/HostVG/QEMUGuest1,if=ide,bus=0,unit=0 \ +-drive 'file=nbd+tcp://[::1]:6000,if=virtio,format=raw' -net none \ +-serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.xml new file mode 100644 index 000000000..3c5c99df7 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.xml @@ -0,0 +1,33 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f5e7ced05..e76d84491 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -495,6 +495,10 @@ mymain(void) QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-network-nbd-export", QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); + DO_TEST("disk-drive-network-nbd-ipv6", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); + DO_TEST("disk-drive-network-nbd-ipv6-export", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-network-nbd-unix", QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-network-gluster", diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 33ea45e50..09d81e04e 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -171,6 +171,8 @@ mymain(void) DO_TEST("disk-drive-cache-v1-none"); DO_TEST("disk-drive-network-nbd"); DO_TEST("disk-drive-network-nbd-export"); + DO_TEST("disk-drive-network-nbd-ipv6"); + DO_TEST("disk-drive-network-nbd-ipv6-export"); DO_TEST("disk-drive-network-nbd-unix"); DO_TEST("disk-scsi-device"); DO_TEST("disk-scsi-vscsi"); -- 2.39.5