]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: support URI syntax for NBD
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 25 Feb 2013 17:44:25 +0000 (18:44 +0100)
committerEric Blake <eblake@redhat.com>
Fri, 15 Mar 2013 21:47:50 +0000 (15:47 -0600)
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 <pbonzini@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
src/qemu/qemu_command.c
tests/qemuargv2xmltest.c
tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.xml [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index 63478f72cd917efdb643b09c606368c349604e24..4891b65262535de223c0206377fb3f030c4a5250 100644 (file)
@@ -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;
 
index a2842337765aabc5673505d8b5e49866c6d61504..d4219854214df3848c0504d9d13d5a60430c17c0 100644 (file)
@@ -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 (file)
index 0000000..a942935
--- /dev/null
@@ -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 (file)
index 0000000..595d7ea
--- /dev/null
@@ -0,0 +1,33 @@
+<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='nbd' name='bar'>
+        <host name='::1' port='6000'/>
+      </source>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
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 (file)
index 0000000..7cdbdd1
--- /dev/null
@@ -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 (file)
index 0000000..3c5c99d
--- /dev/null
@@ -0,0 +1,33 @@
+<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='nbd'>
+        <host name='::1' port='6000'/>
+      </source>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
index f5e7ced053ac541cd4b283b649fcdb7053f33635..e76d84491a0505262b579d562ca015c2d95b6730 100644 (file)
@@ -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",
index 33ea45e50ed82101180858f3ebdd70cfcfe0e358..09d81e04e5e7b7fdc5bd16930837f5d33ea5a60a 100644 (file)
@@ -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");