[Kimchi-devel] [PATCH] [Kimchi] USB xhci hotplug: Check controller, define in template, add test in Power

Aline Manera alinefm at linux.vnet.ibm.com
Mon Oct 17 11:55:10 UTC 2016



On 10/14/2016 05:55 PM, Lucio Correia wrote:
> - Today it is not possible to hotplug a PCI in Power Systems without an
>    USB xhci controller existing in the VM. This commit checks if there
>    is such controller in the VM, displaying an error message if not.
> - When creating VMs using Kimchi in a Power System, the USB xhci
>    controller is defined by default to have PCI hotplug support.
> - From now on all templates are created with xhci usb controller, so a
>     hotplug must be performed flawlessly. If anything wrong the test case
>     will fail.
>
> Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
> Signed-off-by: Lucio Correia <luciojhc at linux.vnet.ibm.com>
> ---
>   i18n.py             |  1 +
>   model/vmhostdevs.py | 34 ++++++++++++++++++++++++++++++++++
>   tests/test_model.py | 25 +++++++++++++++++++++++++
>   vmtemplate.py       | 17 +++++++++++++++++
>   4 files changed, 77 insertions(+)
>
> diff --git a/i18n.py b/i18n.py
> index 82c679b..159021d 100644
> --- a/i18n.py
> +++ b/i18n.py
> @@ -150,6 +150,7 @@ messages = {
>       "KCHVMHDEV0005E": _('The device %(name)s is probably in use by the host. Unable to attach it to the guest.'),
>       "KCHVMHDEV0006E": _('Hot-(un)plug of device %(name)s is not supported.'),
>       "KCHVMHDEV0007E": _('Failed to attach %(device)s to %(vm)s'),
> +    "KCHVMHDEV0008E": _('VM %(vmid)s does not have an USB XHCI controller to accept PCI hotplug.'),
>
>       "KCHVMIF0001E": _("Interface %(iface)s does not exist in virtual machine %(name)s"),
>       "KCHVMIF0002E": _("Network %(network)s specified for virtual machine %(name)s does not exist"),
> diff --git a/model/vmhostdevs.py b/model/vmhostdevs.py
> index e289f03..edb6e36 100644
> --- a/model/vmhostdevs.py
> +++ b/model/vmhostdevs.py
> @@ -43,6 +43,9 @@ from wok.plugins.kimchi.xmlutils.qemucmdline import QEMU_NAMESPACE
>
>
>   CMDLINE_FIELD_NAME = 'spapr-pci-host-bridge.mem_win_size'
> +USB_MODELS_PCI_HOTPLUG = ["piix3-uhci", "piix4-uhci", "ehci", "ich9-ehci1",
> +                          "ich9-uhci1", "ich9-uhci2", "ich9-uhci3",
> +                          "vt82c686b-uhci", "pci-ohci", "nec-xhci"]
>   WINDOW_SIZE_BAR = 0x800000000
>
>
> @@ -135,6 +138,28 @@ class VMHostDevsModel(object):
>
>           return '<devices>%s</devices>' % hostdevs
>
> +    def have_xhci_usb_controller(self, vmid):
> +        dom = VMModel.get_vm(vmid, self.conn)
> +
> +        root = objectify.fromstring(dom.XMLDesc(0))
> +
> +        try:
> +            controllers = root.devices.controller
> +
> +        except AttributeError:
> +            return False
> +
> +        for controller in controllers:
> +
> +            if 'model' not in controller.attrib:
> +                continue
> +
> +            if controller.attrib['type'] == 'usb' and \
> +               controller.attrib['model'] in USB_MODELS_PCI_HOTPLUG:
> +                return True
> +
> +        return False
> +
>       def _get_pci_device_xml(self, dev_info, slot, is_multifunction):
>           if 'detach_driver' not in dev_info:
>               dev_info['detach_driver'] = 'kvm'
> @@ -234,6 +259,15 @@ class VMHostDevsModel(object):
>               dom = VMModel.get_vm(vmid, self.conn)
>               driver = 'vfio' if self.caps.kernel_vfio else 'kvm'
>
> +            # 'vfio' systems requires a xhci usb controller in order to support
> +            # pci hotplug on Power.
> +            if driver == 'vfio' and platform.machine().startswith('ppc') and \
> +               DOM_STATE_MAP[dom.info()[0]] != "shutoff" and \
> +               not self.have_xhci_usb_controller(vmid):
> +                msg = WokMessage('KCHVMHDEV0008E', {'vmid': vmid})
> +                cb(msg.get_text(), False)
> +                raise InvalidOperation("KCHVMHDEV0008E", {'vmid': vmid})
> +
>               # Attach all PCI devices in the same IOMMU group
>               affected_names = self.devs_model.get_list(
>                   _passthrough_affected_by=dev_info['name'])
> diff --git a/tests/test_model.py b/tests/test_model.py
> index 082cb9d..4ddd0d2 100644
> --- a/tests/test_model.py
> +++ b/tests/test_model.py
> @@ -1626,6 +1626,31 @@ class ModelTests(unittest.TestCase):
>               volumes = inst.storagevolumes_get_list(args['name'])
>               self.assertEquals(len(volumes), 2)
>
> +    def _host_is_power():

> +        import platform

Move the import to the import block at the top of file.

> +        return platform.machine().startswith('ppc')
> +
> +    @unittest.skipUnless(_host_is_power(), 'Only required for Power hosts')
> +    def test_pci_hotplug_requires_xhci_usb_controller(self):
> +        config.set("authentication", "method", "pam")
> +        inst = model.Model(None, objstore_loc=self.tmp_store)
> +        tpl_params = {'name': 'test', 'memory': 1024, 'cdrom': UBUNTU_ISO}
> +        inst.templates_create(tpl_params)
> +
> +        with RollbackContext() as rollback:
> +            vm_params = {'name': 'kimchi-vm1', 'template': '/templates/test'}
> +            task1 = inst.vms_create(vm_params)
> +            inst.task_wait(task1['id'])
> +            rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete,
> +                                  'kimchi-vm1')
> +            # Start vm
> +            inst.vm_start('kimchi-vm1')
> +            rollback.prependDefer(utils.rollback_wrapper, inst.vm_poweroff,
> +                                  'kimchi-vm1')
> +            # check if create VM has USB XHCI controller
> +            self.assertTrue(
> +                inst.vmhostdevs_have_xhci_usb_controller('kimchi-vm1'))
> +
>
>   class BaseModelTests(unittest.TestCase):
>       class FoosModel(object):
> diff --git a/vmtemplate.py b/vmtemplate.py
> index 0288330..56b339f 100644
> --- a/vmtemplate.py
> +++ b/vmtemplate.py
> @@ -18,6 +18,7 @@
>   # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
>
>   import os
> +import platform
>   import stat
>   import time
>   import urlparse
> @@ -358,6 +359,18 @@ class VMTemplate(object):
>                                           self.info['os_version'])
>           return unicode(interfaces, 'utf-8')
>
> +    def _get_usb_controller(self):
> +        # powerkvm systems must include xhci controller model
> +        if not platform.machine().startswith('ppc'):
> +            return ''
> +

> +        return """
> +        <controller type='usb' index='0' model='nec-xhci'>
> +            <address type='pci' domain='0x0000'
> +            bus='0x00' slot='0x0f' function='0x0'/>
> +        </controller>

If it is not exist, please, add a new module to /xmlutils to generated 
the above XML by using lxml module instead of using plan text.

> +        """
> +
>       def _get_input_output_xml(self):
>           sound = """
>               <sound model='%(sound_model)s' />
> @@ -469,6 +482,9 @@ class VMTemplate(object):
>           # cpu_info element
>           params['cpu_info_xml'] = self._get_cpu_xml()
>
> +        # usb controller xhci
> +        params['usb_controller'] = self._get_usb_controller()
> +
>           xml = """
>           <domain type='%(domain)s'>
>             %(qemu-stream-cmdline)s
> @@ -503,6 +519,7 @@ class VMTemplate(object):
>               %(interfaces)s
>               %(graphics)s
>               %(input_output)s
> +            %(usb_controller)s
>               %(serial)s
>               <memballoon model='virtio' />
>             </devices>




More information about the Kimchi-devel mailing list