[libvirt] [PATCH v2 0/6] libvirt support for userspace iSCSI initiator (libiscsi)

This series adds support for the libiscsi userspace initiator. Compared to v1, logical units are now specified with IQN/LUN syntax in the name attribute. Paolo Paolo Bonzini (6): qemu: add support for libiscsi qemu: support passthrough for iscsi disks domain: make port optional for network disks secret: add iscsi to possible usage types domain: parse XML for iscsi authorization credentials qemu: pass iscsi authorization credentials docs/formatdomain.html.in | 29 +++-- docs/formatsecret.html.in | 12 ++ docs/schemas/domaincommon.rng | 9 +- docs/schemas/secret.rng | 10 ++ include/libvirt/libvirt.h.in | 1 + src/conf/domain_conf.c | 38 ++++-- src/conf/secret_conf.c | 22 +++- src/conf/secret_conf.h | 1 + src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 143 +++++++++++++++++++-- src/secret/secret_driver.c | 8 ++ tests/qemuargv2xmltest.c | 1 + .../qemuxml2argv-disk-drive-network-gluster.args | 2 +- ...qemuxml2argv-disk-drive-network-iscsi-auth.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi-auth.xml | 31 +++++ .../qemuxml2argv-disk-drive-network-iscsi-lun.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi-lun.xml | 28 ++++ .../qemuxml2argv-disk-drive-network-iscsi.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi.xml | 7 + ...ml2argv-disk-drive-network-nbd-ipv6-export.args | 2 +- .../qemuxml2argv-disk-drive-network-nbd-ipv6.args | 2 +- tests/qemuxml2argvtest.c | 8 ++ tests/qemuxml2xmltest.c | 1 + 23 files changed, 315 insertions(+), 44 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.args -- 1.8.1.4

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> --- docs/formatdomain.html.in | 11 +++-- src/qemu/qemu_command.c | 57 +++++++++++++++++++++- tests/qemuargv2xmltest.c | 1 + .../qemuxml2argv-disk-drive-network-gluster.args | 2 +- .../qemuxml2argv-disk-drive-network-iscsi.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi.xml | 7 +++ ...ml2argv-disk-drive-network-nbd-ipv6-export.args | 2 +- .../qemuxml2argv-disk-drive-network-nbd-ipv6.args | 2 +- tests/qemuxml2argvtest.c | 2 + 9 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.args diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index e4ed3f7..f17b808 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -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/> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8626b62..4774650 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2391,6 +2391,31 @@ qemuParseGlusterString(virDomainDiskDefPtr def) } 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) { virDomainDiskHostDefPtr h = NULL; @@ -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; @@ -2531,6 +2562,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) { const char *transp; @@ -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; @@ -9200,6 +9248,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps, goto error; break; + case VIR_DOMAIN_DISK_PROTOCOL_ISCSI: + if (qemuParseISCSIString(disk) < 0) + goto error; + + break; } } diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index d421985..6fd1de6 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -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"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.args index 6dbb009..9d70586 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.args @@ -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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.args new file mode 100644 index 0000000..b8bc9c6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.args @@ -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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.xml index dd85032..7db3426 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.xml @@ -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> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args index a942935..1541073 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6-export.args @@ -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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args index 7cdbdd1..a28d015 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-nbd-ipv6.args @@ -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 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 44bfe67..07a423e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -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", -- 1.8.1.4

On 2013年03月21日 19:53, Paolo Bonzini wrote:
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> --- docs/formatdomain.html.in | 11 +++-- src/qemu/qemu_command.c | 57 +++++++++++++++++++++- tests/qemuargv2xmltest.c | 1 + .../qemuxml2argv-disk-drive-network-gluster.args | 2 +- .../qemuxml2argv-disk-drive-network-iscsi.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi.xml | 7 +++ ...ml2argv-disk-drive-network-nbd-ipv6-export.args | 2 +- .../qemuxml2argv-disk-drive-network-nbd-ipv6.args | 2 +- tests/qemuxml2argvtest.c | 2 + 9 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi.args
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index e4ed3f7..f17b808 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -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/> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8626b62..4774650 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2391,6 +2391,31 @@ qemuParseGlusterString(virDomainDiskDefPtr def) }
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) {
Hm, we might need to change the helpers like virStrToLong_ui to accept a NULL 4th argument to avoid the useless ("lun" here) variable. But it doesn't relate with this patch. Just small changes for the new "logical unit", previous ACK stands.

This enables usage of commands like persistent reservations. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 9 ++++++- .../qemuxml2argv-disk-drive-network-iscsi-lun.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi-lun.xml | 28 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 4 ++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 21bc615..9529265 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -156,6 +156,7 @@ virDomainDiskIoTypeToString; virDomainDiskPathByName; virDomainDiskProtocolTransportTypeFromString; virDomainDiskProtocolTransportTypeToString; +virDomainDiskProtocolTypeToString; virDomainDiskRemove; virDomainDiskRemoveByName; virDomainDiskTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4774650..313db2c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3026,7 +3026,14 @@ qemuBuildDriveDevStr(virDomainDefPtr def, bus); goto error; } - if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK) { + if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) { + if (disk->protocol != VIR_DOMAIN_DISK_PROTOCOL_ISCSI) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk device='lun' is not supported for protocol='%s'"), + virDomainDiskProtocolTypeToString(disk->protocol)); + goto error; + } + } else if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk device='lun' is not supported for type='%s'"), virDomainDiskTypeToString(disk->type)); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args new file mode 100644 index 0000000..baa7760 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args @@ -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 -nodefconfig -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive file=iscsi://example.org:3260/iqn.1992-01.com.example,if=none,id=drive-scsi0-0-0-0,format=raw -device scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml new file mode 100644 index 0000000..72ceee8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml @@ -0,0 +1,28 @@ +<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='network' device='lun'> + <driver name='qemu' type='raw'/> + <source protocol='iscsi' name='iqn.1992-01.com.example'> + <host name='example.org' port='3260'/> + </source> + <target dev='sda' bus='scsi'/> + </disk> + <controller type='usb' index='0'/> + <controller type='scsi' index='0' model='virtio-scsi'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 07a423e..f126fd9 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -503,6 +503,10 @@ mymain(void) 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-iscsi-lun", + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE_FORMAT, + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_VIRTIO_BLK_SG_IO, QEMU_CAPS_SCSI_BLOCK); DO_TEST("disk-drive-network-gluster", QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-network-rbd", -- 1.8.1.4

On 2013年03月21日 19:53, Paolo Bonzini wrote:
This enables usage of commands like persistent reservations.
Signed-off-by: Paolo Bonzini<pbonzini@redhat.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 9 ++++++- .../qemuxml2argv-disk-drive-network-iscsi-lun.args | 1 + .../qemuxml2argv-disk-drive-network-iscsi-lun.xml | 28 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 4 ++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 21bc615..9529265 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -156,6 +156,7 @@ virDomainDiskIoTypeToString; virDomainDiskPathByName; virDomainDiskProtocolTransportTypeFromString; virDomainDiskProtocolTransportTypeToString; +virDomainDiskProtocolTypeToString;
Not alphabetically sorted.
virDomainDiskRemove; virDomainDiskRemoveByName; virDomainDiskTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4774650..313db2c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3026,7 +3026,14 @@ qemuBuildDriveDevStr(virDomainDefPtr def, bus); goto error; } - if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK) { + if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) { + if (disk->protocol != VIR_DOMAIN_DISK_PROTOCOL_ISCSI) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk device='lun' is not supported for protocol='%s'"), + virDomainDiskProtocolTypeToString(disk->protocol)); + goto error; + } + } else if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk device='lun' is not supported for type='%s'"), virDomainDiskTypeToString(disk->type)); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args new file mode 100644 index 0000000..baa7760 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.args @@ -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 -nodefconfig -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive file=iscsi://example.org:3260/iqn.1992-01.com.example,if=none,id=drive-scsi0-0-0-0,format=raw -device scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-lun.xml
Long line, better to break. ACK.

Only sheepdog actually required it in the code, and we can use 7000 as the default---the same value that QEMU uses for the simple "sheepdog:VOLUME" syntax. With this change, the schema can be fixed to allow no port. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- docs/formatdomain.html.in | 6 ++++++ docs/schemas/domaincommon.rng | 8 +++++--- src/conf/domain_conf.c | 5 ----- src/qemu/qemu_command.c | 3 ++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index f17b808..fd33818 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1700,31 +1700,37 @@ <th> Protocol </th> <th> Meaning </th> <th> Number of hosts </th> + <th> Default port </th> </tr> <tr> <td> nbd </td> <td> a server running nbd-server </td> <td> only one </td> + <td> 10809 </td> </tr> <tr> <td> iscsi </td> <td> an iSCSI server </td> <td> only one </td> + <td> 3260 </td> </tr> <tr> <td> rbd </td> <td> monitor servers of RBD </td> <td> one or more </td> + <td> 6789 </td> </tr> <tr> <td> sheepdog </td> <td> one of the sheepdog servers (default is localhost:7000) </td> <td> zero or one </td> + <td> 7000 </td> </tr> <tr> <td> gluster </td> <td> a server running glusterd daemon </td> <td> only one </td> + <td> 24007 </td> </tr> </table> gluster supports "tcp", "rdma", "unix" as valid values for the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index c4e7b7a..4da65f8 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1114,9 +1114,11 @@ <ref name="ipAddr"/> </choice> </attribute> - <attribute name="port"> - <ref name="unsignedInt"/> - </attribute> + <optional> + <attribute name="port"> + <ref name="unsignedInt"/> + </attribute> + </optional> </group> <group> <attribute name="transport"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b06cae5..8f76e8e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4111,11 +4111,6 @@ virDomainDiskDefParseXML(virCapsPtr caps, goto error; } hosts[nhosts - 1].port = virXMLPropString(child, "port"); - if (!hosts[nhosts - 1].port) { - virReportError(VIR_ERR_XML_ERROR, - "%s", _("missing port for host")); - goto error; - } } } child = child->next; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 313db2c..5422508 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2763,7 +2763,8 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, } else { /* only one host is supported now */ virBufferAsprintf(&opt, "file=sheepdog:%s:%s:", - disk->hosts->name, disk->hosts->port); + disk->hosts->name, + disk->hosts->port ? disk->hosts->port : "7000"); virBufferEscape(&opt, ',', ",", "%s,", disk->src); } break; -- 1.8.1.4

On 2013年03月21日 19:53, Paolo Bonzini wrote:
Only sheepdog actually required it in the code, and we can use 7000 as the default---the same value that QEMU uses for the simple "sheepdog:VOLUME" syntax. With this change, the schema can be fixed to allow no port.
Signed-off-by: Paolo Bonzini<pbonzini@redhat.com> --- docs/formatdomain.html.in | 6 ++++++ docs/schemas/domaincommon.rng | 8 +++++--- src/conf/domain_conf.c | 5 ----- src/qemu/qemu_command.c | 3 ++- 4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index f17b808..fd33818 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1700,31 +1700,37 @@ <th> Protocol</th> <th> Meaning</th> <th> Number of hosts</th> +<th> Default port</th> </tr> <tr> <td> nbd</td> <td> a server running nbd-server</td> <td> only one</td> +<td> 10809</td> </tr> <tr> <td> iscsi</td> <td> an iSCSI server</td> <td> only one</td> +<td> 3260</td> </tr> <tr> <td> rbd</td> <td> monitor servers of RBD</td> <td> one or more</td> +<td> 6789</td> </tr> <tr> <td> sheepdog</td> <td> one of the sheepdog servers (default is localhost:7000)</td> <td> zero or one</td> +<td> 7000</td> </tr> <tr> <td> gluster</td> <td> a server running glusterd daemon</td> <td> only one</td> +<td> 24007</td> </tr> </table> gluster supports "tcp", "rdma", "unix" as valid values for the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index c4e7b7a..4da65f8 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1114,9 +1114,11 @@ <ref name="ipAddr"/> </choice> </attribute> -<attribute name="port"> -<ref name="unsignedInt"/> -</attribute> +<optional> +<attribute name="port"> +<ref name="unsignedInt"/> +</attribute> +</optional> </group> <group> <attribute name="transport"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b06cae5..8f76e8e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4111,11 +4111,6 @@ virDomainDiskDefParseXML(virCapsPtr caps, goto error; } hosts[nhosts - 1].port = virXMLPropString(child, "port"); - if (!hosts[nhosts - 1].port) { - virReportError(VIR_ERR_XML_ERROR, - "%s", _("missing port for host")); - goto error; - } } } child = child->next; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 313db2c..5422508 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2763,7 +2763,8 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, } else { /* only one host is supported now */ virBufferAsprintf(&opt, "file=sheepdog:%s:%s:", - disk->hosts->name, disk->hosts->port); + disk->hosts->name, + disk->hosts->port ? disk->hosts->port : "7000"); virBufferEscape(&opt, ',', ",", "%s,", disk->src); } break;
ACK

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- docs/formatsecret.html.in | 12 ++++++++++++ docs/schemas/secret.rng | 10 ++++++++++ include/libvirt/libvirt.h.in | 1 + src/conf/secret_conf.c | 22 +++++++++++++++++++++- src/conf/secret_conf.h | 1 + src/secret/secret_driver.c | 8 ++++++++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/docs/formatsecret.html.in b/docs/formatsecret.html.in index 01aff2d..c3c4a25 100644 --- a/docs/formatsecret.html.in +++ b/docs/formatsecret.html.in @@ -66,6 +66,18 @@ device</a>. <span class="since">Since 0.9.7</span>. </p> + <h3>Usage type "iscsi"</h3> + + <p> + This secret is associated with an iSCSI target for CHAP authentication. + The <code><usage type='iscsi'></code> element must contain + a single <code>target</code> element that specifies a usage name + for the secret. The iSCSI secret can then be used by UUID or by + this usage name via the <code><auth></code> element of + a <a href="domain.html#elementsDisks">disk + device</a>. <span class="since">Since 1.0.4</span>. + </p> + <h2><a name="example">Example</a></h2> <pre> diff --git a/docs/schemas/secret.rng b/docs/schemas/secret.rng index e49bd5a..d7b8f83 100644 --- a/docs/schemas/secret.rng +++ b/docs/schemas/secret.rng @@ -41,6 +41,7 @@ <choice> <ref name='usagevolume'/> <ref name='usageceph'/> + <ref name='usageiscsi'/> <!-- More choices later --> </choice> </element> @@ -67,4 +68,13 @@ </element> </define> + <define name='usageiscsi'> + <attribute name='type'> + <value>iscsi</value> + </attribute> + <element name='target'> + <ref name='genericName'/> + </element> + </define> + </grammar> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index f6a7aff..45b5638 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -3649,6 +3649,7 @@ typedef enum { VIR_SECRET_USAGE_TYPE_NONE = 0, VIR_SECRET_USAGE_TYPE_VOLUME = 1, VIR_SECRET_USAGE_TYPE_CEPH = 2, + VIR_SECRET_USAGE_TYPE_ISCSI = 3, #ifdef VIR_ENUM_SENTINELS VIR_SECRET_USAGE_TYPE_LAST diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c index 891af65..06b9bb2 100644 --- a/src/conf/secret_conf.c +++ b/src/conf/secret_conf.c @@ -36,7 +36,7 @@ #define VIR_FROM_THIS VIR_FROM_SECRET VIR_ENUM_IMPL(virSecretUsageType, VIR_SECRET_USAGE_TYPE_LAST, - "none", "volume", "ceph") + "none", "volume", "ceph", "iscsi") void virSecretDefFree(virSecretDefPtr def) @@ -57,6 +57,10 @@ virSecretDefFree(virSecretDefPtr def) VIR_FREE(def->usage.ceph); break; + case VIR_SECRET_USAGE_TYPE_ISCSI: + VIR_FREE(def->usage.target); + break; + default: VIR_ERROR(_("unexpected secret usage type %d"), def->usage_type); break; @@ -108,6 +112,15 @@ virSecretDefParseUsage(xmlXPathContextPtr ctxt, } break; + case VIR_SECRET_USAGE_TYPE_ISCSI: + def->usage.target = virXPathString("string(./usage/target)", ctxt); + if (!def->usage.target) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Ceph usage specified, but target is missing")); + return -1; + } + break; + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected secret usage type %d"), @@ -262,6 +275,13 @@ virSecretDefFormatUsage(virBufferPtr buf, } break; + case VIR_SECRET_USAGE_TYPE_ISCSI: + if (def->usage.target != NULL) { + virBufferEscapeString(buf, " <target>%s</target>\n", + def->usage.target); + } + break; + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected secret usage type %d"), diff --git a/src/conf/secret_conf.h b/src/conf/secret_conf.h index 6079d5b..53517f9 100644 --- a/src/conf/secret_conf.h +++ b/src/conf/secret_conf.h @@ -39,6 +39,7 @@ struct _virSecretDef { union { char *volume; /* May be NULL */ char *ceph; + char *target; } usage; }; diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index 5be33b9..c577817 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -149,6 +149,11 @@ secretFindByUsage(virSecretDriverStatePtr driver, int usageType, const char *usa if (STREQ(s->def->usage.ceph, usageID)) return s; break; + + case VIR_SECRET_USAGE_TYPE_ISCSI: + if (STREQ(s->def->usage.target, usageID)) + return s; + break; } } return NULL; @@ -614,6 +619,9 @@ secretUsageIDForDef(virSecretDefPtr def) case VIR_SECRET_USAGE_TYPE_CEPH: return def->usage.ceph; + case VIR_SECRET_USAGE_TYPE_ISCSI: + return def->usage.target; + default: return NULL; } -- 1.8.1.4

On 2013年03月21日 19:53, Paolo Bonzini wrote:
Signed-off-by: Paolo Bonzini<pbonzini@redhat.com> --- docs/formatsecret.html.in | 12 ++++++++++++ docs/schemas/secret.rng | 10 ++++++++++ include/libvirt/libvirt.h.in | 1 + src/conf/secret_conf.c | 22 +++++++++++++++++++++- src/conf/secret_conf.h | 1 + src/secret/secret_driver.c | 8 ++++++++ 6 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/docs/formatsecret.html.in b/docs/formatsecret.html.in index 01aff2d..c3c4a25 100644 --- a/docs/formatsecret.html.in +++ b/docs/formatsecret.html.in @@ -66,6 +66,18 @@ device</a>.<span class="since">Since 0.9.7</span>. </p>
+<h3>Usage type "iscsi"</h3> + +<p> + This secret is associated with an iSCSI target for CHAP authentication. + The<code><usage type='iscsi'></code> element must contain + a single<code>target</code> element that specifies a usage name + for the secret. The iSCSI secret can then be used by UUID or by + this usage name via the<code><auth></code> element of + a<a href="domain.html#elementsDisks">disk + device</a>.<span class="since">Since 1.0.4</span>. +</p> + <h2><a name="example">Example</a></h2>
<pre> diff --git a/docs/schemas/secret.rng b/docs/schemas/secret.rng index e49bd5a..d7b8f83 100644 --- a/docs/schemas/secret.rng +++ b/docs/schemas/secret.rng @@ -41,6 +41,7 @@ <choice> <ref name='usagevolume'/> <ref name='usageceph'/> +<ref name='usageiscsi'/> <!-- More choices later --> </choice> </element> @@ -67,4 +68,13 @@ </element> </define>
+<define name='usageiscsi'> +<attribute name='type'> +<value>iscsi</value> +</attribute> +<element name='target'> +<ref name='genericName'/> +</element> +</define> + </grammar> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index f6a7aff..45b5638 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -3649,6 +3649,7 @@ typedef enum { VIR_SECRET_USAGE_TYPE_NONE = 0, VIR_SECRET_USAGE_TYPE_VOLUME = 1, VIR_SECRET_USAGE_TYPE_CEPH = 2, + VIR_SECRET_USAGE_TYPE_ISCSI = 3,
#ifdef VIR_ENUM_SENTINELS VIR_SECRET_USAGE_TYPE_LAST diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c index 891af65..06b9bb2 100644 --- a/src/conf/secret_conf.c +++ b/src/conf/secret_conf.c @@ -36,7 +36,7 @@ #define VIR_FROM_THIS VIR_FROM_SECRET
VIR_ENUM_IMPL(virSecretUsageType, VIR_SECRET_USAGE_TYPE_LAST, - "none", "volume", "ceph") + "none", "volume", "ceph", "iscsi")
void virSecretDefFree(virSecretDefPtr def) @@ -57,6 +57,10 @@ virSecretDefFree(virSecretDefPtr def) VIR_FREE(def->usage.ceph); break;
+ case VIR_SECRET_USAGE_TYPE_ISCSI: + VIR_FREE(def->usage.target); + break; + default: VIR_ERROR(_("unexpected secret usage type %d"), def->usage_type); break; @@ -108,6 +112,15 @@ virSecretDefParseUsage(xmlXPathContextPtr ctxt, } break;
+ case VIR_SECRET_USAGE_TYPE_ISCSI: + def->usage.target = virXPathString("string(./usage/target)", ctxt); + if (!def->usage.target) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Ceph usage specified, but target is missing"));
s/Ceph/iSCSI/, ACK with this fixed.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- docs/formatdomain.html.in | 12 ++++---- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 33 ++++++++++++++++------ .../qemuxml2argv-disk-drive-network-iscsi-auth.xml | 31 ++++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 5 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fd33818..c2cf75f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1768,12 +1768,12 @@ holds the actual password or other credentials (the domain XML intentionally does not expose the password, only the reference to the object that does manage the password). For now, the - only known secret <code>type</code> is "ceph", for Ceph RBD - network sources, and requires either an - attribute <code>uuid</code> with the UUID of the Ceph secret - object, or an attribute <code>usage</code> with the name - associated with the Ceph secret - object. <span class="since">libvirt 0.9.7</span> + known secret <code>type</code>s are "ceph", for Ceph RBD + network sources, and "iscsi", for CHAP authentication of iSCSI + targets. Both require either a <code>uuid</code> attribute + with the UUID of the secret object, or a <code>usage</code> + attribute matching the key that was specified in the + secret object. <span class="since">libvirt 0.9.7</span> </dd> <dt><code>geometry</code></dt> <dd>The optional <code>geometry</code> element provides the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4da65f8..fae5c0d 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3642,6 +3642,7 @@ <attribute name='type'> <choice> <value>ceph</value> + <value>iscsi</value> </choice> </attribute> <choice> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8f76e8e..159a23d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3992,6 +3992,8 @@ virDomainDiskDefParseXML(virCapsPtr caps, char *wwn = NULL; char *vendor = NULL; char *product = NULL; + int expected_secret_usage = -1; + int auth_secret_usage = -1; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -4029,7 +4031,6 @@ virDomainDiskDefParseXML(virCapsPtr caps, if (cur->type == XML_ELEMENT_NODE) { if (!source && !hosts && xmlStrEqual(cur->name, BAD_CAST "source")) { - sourceNode = cur; switch (def->type) { @@ -4057,6 +4058,11 @@ virDomainDiskDefParseXML(virCapsPtr caps, protocol); goto error; } + if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_ISCSI) { + expected_secret_usage = VIR_SECRET_USAGE_TYPE_ISCSI; + } else if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) { + expected_secret_usage = VIR_SECRET_USAGE_TYPE_CEPH; + } if (!(source = virXMLPropString(cur, "name")) && def->protocol != VIR_DOMAIN_DISK_PROTOCOL_NBD) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -4242,8 +4248,9 @@ virDomainDiskDefParseXML(virCapsPtr caps, _("missing type for secret")); goto error; } - if (virSecretUsageTypeTypeFromString(usageType) != - VIR_SECRET_USAGE_TYPE_CEPH) { + auth_secret_usage = + virSecretUsageTypeTypeFromString(usageType); + if (auth_secret_usage < 0) { virReportError(VIR_ERR_XML_ERROR, _("invalid secret type %s"), usageType); @@ -4393,6 +4400,13 @@ virDomainDiskDefParseXML(virCapsPtr caps, cur = cur->next; } + if (auth_secret_usage != -1 && auth_secret_usage != expected_secret_usage) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid secret type '%s'"), + virSecretUsageTypeTypeToString(auth_secret_usage)); + goto error; + } + device = virXMLPropString(node, "device"); if (device) { if ((def->device = virDomainDiskDeviceTypeFromString(device)) < 0) { @@ -12787,15 +12801,18 @@ virDomainDiskDefFormat(virBufferPtr buf, if (def->auth.username) { virBufferEscapeString(buf, " <auth username='%s'>\n", def->auth.username); + if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_ISCSI) { + virBufferAsprintf(buf, " <secret type='iscsi'"); + } else if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) { + virBufferAsprintf(buf, " <secret type='ceph'"); + } + if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) { virUUIDFormat(def->auth.secret.uuid, uuidstr); - virBufferAsprintf(buf, - " <secret type='ceph' uuid='%s'/>\n", - uuidstr); + virBufferAsprintf(buf, " uuid='%s'/>\n", uuidstr); } if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE) { - virBufferEscapeString(buf, - " <secret type='ceph' usage='%s'/>\n", + virBufferEscapeString(buf, " usage='%s'/>\n", def->auth.secret.usage); } virBufferAddLit(buf, " </auth>\n"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml new file mode 100644 index 0000000..acaa503 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml @@ -0,0 +1,31 @@ +<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='network' device='disk'> + <driver name='qemu' type='raw'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + <source protocol='iscsi' name='iqn.1992-01.com.example'> + <host name='example.org'/> + </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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 41613ea..899414d 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -175,6 +175,7 @@ mymain(void) 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-iscsi-auth"); DO_TEST("disk-scsi-device"); DO_TEST("disk-scsi-vscsi"); DO_TEST("disk-scsi-virtio-scsi"); -- 1.8.1.4

On 2013年03月21日 19:53, Paolo Bonzini wrote:
Signed-off-by: Paolo Bonzini<pbonzini@redhat.com> --- docs/formatdomain.html.in | 12 ++++---- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 33 ++++++++++++++++------ .../qemuxml2argv-disk-drive-network-iscsi-auth.xml | 31 ++++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 5 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fd33818..c2cf75f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1768,12 +1768,12 @@ holds the actual password or other credentials (the domain XML intentionally does not expose the password, only the reference to the object that does manage the password). For now, the - only known secret<code>type</code> is "ceph", for Ceph RBD - network sources, and requires either an - attribute<code>uuid</code> with the UUID of the Ceph secret - object, or an attribute<code>usage</code> with the name - associated with the Ceph secret - object.<span class="since">libvirt 0.9.7</span> + known secret<code>type</code>s are "ceph", for Ceph RBD + network sources, and "iscsi", for CHAP authentication of iSCSI + targets. Both require either a<code>uuid</code> attribute + with the UUID of the secret object, or a<code>usage</code> + attribute matching the key that was specified in the + secret object.<span class="since">libvirt 0.9.7</span> </dd> <dt><code>geometry</code></dt> <dd>The optional<code>geometry</code> element provides the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4da65f8..fae5c0d 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3642,6 +3642,7 @@ <attribute name='type'> <choice> <value>ceph</value> +<value>iscsi</value> </choice> </attribute> <choice> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8f76e8e..159a23d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3992,6 +3992,8 @@ virDomainDiskDefParseXML(virCapsPtr caps, char *wwn = NULL; char *vendor = NULL; char *product = NULL; + int expected_secret_usage = -1; + int auth_secret_usage = -1;
if (VIR_ALLOC(def)< 0) { virReportOOMError(); @@ -4029,7 +4031,6 @@ virDomainDiskDefParseXML(virCapsPtr caps, if (cur->type == XML_ELEMENT_NODE) { if (!source&& !hosts&& xmlStrEqual(cur->name, BAD_CAST "source")) { - sourceNode = cur;
switch (def->type) { @@ -4057,6 +4058,11 @@ virDomainDiskDefParseXML(virCapsPtr caps, protocol); goto error; } + if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_ISCSI) { + expected_secret_usage = VIR_SECRET_USAGE_TYPE_ISCSI; + } else if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) { + expected_secret_usage = VIR_SECRET_USAGE_TYPE_CEPH; + } if (!(source = virXMLPropString(cur, "name"))&& def->protocol != VIR_DOMAIN_DISK_PROTOCOL_NBD) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -4242,8 +4248,9 @@ virDomainDiskDefParseXML(virCapsPtr caps, _("missing type for secret")); goto error; } - if (virSecretUsageTypeTypeFromString(usageType) != - VIR_SECRET_USAGE_TYPE_CEPH) { + auth_secret_usage = + virSecretUsageTypeTypeFromString(usageType); + if (auth_secret_usage< 0) { virReportError(VIR_ERR_XML_ERROR, _("invalid secret type %s"), usageType); @@ -4393,6 +4400,13 @@ virDomainDiskDefParseXML(virCapsPtr caps, cur = cur->next; }
+ if (auth_secret_usage != -1&& auth_secret_usage != expected_secret_usage) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid secret type '%s'"), + virSecretUsageTypeTypeToString(auth_secret_usage)); + goto error; + } + device = virXMLPropString(node, "device"); if (device) { if ((def->device = virDomainDiskDeviceTypeFromString(device))< 0) { @@ -12787,15 +12801,18 @@ virDomainDiskDefFormat(virBufferPtr buf, if (def->auth.username) { virBufferEscapeString(buf, "<auth username='%s'>\n", def->auth.username); + if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_ISCSI) { + virBufferAsprintf(buf, "<secret type='iscsi'"); + } else if (def->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) { + virBufferAsprintf(buf, "<secret type='ceph'"); + } + if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) { virUUIDFormat(def->auth.secret.uuid, uuidstr); - virBufferAsprintf(buf, - "<secret type='ceph' uuid='%s'/>\n", - uuidstr); + virBufferAsprintf(buf, " uuid='%s'/>\n", uuidstr); } if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE) { - virBufferEscapeString(buf, - "<secret type='ceph' usage='%s'/>\n", + virBufferEscapeString(buf, " usage='%s'/>\n", def->auth.secret.usage); } virBufferAddLit(buf, "</auth>\n"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml new file mode 100644 index 0000000..acaa503 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.xml @@ -0,0 +1,31 @@ +<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='network' device='disk'> +<driver name='qemu' type='raw'/> +<auth username='myname'> +<secret type='iscsi' usage='mycluster_myname'/> +</auth> +<source protocol='iscsi' name='iqn.1992-01.com.example'> +<host name='example.org'/> +</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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 41613ea..899414d 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -175,6 +175,7 @@ mymain(void) 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-iscsi-auth"); DO_TEST("disk-scsi-device"); DO_TEST("disk-scsi-vscsi"); DO_TEST("disk-scsi-virtio-scsi");
ACK

A better way to do this would be to use a configuration file like [iscsi "target-name"] user = name password = pwd and pass it via -readconfig. This would remove the username and password from the "ps" output. For now, however, keep this solution. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- src/qemu/qemu_command.c | 80 ++++++++++++++++++---- ...qemuxml2argv-disk-drive-network-iscsi-auth.args | 1 + tests/qemuxml2argvtest.c | 2 + 3 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5422508..006f83d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2134,8 +2134,8 @@ qemuBuildRBDString(virConnectPtr conn, VIR_FREE(base64); } else { virReportError(VIR_ERR_INTERNAL_ERROR, - _("rbd username '%s' specified but secret not found"), - disk->auth.username); + _("%s username '%s' specified but secret not found"), + "rbd", disk->auth.username); goto error; } } else { @@ -2303,6 +2303,7 @@ qemuParseDriveURIString(virDomainDiskDefPtr def, virURIPtr uri, char *transp = NULL; char *sock = NULL; char *volimg = NULL; + char *secret = NULL; if (VIR_ALLOC(def->hosts) < 0) goto no_memory; @@ -2363,6 +2364,16 @@ qemuParseDriveURIString(virDomainDiskDefPtr def, virURIPtr uri, def->src = NULL; } + if (uri->user) { + secret = strchr(uri->user, ':'); + if (secret) + *secret = '\0'; + + def->auth.username = strdup(uri->user); + if (!def->auth.username) + goto no_memory; + } + def->nhosts = 1; ret = 0; @@ -2486,14 +2497,20 @@ error: } static int -qemuBuildDriveURIString(virDomainDiskDefPtr disk, virBufferPtr opt, - const char *scheme) +qemuBuildDriveURIString(virConnectPtr conn, + virDomainDiskDefPtr disk, virBufferPtr opt, + const char *scheme, virSecretUsageType secretType) { int ret = -1; int port = 0; + virSecretPtr sec = NULL; + char *secret = NULL; + size_t secret_size; + char *tmpscheme = NULL; char *volimg = NULL; char *sock = NULL; + char *user = NULL; char *builturi = NULL; const char *transp = NULL; virURI uri = { @@ -2529,8 +2546,42 @@ qemuBuildDriveURIString(virDomainDiskDefPtr disk, virBufferPtr opt, virAsprintf(&sock, "socket=%s", disk->hosts->socket) < 0) goto no_memory; + if (disk->auth.username && secretType != VIR_SECRET_USAGE_TYPE_NONE) { + /* look up secret */ + switch (disk->auth.secretType) { + case VIR_DOMAIN_DISK_SECRET_TYPE_UUID: + sec = virSecretLookupByUUID(conn, + disk->auth.secret.uuid); + break; + case VIR_DOMAIN_DISK_SECRET_TYPE_USAGE: + sec = virSecretLookupByUsage(conn, secretType, + disk->auth.secret.usage); + break; + } + + if (sec) { + secret = (char *)conn->secretDriver->getValue(sec, &secret_size, 0, + VIR_SECRET_GET_VALUE_INTERNAL_CALL); + if (secret == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get the value of the secret for username %s"), + disk->auth.username); + ret = -1; + goto cleanup; + } + if (virAsprintf(&user, "%s:%s", disk->auth.username, secret) < 0) + goto no_memory; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%s username '%s' specified but secret not found"), + scheme, disk->auth.username); + ret = -1; + goto cleanup; + } + } uri.scheme = tmpscheme; /* gluster+<transport> */ uri.server = disk->hosts->name; + uri.user = user; uri.port = port; uri.path = volimg; uri.query = sock; @@ -2554,21 +2605,23 @@ no_memory: } static int -qemuBuildGlusterString(virDomainDiskDefPtr disk, virBufferPtr opt) +qemuBuildGlusterString(virConnectPtr conn, virDomainDiskDefPtr disk, virBufferPtr opt) { - return qemuBuildDriveURIString(disk, opt, "gluster"); + return qemuBuildDriveURIString(conn, disk, opt, "gluster", + VIR_SECRET_USAGE_TYPE_NONE); } #define QEMU_DEFAULT_NBD_PORT "10809" static int -qemuBuildISCSIString(virDomainDiskDefPtr disk, virBufferPtr opt) +qemuBuildISCSIString(virConnectPtr conn, virDomainDiskDefPtr disk, virBufferPtr opt) { - return qemuBuildDriveURIString(disk, opt, "iscsi"); + return qemuBuildDriveURIString(conn, disk, opt, "iscsi", + VIR_SECRET_USAGE_TYPE_ISCSI); } static int -qemuBuildNBDString(virDomainDiskDefPtr disk, virBufferPtr opt) +qemuBuildNBDString(virConnectPtr conn, virDomainDiskDefPtr disk, virBufferPtr opt) { const char *transp; @@ -2583,7 +2636,8 @@ qemuBuildNBDString(virDomainDiskDefPtr disk, virBufferPtr opt) && !disk->hosts->name) || (disk->hosts->transport == VIR_DOMAIN_DISK_PROTO_TRANS_UNIX && disk->hosts->socket && disk->hosts->socket[0] != '/')) - return qemuBuildDriveURIString(disk, opt, "nbd"); + return qemuBuildDriveURIString(conn, disk, opt, "nbd", + VIR_SECRET_USAGE_TYPE_NONE); virBufferAddLit(opt, "file=nbd:"); @@ -2735,7 +2789,7 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, } else if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) { switch (disk->protocol) { case VIR_DOMAIN_DISK_PROTOCOL_NBD: - if (qemuBuildNBDString(disk, &opt) < 0) + if (qemuBuildNBDString(conn, disk, &opt) < 0) goto error; virBufferAddChar(&opt, ','); break; @@ -2746,12 +2800,12 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, virBufferAddChar(&opt, ','); break; case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER: - if (qemuBuildGlusterString(disk, &opt) < 0) + if (qemuBuildGlusterString(conn, disk, &opt) < 0) goto error; virBufferAddChar(&opt, ','); break; case VIR_DOMAIN_DISK_PROTOCOL_ISCSI: - if (qemuBuildISCSIString(disk, &opt) < 0) + if (qemuBuildISCSIString(conn, disk, &opt) < 0) goto error; virBufferAddChar(&opt, ','); break; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.args new file mode 100644 index 0000000..fd2660a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth.args @@ -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://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org/iqn.1992-01.com.example,if=virtio,format=raw -net none -serial none -parallel none diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f126fd9..5e7adf5 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -503,6 +503,8 @@ mymain(void) 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-iscsi-auth", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("disk-drive-network-iscsi-lun", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE_FORMAT, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI, -- 1.8.1.4

On 2013年03月21日 19:53, Paolo Bonzini wrote:
A better way to do this would be to use a configuration file like
[iscsi "target-name"] user = name password = pwd
and pass it via -readconfig. This would remove the username and password from the "ps" output. For now, however, keep this solution.
Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
ACK

On Thu, Mar 21, 2013 at 12:53:48PM +0100, Paolo Bonzini wrote:
This series adds support for the libiscsi userspace initiator. Compared to v1, logical units are now specified with IQN/LUN syntax in the name attribute.
ACK to all 6 Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 2013年03月21日 20:46, Daniel P. Berrange wrote:
On Thu, Mar 21, 2013 at 12:53:48PM +0100, Paolo Bonzini wrote:
This series adds support for the libiscsi userspace initiator. Compared to v1, logical units are now specified with IQN/LUN syntax in the name attribute.
ACK to all 6
Daniel
Got conflicts when trying to push the patches, run out of time today, going to push tomorrow if Eric have no time to do it yet. Osier

On 2013年03月21日 22:43, Osier Yang wrote:
On 2013年03月21日 20:46, Daniel P. Berrange wrote:
On Thu, Mar 21, 2013 at 12:53:48PM +0100, Paolo Bonzini wrote:
This series adds support for the libiscsi userspace initiator. Compared to v1, logical units are now specified with IQN/LUN syntax in the name attribute.
ACK to all 6
Daniel
Got conflicts when trying to push the patches, run out of time today, going to push tomorrow if Eric have no time to do it yet.
Pushed with the few small nits fixed.
participants (3)
-
Daniel P. Berrange
-
Osier Yang
-
Paolo Bonzini