[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