qemu: add support for libiscsi

libiscsi provides a userspace iSCSI initiator.

The main advantage over the kernel initiator is that it is very
easy to provide different initiator names for VMs on the same host.
Thus libiscsi supports usage of persistent reservations in the VM,
which otherwise would only be possible with NPIV.

libiscsi uses "iscsi" as the scheme, not "iscsi+tcp".  We can change
this in the tests (while remaining backwards-compatible manner, because
QEMU uses TCP as the default transport for both Gluster and NBD).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2013-03-21 12:53:49 +01:00 committed by Osier Yang
parent d450037740
commit 1a308ee015
9 changed files with 76 additions and 9 deletions

View File

@ -1446,10 +1446,13 @@
are "nbd", "iscsi", "rbd", "sheepdog" or "gluster". If the
<code>protocol</code> attribute is "rbd", "sheepdog" or "gluster", an
additional attribute <code>name</code> is mandatory to specify which
volume/image will be used; for "nbd" it is optional. When the disk
<code>type</code> is "network", the <code>source</code> may have zero
or more <code>host</code> sub-elements used to specify the hosts
to connect.
volume/image will be used; for "nbd" it is optional. For "iscsi",
the <code>name</code> attribute may include a logical unit number,
separated from the target's name by a slash (for example,
<code>iqn.1992-01.com.example/1</code>); the default LUN is zero.
When the disk <code>type</code> is "network", the <code>source</code>
may have zero or more <code>host</code> sub-elements used to
specify the hosts to connect.
<span class="since">Since 0.0.3; <code>type='dir'</code> since
0.7.5; <code>type='network'</code> since
0.8.7; <code>protocol='iscsi'</code> since 1.0.4</span><br/>

View File

@ -2390,6 +2390,31 @@ qemuParseGlusterString(virDomainDiskDefPtr def)
return qemuParseDriveURIString(def, uri, "gluster");
}
static int
qemuParseISCSIString(virDomainDiskDefPtr def)
{
virURIPtr uri = NULL;
char *slash;
unsigned lun;
if (!(uri = virURIParse(def->src)))
return -1;
if (uri->path &&
(slash = strchr(uri->path + 1, '/')) != NULL) {
if (slash[1] == '\0')
*slash = '\0';
else if (virStrToLong_ui(slash + 1, NULL, 10, &lun) == -1) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("invalid name '%s' for iSCSI disk"), def->src);
return -1;
}
}
return qemuParseDriveURIString(def, uri, "iscsi");
}
static int
qemuParseNBDString(virDomainDiskDefPtr disk)
{
@ -2484,8 +2509,14 @@ qemuBuildDriveURIString(virDomainDiskDefPtr disk, virBufferPtr opt,
virBufferAddLit(opt, "file=");
transp = virDomainDiskProtocolTransportTypeToString(disk->hosts->transport);
if (virAsprintf(&tmpscheme, "%s+%s", scheme, transp) < 0)
goto no_memory;
if (disk->hosts->transport == VIR_DOMAIN_DISK_PROTO_TRANS_TCP) {
tmpscheme = strdup(scheme);
if (tmpscheme == NULL)
goto no_memory;
} else {
if (virAsprintf(&tmpscheme, "%s+%s", scheme, transp) < 0)
goto no_memory;
}
if (disk->src && virAsprintf(&volimg, "/%s", disk->src) < 0)
goto no_memory;
@ -2530,6 +2561,12 @@ qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt)
#define QEMU_DEFAULT_NBD_PORT "10809"
static int
qemuBuildISCSIString(virDomainDiskDefPtr disk, virBufferPtr opt)
{
return qemuBuildDriveURIString(disk, opt, "iscsi");
}
static int
qemuBuildNBDString(virDomainDiskDefPtr disk, virBufferPtr opt)
{
@ -2713,6 +2750,11 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
goto error;
virBufferAddChar(&opt, ',');
break;
case VIR_DOMAIN_DISK_PROTOCOL_ISCSI:
if (qemuBuildISCSIString(disk, &opt) < 0)
goto error;
virBufferAddChar(&opt, ',');
break;
case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
if (disk->nhosts == 0) {
@ -7909,6 +7951,12 @@ qemuParseCommandLineDisk(virCapsPtr qemuCaps,
if (qemuParseGlusterString(def) < 0)
goto error;
} else if (STRPREFIX(def->src, "iscsi:")) {
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
def->protocol = VIR_DOMAIN_DISK_PROTOCOL_ISCSI;
if (qemuParseISCSIString(def) < 0)
goto error;
} else if (STRPREFIX(def->src, "sheepdog:")) {
char *p = def->src;
char *port, *vdi;
@ -9199,6 +9247,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
if (qemuParseGlusterString(disk) < 0)
goto error;
break;
case VIR_DOMAIN_DISK_PROTOCOL_ISCSI:
if (qemuParseISCSIString(disk) < 0)
goto error;
break;
}
}

View File

@ -189,6 +189,7 @@ mymain(void)
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-iscsi");
DO_TEST("disk-drive-network-gluster");
DO_TEST("disk-drive-network-rbd");
DO_TEST("disk-drive-network-rbd-ipv6");

View File

@ -1 +1 @@
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=gluster+tcp://example.org:6000/Volume1/Image,if=virtio,format=raw -drive 'file=gluster+unix:///Volume2/Image?socket=/path/to/sock,if=virtio,format=raw' -net none -serial none -parallel none
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=gluster://example.org:6000/Volume1/Image,if=virtio,format=raw -drive 'file=gluster+unix:///Volume2/Image?socket=/path/to/sock,if=virtio,format=raw' -net none -serial none -parallel none

View File

@ -0,0 +1 @@
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=iscsi://example.org:6000/iqn.1992-01.com.example,if=virtio,format=raw -drive file=iscsi://example.org:6000/iqn.1992-01.com.example/1,if=virtio,format=raw -net none -serial none -parallel none

View File

@ -21,6 +21,13 @@
</source>
<target dev='vda' bus='virtio'/>
</disk>
<disk type='network' device='disk'>
<driver name='qemu' type='raw'/>
<source protocol='iscsi' name='iqn.1992-01.com.example/1'>
<host name='example.org' port='6000'/>
</source>
<target dev='vdb' bus='virtio'/>
</disk>
<controller type='usb' index='0'/>
<memballoon model='virtio'/>
</devices>

View File

@ -1,5 +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 \
-drive 'file=nbd://[::1]:6000/bar,if=virtio,format=raw' -net none \
-serial none -parallel none

View File

@ -1,5 +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 \
-drive 'file=nbd://[::1]:6000,if=virtio,format=raw' -net none \
-serial none -parallel none

View File

@ -501,6 +501,8 @@ mymain(void)
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-iscsi",
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-network-gluster",
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-network-rbd",