[Kimchi-devel] [PATCH 3/4] host pci pass through: list all host devices in a tree

Zhou Zheng Sheng zhshzhou at linux.vnet.ibm.com
Sun Apr 27 10:30:22 UTC 2014


on 2014/04/24 17:06, Mark Wu wrote:
> On 04/23/2014 05:48 PM, Zhou Zheng Sheng wrote:
>> The host devices form a tree. If the user decides to pass through an HBA
>> card to guest, all the related SCSI disks under the HBA card will be
>> managed by the guest as well. If we can present all host devices in a
>> tree, the user can conveniently infer the affected sub-devices of a
>> passed through PCI device.
>>
>> To get all devices in a tree, GET the following URL:
>>
>> curl -u root -H "Content-Type: application/json" \
>>    -H  "Accept: application/json" \
>>    http://127.0.0.1:8000/host/devices?_tree=1
>>
>> It would print information like follow.
>> [
>>    {
>>      "hardware":{...},
>>      "product":"...",
>>      "name":"computer",
>>      "parent":null,
>>      "path":null,
>>      "firmware":{...},
>>      "type":"system",
>>      "children":[
>>        {
>>          "slot":"0",
>>          "function":"0",
>>          "domain":"0",
>>          "vendor":{...},
>>          "name":"pci_0000_00_00_0",
>>          "parent":"computer",
>>          "bus":"0",
>>          "product":{...},
>>          "path":"/sys/devices/pci0000:00/0000:00:00.0",
>>          "type":"pci",
>>          "iommuGroup":"0"
>>        },
>>        {
>>          # Another child device info ...,
>>          "children":[
>>            {
>>              # A grand child device info ...,
>>            }, ... # Other grand children devices info
>>          ]
>>        }, ...
>>      ]
>>    }
>> ]
>>
>> The above tree is not very human friendly. In future we should parse
>> this tree in front-end and show a nice graphical tree to the user.
>> For now, you can get a human readable device tree using the following
>> command (but it's just for debugging purpose).
>>    PYTHONPATH=src python -m kimchi.hostdev | less
>>
>> It would print the following.
>> -----------------
>>   ~{'firmware': {...},
>>   ~ 'hardware': {...},
>>   ~ 'name': 'computer',
>>   ~ 'parent': None,
>>   ~ 'path': None,
>>   ~ 'product': '...',
>>   ~ 'type': 'system'}
>>     +-----------------
>>     | ~{'bus': '0',
>>     | ~ 'domain': '0',
>>     | ~ 'function': '0',
>>     | ~ 'iommuGroup': '0',
>>     | ~ 'name': 'pci_0000_00_00_0',
>>     | ~ 'parent': 'computer',
>>     | ~ 'path': '/sys/devices/pci0000:00/0000:00:00.0',
>>     | ~ 'product': {'description': '... DRAM Controller',
>>     | ~             'id': '0x0104'},
>>     | ~ 'slot': '0',
>>     | ~ 'type': 'pci',
>>     | ~ 'vendor': {'id': '0x8086', 'name': 'Intel Corporation'}}
>>     |
>>     +-----------------
>>     | ~{'bus': '0',
>>     | ~ 'domain': '0',
>>     | ~ 'function': '0',
>>     | ~ 'iommuGroup': '1',
>>     | ~ 'name': 'pci_0000_00_01_0',
>>     | ~ 'parent': 'computer',
>>     | ~ 'path': '/sys/devices/pci0000:00/0000:00:01.0',
>>     | ~ 'product': {...},
>>     | ~ 'slot': '1',
>>     | ~ 'type': 'pci',
>>     | ~ 'vendor': {'id': '0x8086', 'name': 'Intel Corporation'}}
>>     |   \-----------------
>>     |     ~{'bus': '1',
>>     |     ~ 'domain': '0',
>>     |     ~ 'function': '0',
>>     |     ~ 'iommuGroup': '1',
>>     |     ~ 'name': 'pci_0000_01_00_0',
>>     |     ~ 'parent': 'pci_0000_00_01_0',
>>     |     ~ 'path': '/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0',
>>     |     ~ 'product': {'description': 'GF119M ...', 'id': '0x1057'},
>>     |     ~ 'slot': '0',
>>     |     ~ 'type': 'pci',
>>     |     ~ 'vendor': {'id': '0x10de', 'name': 'NVIDIA Corporation'}}
>>     |
>>     |
>>     +-----------------
>>     | ~{'bus': '0',
>>     | ~ 'domain': '0',
>>     ...
>>
>> Signed-off-by: Zhou Zheng Sheng <zhshzhou at linux.vnet.ibm.com>
>> ---
>>   docs/API.md                |  7 +++++++
>>   src/kimchi/control/host.py | 21 +++++++++++++++++++++
>>   src/kimchi/i18n.py         |  2 ++
>>   3 files changed, 30 insertions(+)
>>
>> diff --git a/docs/API.md b/docs/API.md
>> index 009c58d..d89ca8c 100644
>> --- a/docs/API.md
>> +++ b/docs/API.md
>> @@ -812,6 +812,13 @@ Contains the host sample data.
>>       * Parameters:
>>           * _cap: Filter node device list with given node device
>> capability.
>>                   To list Fibre Channel SCSI Host devices, use
>> "_cap=fc_host".
>> +        * _tree: To list the devices in a tree, use "_tree=1". The
>> result is
>> +                 like [root_device], where root_device dictionary
>> contains all
>> +                 information of the root divice, and a
>> root_device["children"]
>> +                 item. The root_device["children"] is a list, and the
>> elements
>> +                 in the list are device dicts containing device
>> information and
>> +                 "children" lists. If a device is a leaf one, it does
>> not
>> +                 contain device["children"] item.
>>
>>   ### Resource: Device
>>
>> diff --git a/src/kimchi/control/host.py b/src/kimchi/control/host.py
>> index 003c4b9..9347932 100644
>> --- a/src/kimchi/control/host.py
>> +++ b/src/kimchi/control/host.py
>> @@ -22,6 +22,7 @@ import cherrypy
>>   from kimchi.control.base import Collection, Resource, SimpleCollection
>>   from kimchi.control.utils import UrlSubNode, validate_method
>>   from kimchi.exception import OperationFailed
>> +from kimchi import hostdev
>>   from kimchi.template import render
>>
>>
>> @@ -88,6 +89,26 @@ class Devices(Collection):
>>           super(Devices, self).__init__(model)
>>           self.resource = Device
>>
>> +    def _get_resources(self, flag_filter):
>> +        try:
>> +            _tree = bool(int(flag_filter['_tree']))
>> +            del flag_filter['_tree']
>> +        except KeyError:
>> +            _tree = False
>> +
>> +        devices = super(Devices, self)._get_resources(flag_filter)
>> +
>> +        if devices and _tree:
>> +            dev_infos = [device.data for device in devices]
>> +            root = hostdev.get_devices_tree(dev_infos)
>> +            if root is None:
>> +                raise InvalidParameter('KCHTMPL0023E')
>> +            root_device = Device(self.model, root['name'])
>> +            root_device.info = root
>> +            devices = [root_device]
>> +
>> +        return devices
>> +
>>
>>   class Device(Resource):
>>       def __init__(self, model, id):
>> diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
>> index 3d3abb4..955aff2 100644
>> --- a/src/kimchi/i18n.py
>> +++ b/src/kimchi/i18n.py
>> @@ -117,6 +117,8 @@ messages = {
>>       "KCHTMPL0020E": _("Unable to create template due error: %(err)s"),
>>       "KCHTMPL0021E": _("Unable to delete template due error: %(err)s"),
>>       "KCHTMPL0022E": _("Disk size must be greater than 1GB."),
>> +    "KCHTMPL0023E": _("No root device found. Maybe you should stop
>> filtering "
>> +                      "devices to avoid filtering out the root device
>> of the device tree."),
>>
>>       "KCHPOOL0001E": _("Storage pool %(name)s already exists"),
>>       "KCHPOOL0002E": _("Storage pool %(name)s does not exist"),
> We need have a discussion with UI developers about the restriction.
> As you mentioned,  the other devices in the same group will be affected
> by the passing through.
> We need let the user know this potential dangerous.  Considering kimchi
> is a light weight virtualization management tool,  I will suggest we
> only expose the leaf device with a field which indicate the devices will
> be affected by passing this device.  And the usb controller and scsi
> could be filtered, we can implement the passing through of them by their
> own mechanism.

In next patch set I will implement three types of pass through.

1. USB device
  Kimchi should be able to list all USB devices available to pass through.

2. SCSI device
  It's supported since libvirt 1.0.6. Kimchi should be able to list all
SCSI generic devices and pass through to VM. (A bit conflict with SCSI
storage pool?)

3. PCI device
  List only leaf PCI device, such as wireless NIC, and each device entry
should contain a list of device names in the same IOMMU group, because
all PCI devices in the same IOMMU group should be detached at the same
time. This should simplifies the front-end work.

However I think a device tree is still useful. Say two PCI devices are
in the same IOMMU group, one is wireless NIC and other is a USB/SD/SCSI
controller. When we decide to pass through the wireless NIC to guest,
the controller would also be detached. Only listing the wireless NIC and
the controller's names are not enough, because the controller may be
linked to children devices, and those children devices are affected too.

In back-end, I think providing rich device information and organizing
them in a tree is very useful. It should be the front-end's duty to show
them in a human readable and friendly manner. If you think the
information produced by host/devices is too much, that is because it's
not for human, but for front-end code to parse.

We can show all host devices in a tree in the front-end. The node in the
tree contains only an icon and a title. When the mouse moves over the
title, details can be shown in tool tip. Only the leaf USB, SCSI and PCI
device are available for the user to pass through, and they are shown in
highlight with a tick box. Other parent devices can be shown in gray
color. By clicking the leaf device tick box, the code should
automatically compute the affected devices. For USB or SCSI device, the
affected device is itself. For PCI device, the affect devices are ones
in the same IOMMU group, and the tree view should changed promptly to
reflect which devices would be affected. Once the user determines the
devices to pass through, the front-end code just send the device names
to back-end, and back-end detect the device types automatically and
generate the XML. In this way we provides a single front-end interface
to pass through all kinds of host devices, and also a single back-end
interface to list and pass through them.




More information about the Kimchi-devel mailing list