Browse Source

qubes/devices: devices class framework

This fixes loading PCI devices.
Wojtek Porczyk 8 years ago
parent
commit
349e218638
3 changed files with 30 additions and 10 deletions
  1. 17 10
      qubes/__init__.py
  2. 10 0
      qubes/devices.py
  3. 3 0
      setup.py

+ 17 - 10
qubes/__init__.py

@@ -81,6 +81,18 @@ except ImportError:
     pass
 
 
+def get_entry_point_one(group, name):
+    epoints = tuple(pkg_resources.iter_entry_points(group, name))
+    if not epoints:
+        raise KeyError(name)
+    elif len(epoints) > 1:
+        raise TypeError(
+            'more than 1 implementation of {!r} found: {}'.format(name,
+                ', '.join('{}.{}'.format(ep.module_name, '.'.join(ep.attrs))
+                    for ep in epoints)))
+    return epoints[0].load()
+
+
 class VMMConnection(object):
     '''Connection to Virtual Machine Manager (libvirt)'''
 
@@ -1401,18 +1413,13 @@ class Qubes(PropertyHolder):
         :param str clsname: name of the class
         :return type: class
         '''
-        epoints = tuple(pkg_resources.iter_entry_points('qubes.vm', clsname))
-        if not epoints:
+
+        try:
+            get_entry_point_one('qubes.vm', clsname)
+        except KeyError:
             raise qubes.exc.QubesException(
                 'no such VM class: {!r}'.format(clsname))
-        elif len(epoints) > 1:
-            raise qubes.exc.QubesException(
-                'more than 1 implementation of {!r} found: {}'.format(
-                    clsname,
-                    ', '.join(
-                        '{}.{}'.format(ep.module_name, '.'.join(ep.attrs))
-                        for ep in epoints)))
-        return epoints[0].load()
+        # don't catch TypeError
 
 
     def add_new_vm(self, cls, qid=None, **kwargs):

+ 10 - 0
qubes/devices.py

@@ -24,6 +24,8 @@
 
 import re
 
+import qubes
+
 class DeviceCollection(object):
     '''Bag for devices.
 
@@ -45,6 +47,14 @@ class DeviceCollection(object):
         :param str device: device identifier (format is class-dependent)
         '''
 
+        try:
+            devclass = qubes.get_entry_point_one('qubes.devices', self._class)
+        except KeyError:
+            devclass = str
+
+        if not isinstance(device, devclass):
+            device = devclass(device)
+
         if device in self:
             raise KeyError(
                 'device {!r} of class {} already attached to {!r}'.format(

+ 3 - 0
setup.py

@@ -39,5 +39,8 @@ if __name__ == '__main__':
                 'qubes.ext.gui = qubes.ext.gui:GUI',
                 'qubes.ext.r3compatibility = qubes.ext.r3compatibility:R3Compatibility',
             ],
+            'qubes.devices': [
+                'pci = qubes.devices:PCIDevice',
+            ],
         }
     )