From ae5d30a0b30677d528315e2935c776afdbfc3a5d Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Mon, 21 Nov 2016 22:58:20 -0500 Subject: [PATCH] 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: An optional address element can be specified within the hostdev (pick CCW or PCI as necessary):
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 Reviewed-by: Boris Fiuczynski --- docs/formatdomain.html.in | 24 +++++ docs/news.html.in | 4 + docs/schemas/domaincommon.rng | 23 +++++ src/conf/domain_audit.c | 7 ++ src/conf/domain_conf.c | 94 ++++++++++++++++++- ...uxml2argv-hostdev-scsi-vhost-scsi-ccw.args | 25 +++++ ...muxml2argv-hostdev-scsi-vhost-scsi-ccw.xml | 34 +++++++ ...uxml2argv-hostdev-scsi-vhost-scsi-pci.args | 25 +++++ ...muxml2argv-hostdev-scsi-vhost-scsi-pci.xml | 42 +++++++++ tests/qemuxml2argvtest.c | 6 ++ ...xml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml | 1 + ...xml2xmlout-hostdev-scsi-vhost-scsi-pci.xml | 1 + tests/qemuxml2xmltest.c | 6 ++ 13 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4e40aa1484..6bd02ccdd5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3694,6 +3694,17 @@ </devices> ... +

or:

+ +
+  ...
+  <devices>
+    <hostdev mode='subsystem' type='scsi_host'>
+      <source protocol='vhost' wwpn='naa.50014057667280d8'/>
+    </hostdev>
+  </devices>
+  ...
+
hostdev
The hostdev 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.
+
scsi_host
+
since 2.5.0For SCSI devices, user + is responsible to make sure the device is not used by host. This + type passes all LUNs presented by a single HBA to + the guest. +

Note: The managed attribute is only used with PCI devices @@ -3795,6 +3812,13 @@ credentials to the iSCSI server.

+
scsi_host
+
Since 2.5.0, multiple LUNs behind a + single SCSI HBA are described by a protocol + attribute set to "vhost" and a wwpn attribute that + is the vhost_scsi wwpn (16 hexadecimal digits with a prefix of + "naa.") established in the host configfs. +
vendor, product
diff --git a/docs/news.html.in b/docs/news.html.in index 009045247f..54eb8addce 100644 --- a/docs/news.html.in +++ b/docs/news.html.in @@ -27,6 +27,10 @@ libvirtd via SSH, using the libssh library; for example: qemu+libssh://server/system +
  • vhost-scsi: Add support scsi_host hostdev passthrough
    + Add the capability to pass through a scsi_host HBA and the + associated LUNs to the guest. +
  • Improvements diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 19d45fd6ea..bb903ef38f 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3974,6 +3974,7 @@ + @@ -4102,6 +4103,28 @@ + + + scsi_host + + + + + + + vhost + + + + + (naa\.)[0-9a-fA-F]{16} + + + + + + + storage diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 2decf02383..2d9ff5e3ff 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -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); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 697bc1d2f4..5d2bc8dfe3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -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, "\n"); + if (!closedSource) + virBufferAddLit(buf, "\n"); return 0; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args new file mode 100644 index 0000000000..199adfa5db --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args @@ -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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml new file mode 100644 index 0000000000..e428518c3c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml @@ -0,0 +1,34 @@ + + QEMUGuest2 + c7a5fdbd-edaf-9466-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
    + + +
    + + + +
    + + +
    + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args new file mode 100644 index 0000000000..cb4553fe29 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args @@ -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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml new file mode 100644 index 0000000000..aea6f7f926 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml @@ -0,0 +1,42 @@ + + QEMUGuest2 + c7a5fdbd-edaf-9466-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
    + + +
    + + +
    + + +
    + + + + + + +
    + + +
    + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 985f45dc4b..1954696993 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -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); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml new file mode 120000 index 0000000000..adea6e5a85 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml new file mode 120000 index 0000000000..891aaf9e01 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index e22b63f00f..4c7f147db6 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -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); -- GitLab