conf: Wire up the vhost-scsi connection from/to XML

With the QEMU components in place, provide the XML parsing to
invoke that code when given the following XML snippet:

    <hostdev mode='subsystem' type='scsi_host'>
      <source protocol='vhost' wwpn='naa.501234567890abcd'/>
    </hostdev>

An optional address element can be specified within the hostdev
(pick CCW or PCI as necessary):

    <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0625'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>

Add basic vhost-scsi tests which were cloned from hostdev-scsi-virtio-scsi
in both xml2argv and xml2xml. Added ones for both vhost-scsi-ccw and
vhost-scsi-pci since the syntaxes are slightly different between them.

Also adjusted the docs to describe the changes.

Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
This commit is contained in:
Eric Farman 2016-11-21 22:58:20 -05:00 committed by John Ferlan
parent 81a206f52b
commit ae5d30a0b3
13 changed files with 290 additions and 2 deletions

View File

@ -3694,6 +3694,17 @@
&lt;/devices&gt;
...</pre>
<p>or:</p>
<pre>
...
&lt;devices&gt;
&lt;hostdev mode='subsystem' type='scsi_host'&gt;
&lt;source protocol='vhost' wwpn='naa.50014057667280d8'/&gt;
&lt;/hostdev&gt;
&lt;/devices&gt;
...</pre>
<dl>
<dt><code>hostdev</code></dt>
<dd>The <code>hostdev</code> element is the main container for describing
@ -3732,6 +3743,12 @@
If a disk lun in the domain already has the rawio capability,
then this setting not required.
</dd>
<dt><code>scsi_host</code></dt>
<dd><span class="since">since 2.5.0</span>For SCSI devices, user
is responsible to make sure the device is not used by host. This
<code>type</code> passes all LUNs presented by a single HBA to
the guest.
</dd>
</dl>
<p>
Note: The <code>managed</code> attribute is only used with PCI devices
@ -3795,6 +3812,13 @@
credentials to the iSCSI server.
</p>
</dd>
<dt><code>scsi_host</code></dt>
<dd><span class="since">Since 2.5.0</span>, multiple LUNs behind a
single SCSI HBA are described by a <code>protocol</code>
attribute set to "vhost" and a <code>wwpn</code> attribute that
is the vhost_scsi wwpn (16 hexadecimal digits with a prefix of
"naa.") established in the host configfs.
</dd>
</dl>
</dd>
<dt><code>vendor</code>, <code>product</code></dt>

View File

@ -27,6 +27,10 @@
libvirtd via SSH, using the libssh library; for example:
<tt>qemu+libssh://<i>server</i>/system</tt>
</li>
<li>vhost-scsi: Add support scsi_host hostdev passthrough<br/>
Add the capability to pass through a scsi_host HBA and the
associated LUNs to the guest.
</li>
</ul>
</li>
<li><strong>Improvements</strong>

View File

@ -3974,6 +3974,7 @@
<ref name="hostdevsubsyspci"/>
<ref name="hostdevsubsysusb"/>
<ref name="hostdevsubsysscsi"/>
<ref name="hostdevsubsyshost"/>
</choice>
</define>
@ -4102,6 +4103,28 @@
</element>
</define>
<define name="hostdevsubsyshost">
<attribute name="type">
<value>scsi_host</value>
</attribute>
<element name="source">
<choice>
<group>
<attribute name="protocol">
<choice>
<value>vhost</value> <!-- vhost, required -->
</choice>
</attribute>
<attribute name="wwpn">
<data type="string">
<param name="pattern">(naa\.)[0-9a-fA-F]{16}</param>
</data>
</attribute>
</group>
</choice>
</element>
</define>
<define name="hostdevcapsstorage">
<attribute name="type">
<value>storage</value>

View File

@ -392,6 +392,7 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
virDomainHostdevSubsysUSBPtr usbsrc = &hostdev->source.subsys.u.usb;
virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host;
virUUIDFormat(vm->def->uuid, uuidstr);
if (!(vmname = virAuditEncode("vm", vm->def->name))) {
@ -444,6 +445,12 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
}
break;
}
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
if (VIR_STRDUP_QUIET(address, hostsrc->wwpn) < 0) {
VIR_WARN("OOM while encoding audit message");
goto cleanup;
}
break;
default:
VIR_WARN("Unexpected hostdev type while encoding audit message: %d",
hostdev->source.subsys.type);

View File

@ -2324,6 +2324,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
} else {
VIR_FREE(scsisrc->u.host.adapter);
}
} else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
VIR_FREE(hostsrc->wwpn);
}
break;
}
@ -6093,6 +6096,58 @@ virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode,
return ret;
}
static int
virDomainHostdevSubsysSCSIVHostDefParseXML(xmlNodePtr sourcenode,
virDomainHostdevDefPtr def)
{
char *protocol = NULL;
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
if (!(protocol = virXMLPropString(sourcenode, "protocol"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing scsi_host subsystem protocol"));
return -1;
}
if ((hostsrc->protocol =
virDomainHostdevSubsysSCSIHostProtocolTypeFromString(protocol)) <= 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unknown scsi_host subsystem protocol '%s'"),
protocol);
goto cleanup;
}
switch ((virDomainHostdevSubsysSCSIHostProtocolType) hostsrc->protocol) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST:
if (!(hostsrc->wwpn = virXMLPropString(sourcenode, "wwpn"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("missing vhost-scsi hostdev source wwpn"));
goto cleanup;
}
if (!STRPREFIX(hostsrc->wwpn, "naa.") ||
!virValidateWWN(hostsrc->wwpn + 4)) {
virReportError(VIR_ERR_XML_ERROR, "%s", _("malformed 'wwpn' value"));
goto cleanup;
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_NONE:
case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST:
virReportError(VIR_ERR_XML_ERROR,
_("Invalid hostdev protocol '%s'"),
virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol));
goto cleanup;
break;
}
return 0;
cleanup:
VIR_FREE(hostsrc->wwpn);
VIR_FREE(protocol);
return -1;
}
static int
virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
@ -6217,6 +6272,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
goto error;
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
if (virDomainHostdevSubsysSCSIVHostDefParseXML(sourcenode, def) < 0)
goto error;
break;
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("address type='%s' not supported in hostdev interfaces"),
@ -13022,6 +13082,15 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt,
def->shareable = true;
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
if (def->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
def->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
def->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("SCSI_host host device must use 'pci' "
"or 'ccw' address type"));
goto error;
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
break;
@ -13906,7 +13975,14 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
else
return virDomainHostdevMatchSubsysSCSIHost(a, b);
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
/* Fall through for now */
if (a->source.subsys.u.scsi_host.protocol !=
b->source.subsys.u.scsi_host.protocol)
return 0;
if (STREQ(a->source.subsys.u.scsi_host.wwpn,
b->source.subsys.u.scsi_host.wwpn))
return 1;
else
return 0;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
return 0;
}
@ -20812,9 +20888,11 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
unsigned int flags,
bool includeTypeInAddr)
{
bool closedSource = false;
virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
@ -20855,6 +20933,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
protocol, iscsisrc->path);
}
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
const char *protocol =
virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol);
closedSource = true;
virBufferAsprintf(buf, " protocol='%s' wwpn='%s'/",
protocol, hostsrc->wwpn);
}
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
@ -20908,6 +20995,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
scsihostsrc->unit);
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected hostdev type %d"),
@ -20923,7 +21012,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</source>\n");
if (!closedSource)
virBufferAddLit(buf, "</source>\n");
return 0;
}

View File

@ -0,0 +1,25 @@
LC_ALL=C \
PATH=/bin \
HOME=/home/test \
USER=test \
LOGNAME=test \
QEMU_AUDIO_DRV=none \
/usr/bin/qemu \
-name QEMUGuest2 \
-S \
-M s390-ccw \
-m 214 \
-smp 1,sockets=1,cores=1,threads=1 \
-uuid c7a5fdbd-edaf-9466-926a-d65c16db1809 \
-nographic \
-nodefaults \
-monitor unix:/tmp/lib/domain--1-QEMUGuest2/monitor.sock,server,nowait \
-no-acpi \
-boot c \
-device virtio-scsi-ccw,id=scsi0,devno=fe.0.0001 \
-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-virtio-disk0 \
-device virtio-blk-ccw,devno=fe.0.0000,drive=drive-virtio-disk0,\
id=virtio-disk0 \
-device vhost-scsi-ccw,wwpn=naa.5123456789abcde0,vhostfd=3,id=hostdev0,\
devno=fe.0.0002 \
-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0003

View File

@ -0,0 +1,34 @@
<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='s390x' machine='s390-ccw'>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='virtio'/>
<address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
</disk>
<controller type='scsi' index='0' model='virtio-scsi'>
<address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0001'/>
</controller>
<hostdev mode='subsystem' type='scsi_host' managed='no'>
<source protocol='vhost' wwpn='naa.5123456789abcde0'/>
<address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0002'/>
</hostdev>
<memballoon model='virtio'>
<address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0003'/>
</memballoon>
<panic model='s390'/>
</devices>
</domain>

View File

@ -0,0 +1,25 @@
LC_ALL=C \
PATH=/bin \
HOME=/home/test \
USER=test \
LOGNAME=test \
QEMU_AUDIO_DRV=none \
/usr/bin/qemu \
-name QEMUGuest2 \
-S \
-M pc \
-m 214 \
-smp 1,sockets=1,cores=1,threads=1 \
-uuid c7a5fdbd-edaf-9466-926a-d65c16db1809 \
-nographic \
-nodefaults \
-monitor unix:/tmp/lib/domain--1-QEMUGuest2/monitor.sock,server,nowait \
-no-acpi \
-boot c \
-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
-usb \
-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-ide0-0-0 \
-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
-device vhost-scsi-pci,wwpn=naa.5123456789abcde0,vhostfd=3,id=hostdev0,\
bus=pci.0,addr=0x5 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4

View File

@ -0,0 +1,42 @@
<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'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</controller>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<hostdev mode='subsystem' type='scsi_host' managed='no'>
<source protocol='vhost' wwpn='naa.5123456789abcde0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</hostdev>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -2034,6 +2034,12 @@ mymain(void)
DO_TEST("hostdev-scsi-virtio-iscsi-auth",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC);
DO_TEST("hostdev-scsi-vhost-scsi-ccw",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_VIRTIO_CCW);
DO_TEST("hostdev-scsi-vhost-scsi-pci",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC);
DO_TEST("mlock-on", QEMU_CAPS_REALTIME_MLOCK);
DO_TEST_FAILURE("mlock-on", NONE);

View File

@ -0,0 +1 @@
../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml

View File

@ -0,0 +1 @@
../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml

View File

@ -858,6 +858,12 @@ mymain(void)
QEMU_CAPS_DEVICE_IOH3420,
QEMU_CAPS_HDA_DUPLEX);
DO_TEST("hostdev-scsi-vhost-scsi-ccw",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_VIRTIO_CCW);
DO_TEST("hostdev-scsi-vhost-scsi-pci",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC);
DO_TEST("hostdev-scsi-lsi",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC);