]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: escape ipv6 for rbd network disk hosts
authorJosh Durgin <josh.durgin@inktank.com>
Fri, 25 Jan 2013 02:45:31 +0000 (18:45 -0800)
committerOsier Yang <jyang@redhat.com>
Fri, 25 Jan 2013 03:48:24 +0000 (11:48 +0800)
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 <jyang@redhat.com>
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
docs/schemas/domaincommon.rng
src/qemu/qemu_command.c
tests/qemuargv2xmltest.c
tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-ipv6.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c

index 1a7d6b5dc122e9e5d1a2177155c9ecb58912ac05..049f232e08fff9b97db141da74dfe472b721fc12 100644 (file)
                           </attribute>
                         </optional>
                         <attribute name="name">
-                          <ref name="dnsName"/>
+                          <choice>
+                            <ref name="dnsName"/>
+                            <ref name="ipAddr"/>
+                          </choice>
                         </attribute>
                         <attribute name="port">
                           <ref name="unsignedInt"/>
index 02fe015484fc71ef579634c73d584fc67251787f..f6273c179879b3d67e7f0edc2de981d7ad138660 100644 (file)
@@ -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;
 
index 29233245ea35ff8f44dc231bb913278d945cda1e..e465f3d2ccc565334dfd07352ecc98e8c363ca8f 100644 (file)
@@ -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 (file)
index 0000000..0c67229
--- /dev/null
@@ -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 (file)
index 0000000..a2ca2d2
--- /dev/null
@@ -0,0 +1,36 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <disk type='network' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source protocol='rbd' name='pool/image'>
+        <host name='::1' port='6321'/>
+        <host name='example.org' port='6789'/>
+        <host name='ffff:1234:567:abc::0f' port='6322'/>
+        <host name='2001:db8::ff00:42:8329' port='6322'/>
+      </source>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
index 31ed116d77d6389ee257a3d31112dd85a745188c..88e1c3651408e24f6323d3f0416773072f7186f9 100644 (file)
@@ -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);