[libvirt] [PATCH 03/23] Add support for <hostdev mode="capabilities">
Osier Yang
jyang at redhat.com
Fri Dec 14 10:37:41 UTC 2012
On 2012年12月01日 04:26, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange"<berrange at redhat.com>
>
> The<hostdev> device type has long had a redundant "mode"
> attribute, which has always been "subsys". This finally
> introduces a new mode "capabilities", which will be used
> by the LXC driver for device assignment. Since container
> based virtualization uses a single kernel, the idea of
> assigning physical PCI devices doesn't make sense. It is
> still reasonable to assign USB devices, but for assinging
> arbitrary nodes in /dev, the new 'capabilities' mode is
> to be used.
>
> The first capability support is 'storage', which is for
> assignment of block devices. Functionally this is really
> pretty similar to the<disk> support. The only difference
> is the device node name is identical in both host and
> container namespaces.
>
> <hostdev mode='capabilities' type='storage'>
> <source>
> <block>/dev/sdf1</block>
> </source>
> </hostdev>
>
> The second capability support is 'misc', which is for
> assignment of character devices. There is no existing
> parallel to this. Again the device node is the same
> inside& outside the container.
>
> <hostdev mode='capabilities' type='misc'>
> <source>
> <char>/dev/sdf1</char>
> </source>
> </hostdev>
>
> The reason for keeping the char& storage devices
> separate in the domain XML, is to mirror the split
> in the node device XML. NB the node device XML does
> not yet report character devices, but that's another
> new patch to come
>
> Signed-off-by: Daniel P. Berrange<berrange at redhat.com>
> ---
> docs/schemas/domaincommon.rng | 128 +++++++++++++++++--------
> src/conf/domain_audit.c | 80 +++++++++++-----
> src/conf/domain_conf.c | 175 ++++++++++++++++++++++++++++++++++-
> src/conf/domain_conf.h | 31 +++++--
> src/libvirt_private.syms | 1 +
> tests/lxcxml2xmldata/lxc-hostdev.xml | 34 +++++++
> tests/lxcxml2xmltest.c | 1 +
> 7 files changed, 375 insertions(+), 75 deletions(-)
> create mode 100644 tests/lxcxml2xmldata/lxc-hostdev.xml
>
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 0e85739..072e5cc 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -2812,63 +2812,109 @@
> </zeroOrMore>
> </element>
> </define>
> +
> <define name="hostdev">
> <element name="hostdev">
> +<choice>
> +<group>
> +<ref name="hostdevsubsys"/>
> +</group>
> +<group>
> +<ref name="hostdevcaps"/>
> +</group>
> +</choice>
> <optional>
> -<attribute name="mode">
> -<choice>
> -<value>subsystem</value>
> -<value>capabilities</value>
> -</choice>
> -</attribute>
> -</optional>
> -<attribute name="type">
> -<choice>
> -<value>usb</value>
> -<value>pci</value>
> -</choice>
> -</attribute>
> -<optional>
> -<attribute name="managed">
> -<choice>
> -<value>yes</value>
> -<value>no</value>
> -</choice>
> -</attribute>
> +<ref name="alias"/>
> </optional>
> -<group>
> -<element name="source">
> -<optional>
> -<ref name="startupPolicy"/>
> -</optional>
> -<choice>
> -<group>
> -<ref name="usbproduct"/>
> -<optional>
> -<ref name="usbaddress"/>
> -</optional>
> -</group>
> -<ref name="usbaddress"/>
> -<element name="address">
> -<ref name="pciaddress"/>
> -</element>
> -</choice>
> -</element>
> -</group>
> <optional>
> <ref name="deviceBoot"/>
> </optional>
> <optional>
> -<ref name="alias"/>
> +<ref name="rom"/>
> </optional>
> <optional>
> <ref name="address"/>
> </optional>
> +</element>
> +</define>
> +
> +<define name="hostdevsubsys">
> +<optional>
> +<attribute name="mode">
> +<value>subsystem</value>
> +</attribute>
> +</optional>
> +<optional>
> +<attribute name="managed">
> +<choice>
> +<value>yes</value>
> +<value>no</value>
> +</choice>
> +</attribute>
> +</optional>
> +<choice>
> +<ref name="hostdevsubsyspci"/>
> +<ref name="hostdevsubsysusb"/>
> +</choice>
> +</define>
> +
> +<define name="hostdevcaps">
> +<attribute name="mode">
> +<value>capabilities</value>
> +</attribute>
> +<choice>
> +<group>
> +<ref name="hostdevcapsstorage"/>
> +</group>
> +</choice>
> +</define>
> +
> +
> +<define name="hostdevsubsyspci">
> +<attribute name="type">
> +<value>pci</value>
> +</attribute>
> +<element name="source">
> +<optional>
> +<ref name="startupPolicy"/>
> +</optional>
> +<element name="address">
> +<ref name="pciaddress"/>
> +</element>
> +</element>
> +</define>
> +
> +<define name="hostdevsubsysusb">
> +<attribute name="type">
> +<value>usb</value>
> +</attribute>
> +<element name="source">
> <optional>
> -<ref name="rom"/>
> +<ref name="startupPolicy"/>
> </optional>
> +<choice>
> +<group>
> +<ref name="usbproduct"/>
> +<optional>
> +<ref name="usbaddress"/>
> +</optional>
> +</group>
> +<ref name="usbaddress"/>
> +</choice>
> </element>
> </define>
> +
> +<define name="hostdevcapsstorage">
> +<attribute name="type">
> +<value>storage</value>
> +</attribute>
> +<element name="source">
> +<element name="block">
> +<ref name="absFilePath"/>
> +</element>
> +</element>
> +</define>
> +
> <define name="usbproduct">
> <element name="vendor">
> <attribute name="id">
> diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
> index 939d213..e61eabe 100644
> --- a/src/conf/domain_audit.c
> +++ b/src/conf/domain_audit.c
> @@ -260,42 +260,72 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
> virt = "?";
> }
>
> - switch (hostdev->source.subsys.type) {
> - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
> - if (virAsprintf(&address, "%.4x:%.2x:%.2x.%.1x",
> - hostdev->source.subsys.u.pci.domain,
> - hostdev->source.subsys.u.pci.bus,
> - hostdev->source.subsys.u.pci.slot,
> - hostdev->source.subsys.u.pci.function)< 0) {
> + switch (hostdev->mode) {
> + case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
> + switch (hostdev->source.subsys.type) {
> + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
> + if (virAsprintf(&address, "%.4x:%.2x:%.2x.%.1x",
> + hostdev->source.subsys.u.pci.domain,
> + hostdev->source.subsys.u.pci.bus,
> + hostdev->source.subsys.u.pci.slot,
> + hostdev->source.subsys.u.pci.function)< 0) {
> + VIR_WARN("OOM while encoding audit message");
> + goto cleanup;
> + }
> + break;
> + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
> + if (virAsprintf(&address, "%.3d.%.3d",
> + hostdev->source.subsys.u.usb.bus,
> + hostdev->source.subsys.u.usb.device)< 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);
> + goto cleanup;
> + }
> +
> + if (!(device = virAuditEncode("device", VIR_AUDIT_STR(address)))) {
> VIR_WARN("OOM while encoding audit message");
> goto cleanup;
> }
> +
> + VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
> + "virt=%s resrc=dev reason=%s %s uuid=%s bus=%s %s",
> + virt, reason, vmname, uuidstr,
> + virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type),
> + device);
> break;
> - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
> - if (virAsprintf(&address, "%.3d.%.3d",
> - hostdev->source.subsys.u.usb.bus,
> - hostdev->source.subsys.u.usb.device)< 0) {
> - VIR_WARN("OOM while encoding audit message");
> +
> + case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
> + switch (hostdev->source.caps.type) {
> + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
> + if (!(device = virAuditEncode("disk",
> + VIR_AUDIT_STR(hostdev->source.caps.u.storage.block)))) {
> + VIR_WARN("OOM while encoding audit message");
> + goto cleanup;
> + }
> +
> + VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
> + "virt=%s resrc=hostdev reason=%s %s uuid=%s %s",
> + virt, reason, vmname, uuidstr, device);
> + break;
> +
> + default:
> + VIR_WARN("Unexpected hostdev type while encoding audit message: %d",
> + hostdev->source.caps.type);
> goto cleanup;
> }
> break;
> - default:
> - VIR_WARN("Unexpected hostdev type while encoding audit message: %d",
> - hostdev->source.subsys.type);
> - goto cleanup;
> - }
>
> - if (!(device = virAuditEncode("device", VIR_AUDIT_STR(address)))) {
> - VIR_WARN("OOM while encoding audit message");
> + default:
> + VIR_WARN("Unexpected hostdev mode while cndoing audit message: %d",
> + hostdev->mode);
> goto cleanup;
> }
>
> - VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
> - "virt=%s resrc=dev reason=%s %s uuid=%s bus=%s %s",
> - virt, reason, vmname, uuidstr,
> - virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type),
> - device);
> -
> cleanup:
> VIR_FREE(vmname);
> VIR_FREE(device);
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index dd0e841..d97bbc8 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -530,12 +530,16 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceClipboardCopypaste,
>
> VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
> "subsystem",
> - "capabilities")
> + "capabilities");
>
> VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
> "usb",
> "pci")
>
> +VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
> + "storage",
> + "misc")
> +
> VIR_ENUM_IMPL(virDomainPciRombarMode,
> VIR_DOMAIN_PCI_ROMBAR_LAST,
> "default",
> @@ -1440,6 +1444,17 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
> */
> if (def->parent.type == VIR_DOMAIN_DEVICE_NONE)
> virDomainDeviceInfoFree(def->info);
> +
> + if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) {
> + switch (def->source.caps.type) {
> + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
> + VIR_FREE(def->source.caps.u.storage.block);
> + break;
> + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
> + VIR_FREE(def->source.caps.u.misc.chardev);
> + break;
> + }
> + }
> }
>
> void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
> @@ -3026,6 +3041,71 @@ error:
> return ret;
> }
>
> +static int
> +virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
> + xmlXPathContextPtr ctxt,
> + const char *type,
> + virDomainHostdevDefPtr def)
> +{
> + xmlNodePtr sourcenode;
> + int ret = -1;
> +
> + /* @type is passed in from the caller rather than read from the
> + * xml document, because it is specified in different places for
> + * different kinds of defs - it is an attribute of
> + *<source>/<address> for an intelligent hostdev (<interface>),
> + * but an attribute of the toplevel element for a standard
> + *<hostdev>. (the functions we're going to call expect address
> + * type to already be known).
Per the @type is passed in from caller...
> + */
> + if (type) {
> + if ((def->source.caps.type
> + = virDomainHostdevCapsTypeFromString(type))< 0) {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("unknown host device source address type '%s'"),
> + type);
> + goto error;
> + }
> + } else {
> + virReportError(VIR_ERR_XML_ERROR,
> + "%s", _("missing source address type"));
> + goto error;
> + }
But this indicates a parsing error.
More information about the libvir-list
mailing list