From c1509ab47edf61e9f20d11922526b9fca518d238 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Thu, 24 Jan 2013 18:45:31 -0800 Subject: [PATCH] qemu: escape ipv6 for rbd network disk hosts Hosts for rbd are ceph monitor daemons. These have fixed IP addresses, so they are often referenced by IP rather than hostname for convenience, or to avoid relying on DNS. Using IPv4 addresses as the host name works already, but IPv6 addresses require rbd-specific escaping because the colon is used as an option separator in the string passed to qemu. Escape these colons, and enclose the IPv6 address in square brackets so it is distinguished from the port, which is currently mandatory. Acked-by: Osier Yang Signed-off-by: Josh Durgin --- docs/schemas/domaincommon.rng | 5 ++- src/qemu/qemu_command.c | 33 +++++++++++++---- tests/qemuargv2xmltest.c | 1 + ...uxml2argv-disk-drive-network-rbd-ipv6.args | 9 +++++ ...muxml2argv-disk-drive-network-rbd-ipv6.xml | 36 +++++++++++++++++++ tests/qemuxml2argvtest.c | 2 ++ 6 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 1a7d6b5dc1..049f232e08 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1099,7 +1099,10 @@ - + + + + diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 02fe015484..f6273c1798 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -34,6 +34,7 @@ #include "virerror.h" #include "virutil.h" #include "virfile.h" +#include "virstring.h" #include "viruuid.h" #include "c-ctype.h" #include "domain_nwfilter.h" @@ -1937,13 +1938,16 @@ qemuBuildRBDString(virConnectPtr conn, if (i) { virBufferAddLit(opt, "\\;"); } - if (disk->hosts[i].port) { - virBufferAsprintf(opt, "%s\\:%s", - disk->hosts[i].name, - disk->hosts[i].port); + + /* assume host containing : is ipv6 */ + if (strchr(disk->hosts[i].name, ':')) { + virBufferEscape(opt, '\\', ":", "[%s]", disk->hosts[i].name); } else { virBufferAsprintf(opt, "%s", disk->hosts[i].name); } + if (disk->hosts[i].port) { + virBufferAsprintf(opt, "\\:%s", disk->hosts[i].port); + } } } @@ -1961,15 +1965,25 @@ error: static int qemuAddRBDHost(virDomainDiskDefPtr disk, char *hostport) { char *port; + size_t skip; + char **parts; disk->nhosts++; if (VIR_REALLOC_N(disk->hosts, disk->nhosts) < 0) goto no_memory; - port = strstr(hostport, "\\:"); + if ((port = strchr(hostport, ']'))) { + /* ipv6, strip brackets */ + hostport += 1; + skip = 3; + } else { + port = strstr(hostport, "\\:"); + skip = 2; + } + if (port) { *port = '\0'; - port += 2; + port += skip; disk->hosts[disk->nhosts-1].port = strdup(port); if (!disk->hosts[disk->nhosts-1].port) goto no_memory; @@ -1978,7 +1992,12 @@ static int qemuAddRBDHost(virDomainDiskDefPtr disk, char *hostport) if (!disk->hosts[disk->nhosts-1].port) goto no_memory; } - disk->hosts[disk->nhosts-1].name = strdup(hostport); + + parts = virStringSplit(hostport, "\\:", 0); + if (!parts) + goto no_memory; + disk->hosts[disk->nhosts-1].name = virStringJoin((const char **)parts, ":"); + virStringFreeList(parts); if (!disk->hosts[disk->nhosts-1].name) goto no_memory; diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 29233245ea..e465f3d2cc 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -185,6 +185,7 @@ mymain(void) DO_TEST("disk-drive-network-nbd"); DO_TEST("disk-drive-network-gluster"); DO_TEST("disk-drive-network-rbd"); + DO_TEST("disk-drive-network-rbd-ipv6"); /* older format using CEPH_ARGS env var */ DO_TEST("disk-drive-network-rbd-ceph-env"); DO_TEST("disk-drive-network-sheepdog"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.args new file mode 100644 index 0000000000..0c67229bbc --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.args @@ -0,0 +1,9 @@ +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=rbd:pool/image:auth_supported=none:\ +mon_host=[\:\:1]\:6321\;example.org\:6789\;\ +[ffff\:1234\:567\:abc\:\:0f]\:6322\;\ +[2001\:db8\:\:ff00\:42\:8329]\:6322,\ +if=virtio,format=raw' -net none -serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.xml new file mode 100644 index 0000000000..a2ca2d2f0d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.xml @@ -0,0 +1,36 @@ + + 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 31ed116d77..88e1c36514 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -478,6 +478,8 @@ mymain(void) QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-network-rbd-auth", QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); + DO_TEST("disk-drive-network-rbd-ipv6", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-no-boot", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_BOOTINDEX); DO_TEST("disk-usb", NONE);