Wow *that*'s not what I was trying to - ignore...
John
On 08/05/2014 07:22 PM, John Ferlan wrote:
Introduce a new structure to handle an iSCSI host device based on
the
existing virDomainHostdevSubsysSCSI by adding a "protocol='iscsi'" to
the <source/> element. The hostdev structure mimics the existing
<disk/> element for an iSCSI device (network) device. New XML is:
<hostdev mode='subsystem' type='scsi' managed='yes'>
<source protocol='iscsi' name='iqn.1992-01.com.example'>
<host name='example.org' port='3260'/>
<auth username='myname'>
<secret type='iscsi' usage='mycluster_myname'/>
</auth>
</source>
<address type='drive' controller='0' bus='0'
target='2' unit='5'/>
</hostdev>
The controller element will mimic the existing scsi_host code insomuch
as when 'lsi' and 'virtio-scsi' are used.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
Changes since v3:
* Rework RNG to match comments from review 8/8
* Move the <auth> inside the <source>
* Modify the tests and html doc to match where the <auth> is found
docs/formatdomain.html.in | 144 +++++++++++++-------
docs/schemas/domaincommon.rng | 51 ++++++-
src/conf/domain_conf.c | 150 ++++++++++++++++++---
.../qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.args | 14 ++
.../qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml | 46 +++++++
.../qemuxml2argv-hostdev-scsi-lsi-iscsi.args | 14 ++
.../qemuxml2argv-hostdev-scsi-lsi-iscsi.xml | 40 ++++++
...emuxml2argv-hostdev-scsi-virtio-iscsi-auth.args | 16 +++
...qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml | 46 +++++++
.../qemuxml2argv-hostdev-scsi-virtio-iscsi.args | 16 +++
.../qemuxml2argv-hostdev-scsi-virtio-iscsi.xml | 40 ++++++
tests/qemuxml2argvtest.c | 16 +++
tests/qemuxml2xmltest.c | 5 +
13 files changed, 529 insertions(+), 69 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.xml
create mode 100644
tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.args
create mode 100644
tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e5b1adb..8b294bd 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2824,57 +2824,107 @@
</devices>
...</pre>
+
+ <p>or:</p>
+
+<pre>
+ ...
+ <devices>
+ <hostdev mode='subsystem' type='scsi'>
+ <source protocol='iscsi'
name='iqn.2014-08.com.example:iscsi-nopool/1'>
+ <host name='example.com' port='3260'/>
+ <auth username='myuser'>
+ <secret type='iscsi' usage='libvirtiscsi'/>
+ </auth>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </hostdev>
+ </devices>
+ ...</pre>
+
<dl>
<dt><code>hostdev</code></dt>
<dd>The <code>hostdev</code> element is the main container for
describing
- host devices. For usb device passthrough <code>mode</code> is
always
- "subsystem" and <code>type</code> is "usb" for a
USB device, "pci"
- for a PCI device and "scsi" for a SCSI device. When
- <code>managed</code> is "yes" for a PCI
- device, it is detached from the host before being passed on to
- the guest, and reattached to the host after the guest exits.
- If <code>managed</code> is omitted or "no", and for USB
- devices, the user is responsible to
- call <code>virNodeDeviceDettach</code> (or <code>virsh
- nodedev-dettach</code>) before starting the guest or
- hot-plugging the device,
- and <code>virNodeDeviceReAttach</code> (or <code>virsh
- nodedev-reattach</code>) after hot-unplug or stopping the
- guest. For SCSI device, user is responsible to make sure the device
- is not used by host.
- The optional <code>sgio</code> (<span
class="since">since 1.0.6</span>)
- attribute indicates whether the kernel will filter unprivileged
- SG_IO commands for the disk, valid settings are "filtered" or
- "unfiltered". Defaults to "filtered".
+ host devices. For each device, the <code>mode</code> is always
+ "subsystem" and the <code>type</code> is one of the
following values
+ with additional attributes noted.
+ <dl>
+ <dt>usb</dt>
+ <dd>For USB devices, the user is responsible to call
+ <code>virNodeDeviceDettach</code> (or
+ <code>virsh nodedev-detach</code>) before starting the guest
+ or hot-plugging the device and
<code>virNodeDeviceReAttach</code>
+ (or <code>virsh nodedev-reattach</code>) after hot-unplug or
+ stopping the guest.
+ </dd>
+ <dt>pci</dt>
+ <dd>For PCI devices, when <code>managed</code> is
"yes" it is
+ detached from the host before being passed on to the guest
+ and reattached to the host after the guest exits. If
+ <code>managed</code> is omitted or "no", follow the
steps
+ described for a USB device to detach before starting the
+ guest or hot-plugging and reattach after stopping the guest
+ or hot-unplug.
+ </dd>
+ <dt>scsi</dt>
+ <dd>For SCSI devices, user is responsible to make sure the device
+ is not used by host. The optional <code>sgio</code>
+ (<span class="since">since 1.0.6</span>) attribute
indicates
+ whether the kernel will filter unprivileged SG_IO commands for
+ the disk, valid settings are "filtered" or
"unfiltered".
+ The default is "filtered".
+ </dd>
+ </dl>
</dd>
<dt><code>source</code></dt>
- <dd>The source element describes the device as seen from the host.
- The USB device can either be addressed by vendor / product id using the
- <code>vendor</code> and <code>product</code> elements or
by the device's
- address on the hosts using the <code>address</code> element. PCI
devices
- on the other hand can only be described by their
<code>address</code>.
- SCSI devices are described by both the <code>adapter</code> and
- <code>address</code> elements.
-
- <span class="since">Since 1.0.0</span>, the
<code>source</code> element
- of USB devices may contain <code>startupPolicy</code> attribute which
can
- be used to define policy what to do if the specified host USB device is
- not found. The attribute accepts the following values:
- <table class="top_table">
- <tr>
- <td> mandatory </td>
- <td> fail if missing for any reason (the default) </td>
- </tr>
- <tr>
- <td> requisite </td>
- <td> fail if missing on boot up,
- drop if missing on migrate/restore/revert </td>
- </tr>
- <tr>
- <td> optional </td>
- <td> drop if missing at any start attempt </td>
- </tr>
- </table>
+ <dd>The source element describes the device as seen from the host using
+ the following mechanism to describe:
+ <dl>
+ <dt>usb</dt>
+ <dd>The USB device can either be addressed by vendor / product id
+ using the <code>vendor</code> and
<code>product</code> elements
+ or by the device's address on the host using the
+ <code>address</code> element.
+ <p>
+ <span class="since">Since 1.0.0</span>, the
<code>source</code>
+ element of USB devices may contain <code>startupPolicy</code>
+ attribute which can be used to define policy what to do if the
+ specified host USB device is not found. The attribute accepts
+ the following values:
+ </p>
+ <table class="top_table">
+ <tr>
+ <td> mandatory </td>
+ <td> fail if missing for any reason (the default) </td>
+ </tr>
+ <tr>
+ <td> requisite </td>
+ <td> fail if missing on boot up,
+ drop if missing on migrate/restore/revert </td>
+ </tr>
+ <tr>
+ <td> optional </td>
+ <td> drop if missing at any start attempt </td>
+ </tr>
+ </table>
+ </dd>
+ <dt>pci</dt>
+ <dd>PCI devices can only be described by their
<code>address</code>.
+ </dd>
+ <dt>scsi</dt>
+ <dd>SCSI devices are described by both the
<code>adapter</code>
+ and <code>address</code> elements.
+ <p>
+ <span class="since">Since 1.2.8</span>, the
<code>source</code>
+ element of a SCSI device may contain the <code>protocol</code>
+ attribute. When the attribute is set to "iscsi", the host
+ device XML follows the network <a
href="#elementsDisks">disk</a>
+ device using the same <code>name</code> attribute and
optionally
+ using the <code>auth</code> element to provide the
authentication
+ credentials to the iSCSI server.
+ </p>
+ </dd>
+ </dl>
</dd>
<dt><code>vendor</code>,
<code>product</code></dt>
<dd>The <code>vendor</code> and <code>product</code>
elements each have an
@@ -3589,7 +3639,7 @@
before being passed on to the guest, and reattached to the host
after the guest exits. If <code>managed</code> is omitted or
"no",
the user is responsible to call <code>virNodeDeviceDettach</code>
- (or <code>virsh nodedev-dettach</code>) before starting the guest
+ (or <code>virsh nodedev-detach</code>) before starting the guest
or hot-plugging the device, and <code>virNodeDeviceReAttach</code>
(or <code>virsh nodedev-reattach</code>) after hot-unplug or
stopping the guest.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 11f0fd0..b7a1b6f 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3589,12 +3589,51 @@
</attribute>
</optional>
<element name="source">
- <interleave>
- <ref name="sourceinfoadapter"/>
- <element name="address">
- <ref name="scsiaddress"/>
- </element>
- </interleave>
+ <choice>
+ <group> <!-- scsi_host adapter -->
+ <optional>
+ <attribute name="protocol">
+ <choice>
+ <value>adapter</value> <!-- scsi_host, default,
optional -->
+ </choice>
+ </attribute>
+ </optional>
+ <interleave>
+ <ref name="sourceinfoadapter"/>
+ <element name="address">
+ <ref name="scsiaddress"/>
+ </element>
+ </interleave>
+ </group>
+ <group> <!-- iscsi adapter -->
+ <attribute name="protocol">
+ <choice>
+ <value>iscsi</value> <!-- iscsi, required -->
+ </choice>
+ </attribute>
+ <attribute name="name">
+ <text/>
+ </attribute>
+ <interleave>
+ <oneOrMore>
+ <element name='host'>
+ <attribute name='name'>
+ <text/>
+ </attribute>
+ <optional>
+ <attribute name='port'>
+ <ref name="PortNumber"/>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </oneOrMore>
+ <optional>
+ <ref name='diskAuth'/>
+ </optional>
+ </interleave>
+ </group>
+ </choice>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 358afae..d87ca24 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -597,6 +597,11 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend,
"vfio",
"xen")
+VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol,
+ VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST,
+ "adapter",
+ "iscsi")
+
VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
"storage",
"misc",
@@ -4213,10 +4218,96 @@ virDomainHostdevSubsysSCSIHostDefParseXML(xmlNodePtr sourcenode,
}
static int
+virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode,
+ virDomainHostdevSubsysSCSIPtr def)
+{
+ int ret = -1;
+ int auth_secret_usage = -1;
+ xmlNodePtr cur;
+ virStorageAuthDefPtr authdef = NULL;
+ virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &def->u.iscsi;
+
+ /* Similar to virDomainDiskSourceParse for a VIR_STORAGE_TYPE_NETWORK */
+
+ if (!(iscsisrc->path = virXMLPropString(sourcenode, "name"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing iSCSI hostdev source path name"));
+ goto cleanup;
+ }
+
+ if (virDomainStorageHostParse(sourcenode, &iscsisrc->hosts,
+ &iscsisrc->nhosts) < 0)
+ goto cleanup;
+
+ if (iscsisrc->nhosts < 1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing the host address for the iSCSI hostdev"));
+ goto cleanup;
+ }
+ if (iscsisrc->nhosts > 1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("only one source host address may be specified "
+ "for the iSCSI hostdev"));
+ goto cleanup;
+ }
+
+ cur = sourcenode->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(cur->name, BAD_CAST "auth")) {
+ if (!(authdef = virStorageAuthDefParse(sourcenode->doc, cur)))
+ goto cleanup;
+ if ((auth_secret_usage =
+ virSecretUsageTypeFromString(authdef->secrettype)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("invalid secret type %s"),
+ authdef->secrettype);
+ goto cleanup;
+ }
+ if (auth_secret_usage != VIR_SECRET_USAGE_TYPE_ISCSI) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("hostdev invalid secret type '%s'"),
+ authdef->secrettype);
+ goto cleanup;
+ }
+ iscsisrc->auth = authdef;
+ authdef = NULL;
+ }
+ cur = cur->next;
+ }
+ ret = 0;
+
+ cleanup:
+ virStorageAuthDefFree(authdef);
+ return ret;
+}
+
+static int
virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode,
virDomainHostdevSubsysSCSIPtr scsisrc)
{
- return virDomainHostdevSubsysSCSIHostDefParseXML(sourcenode, scsisrc);
+ char *protocol = NULL;
+ int ret = -1;
+
+ if ((protocol = virXMLPropString(sourcenode, "protocol"))) {
+ scsisrc->protocol =
+ virDomainHostdevSubsysSCSIProtocolTypeFromString(protocol);
+ if (scsisrc->protocol < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown SCSI subsystem protocol '%s'"),
+ protocol);
+ goto cleanup;
+ }
+ }
+
+ if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
+ ret = virDomainHostdevSubsysSCSIiSCSIDefParseXML(sourcenode, scsisrc);
+ else
+ ret = virDomainHostdevSubsysSCSIHostDefParseXML(sourcenode, scsisrc);
+
+ cleanup:
+ VIR_FREE(protocol);
+ return ret;
}
/* Check if a drive type address $controller:0:0:$unit is already
@@ -15761,6 +15852,7 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
+ virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
@@ -15777,17 +15869,27 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
}
virBufferAddLit(buf, "<source");
- if (def->startupPolicy) {
- const char *policy;
- policy = virDomainStartupPolicyTypeToString(def->startupPolicy);
- virBufferAsprintf(buf, " startupPolicy='%s'", policy);
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+ if (def->startupPolicy) {
+ const char *policy;
+ policy = virDomainStartupPolicyTypeToString(def->startupPolicy);
+ virBufferAsprintf(buf, " startupPolicy='%s'", policy);
+ }
+ if (usbsrc->autoAddress && (flags & VIR_DOMAIN_XML_MIGRATABLE))
+ virBufferAddLit(buf, " autoAddress='yes'");
+
+ if (def->missing && !(flags & VIR_DOMAIN_XML_INACTIVE))
+ virBufferAddLit(buf, " missing='yes'");
}
- if (usbsrc->autoAddress && (flags & VIR_DOMAIN_XML_MIGRATABLE))
- virBufferAddLit(buf, " autoAddress='yes'");
- if (def->missing &&
- !(flags & VIR_DOMAIN_XML_INACTIVE))
- virBufferAddLit(buf, " missing='yes'");
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
+ scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
+ const char *protocol =
+ virDomainHostdevSubsysSCSIProtocolTypeToString(scsisrc->protocol);
+
+ virBufferAsprintf(buf, " protocol='%s' name='%s'",
+ protocol, iscsisrc->path);
+ }
virBufferAddLit(buf, ">\n");
@@ -15828,12 +15930,20 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
- virBufferAsprintf(buf, "<adapter name='%s'/>\n",
- scsihostsrc->adapter);
- virBufferAsprintf(buf, "<address %sbus='%d' target='%d'
unit='%d'/>\n",
- includeTypeInAddr ? "type='scsi' " :
"",
- scsihostsrc->bus, scsihostsrc->target,
- scsihostsrc->unit);
+ if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
+ virBufferAddLit(buf, "<host");
+ virBufferEscapeString(buf, " name='%s'",
iscsisrc->hosts[0].name);
+ virBufferEscapeString(buf, " port='%s'",
iscsisrc->hosts[0].port);
+ virBufferAddLit(buf, "/>\n");
+ } else {
+ virBufferAsprintf(buf, "<adapter name='%s'/>\n",
+ scsihostsrc->adapter);
+ virBufferAsprintf(buf,
+ "<address %sbus='%d' target='%d'
unit='%d'/>\n",
+ includeTypeInAddr ? "type='scsi' " :
"",
+ scsihostsrc->bus, scsihostsrc->target,
+ scsihostsrc->unit);
+ }
break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -15842,8 +15952,16 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
return -1;
}
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
+ scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI &&
+ iscsisrc->auth) {
+ if (virStorageAuthDefFormat(buf, iscsisrc->auth) < 0)
+ return -1;
+ }
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</source>\n");
+
return 0;
}
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.args
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.args
new file mode 100644
index 0000000..6638dce
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.args
@@ -0,0 +1,14 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -nodefaults -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-device lsi,id=scsi0,bus=pci.0,addr=0x3 -usb \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=iscsi://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org\
+:3260/iqn.1992-01.com.example,if=none,format=raw,id=drive-hostdev0 \
+-device scsi-generic,bus=scsi0.0,scsi-id=4,drive=drive-hostdev0,id=hostdev0 \
+-drive file=iscsi://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org\
+:3260/iqn.1992-01.com.example/1,if=none,format=raw,id=drive-hostdev1 \
+-device scsi-generic,bus=scsi0.0,scsi-id=5,drive=drive-hostdev1,id=hostdev1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml
new file mode 100644
index 0000000..3bfded4
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi-auth.xml
@@ -0,0 +1,46 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</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/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0'/>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example'>
+ <host name='example.org' port='3260'/>
+ <auth username='myname'>
+ <secret type='iscsi' usage='mycluster_myname'/>
+ </auth>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='0' unit='4'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example/1'>
+ <host name='example.org' port='3260'/>
+ <auth username='myname'>
+ <secret type='iscsi' usage='mycluster_myname'/>
+ </auth>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='0' unit='5'/>
+ </hostdev>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.args
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.args
new file mode 100644
index 0000000..2aebe9c
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.args
@@ -0,0 +1,14 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -nodefaults -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-device lsi,id=scsi0,bus=pci.0,addr=0x3 -usb \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=iscsi://example.org:3260/iqn.1992-01.com.example,if=none,\
+format=raw,id=drive-hostdev0 \
+-device scsi-generic,bus=scsi0.0,scsi-id=4,drive=drive-hostdev0,id=hostdev0 \
+-drive file=iscsi://example.org:3260/iqn.1992-01.com.example/1,if=none,\
+format=raw,id=drive-hostdev1 \
+-device scsi-generic,bus=scsi0.0,scsi-id=5,drive=drive-hostdev1,id=hostdev1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.xml
new file mode 100644
index 0000000..8a05099
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi-iscsi.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</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/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0'/>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example'>
+ <host name='example.org' port='3260'/>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='0' unit='4'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example/1'>
+ <host name='example.org' port='3260'/>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='0' unit='5'/>
+ </hostdev>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.args
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.args
new file mode 100644
index 0000000..7fd3a00
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.args
@@ -0,0 +1,16 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -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=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=iscsi://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org\
+:3260/iqn.1992-01.com.example,if=none,format=raw,id=drive-hostdev0 \
+-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=2,lun=4,\
+drive=drive-hostdev0,id=hostdev0 \
+-drive file=iscsi://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org\
+:3260/iqn.1992-01.com.example/1,if=none,format=raw,id=drive-hostdev1 \
+-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=2,lun=5,\
+drive=drive-hostdev1,id=hostdev1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml
new file mode 100644
index 0000000..d4dba4a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth.xml
@@ -0,0 +1,46 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</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/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0'
model='virtio-scsi'/>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example'>
+ <host name='example.org' port='3260'/>
+ <auth username='myname'>
+ <secret type='iscsi' usage='mycluster_myname'/>
+ </auth>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='2' unit='4'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example/1'>
+ <host name='example.org' port='3260'/>
+ <auth username='myname'>
+ <secret type='iscsi' usage='mycluster_myname'/>
+ </auth>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='2' unit='5'/>
+ </hostdev>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.args
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.args
new file mode 100644
index 0000000..e4b6e97
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.args
@@ -0,0 +1,16 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -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=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=iscsi://example.org:3260/iqn.1992-01.com.example,if=none,\
+format=raw,id=drive-hostdev0 \
+-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=2,lun=4,\
+drive=drive-hostdev0,id=hostdev0 \
+-drive file=iscsi://example.org:3260/iqn.1992-01.com.example/1,if=none,\
+format=raw,id=drive-hostdev1 \
+-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=2,lun=5,\
+drive=drive-hostdev1,id=hostdev1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.xml
new file mode 100644
index 0000000..13c0930
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</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/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0'
model='virtio-scsi'/>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example'>
+ <host name='example.org' port='3260'/>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='2' unit='4'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='scsi' managed='yes'>
+ <source protocol='iscsi' name='iqn.1992-01.com.example/1'>
+ <host name='example.org' port='3260'/>
+ </source>
+ <address type='drive' controller='0' bus='0'
target='2' unit='5'/>
+ </hostdev>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 12ecabc..609c1bc 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1353,6 +1353,22 @@ mymain(void)
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC,
QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX);
+ DO_TEST("hostdev-scsi-lsi-iscsi", QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC);
+ DO_TEST("hostdev-scsi-lsi-iscsi-auth", QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC);
+ DO_TEST("hostdev-scsi-virtio-iscsi", QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC);
+ DO_TEST("hostdev-scsi-virtio-iscsi-auth", QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC);
DO_TEST("mlock-on", QEMU_CAPS_MLOCK);
DO_TEST_FAILURE("mlock-on", NONE);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 451dedc..7d416d0 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -361,6 +361,11 @@ mymain(void)
DO_TEST_DIFFERENT("hostdev-scsi-autogen-address");
+ DO_TEST("hostdev-scsi-lsi-iscsi");
+ DO_TEST("hostdev-scsi-lsi-iscsi-auth");
+ DO_TEST("hostdev-scsi-virtio-iscsi");
+ DO_TEST("hostdev-scsi-virtio-iscsi-auth");
+
DO_TEST_DIFFERENT("s390-defaultconsole");
DO_TEST("pcihole64");