devices: adjust API for 'devices: add assignment.device property' change
Make it easy to retrieve DeviceInfo object out of DeviceAssignment object. The only missing piece of information for that is device class, so add it. Make it optional, as it can be filled on demand when passing the object through DeviceCollection (either by listing devices, or attaching/detaching). This also makes DeviceCollection._device method not needed anymore.
This commit is contained in:
parent
3edbc85282
commit
c826378579
@ -34,10 +34,11 @@ Devices are identified by pair of (backend domain, `ident`), where `ident` is
|
||||
class DeviceAssignment(object): # pylint: disable=too-few-public-methods
|
||||
''' Maps a device to a frontend_domain. '''
|
||||
|
||||
def __init__(self, backend_domain, ident, options=None, persistent=False,
|
||||
frontend_domain=None):
|
||||
def __init__(self, backend_domain, ident, options=None,
|
||||
persistent=False, frontend_domain=None, devclass=None):
|
||||
self.backend_domain = backend_domain
|
||||
self.ident = ident
|
||||
self.devclass = devclass
|
||||
self.options = options or {}
|
||||
self.persistent = persistent
|
||||
self.frontend_domain = frontend_domain
|
||||
@ -55,6 +56,22 @@ class DeviceAssignment(object): # pylint: disable=too-few-public-methods
|
||||
return self.backend_domain == other.backend_domain \
|
||||
and self.ident == other.ident
|
||||
|
||||
def clone(self):
|
||||
'''Clone object instance'''
|
||||
return self.__class__(
|
||||
self.backend_domain,
|
||||
self.ident,
|
||||
self.options,
|
||||
self.persistent,
|
||||
self.frontend_domain,
|
||||
self.devclass,
|
||||
)
|
||||
|
||||
@property
|
||||
def device(self):
|
||||
'''Get DeviceInfo object corresponding to this DeviceAssignment'''
|
||||
return self.backend_domain.devices[self.devclass][self.ident]
|
||||
|
||||
|
||||
class DeviceInfo(object):
|
||||
''' Holds all information about a device '''
|
||||
@ -120,6 +137,10 @@ class DeviceCollection(object):
|
||||
else:
|
||||
assert device_assignment.frontend_domain == self._vm, \
|
||||
"Trying to attach DeviceAssignment belonging to other domain"
|
||||
if device_assignment.devclass is None:
|
||||
device_assignment.devclass = self._class
|
||||
else:
|
||||
assert device_assignment.devclass == self._class
|
||||
|
||||
options = device_assignment.options.copy()
|
||||
if device_assignment.persistent:
|
||||
@ -143,6 +164,10 @@ class DeviceCollection(object):
|
||||
else:
|
||||
assert device_assignment.frontend_domain == self._vm, \
|
||||
"Trying to detach DeviceAssignment belonging to other domain"
|
||||
if device_assignment.devclass is None:
|
||||
device_assignment.devclass = self._class
|
||||
else:
|
||||
assert device_assignment.devclass == self._class
|
||||
|
||||
self._vm.qubesd_call(None,
|
||||
'admin.vm.device.{}.Detach'.format(self._class),
|
||||
@ -174,13 +199,14 @@ class DeviceCollection(object):
|
||||
continue
|
||||
backend_domain = self._vm.app.domains[backend_domain]
|
||||
yield DeviceAssignment(backend_domain, ident, options,
|
||||
persistent=dev_persistent, frontend_domain=self._vm)
|
||||
persistent=dev_persistent, frontend_domain=self._vm,
|
||||
devclass=self._class)
|
||||
|
||||
def attached(self):
|
||||
'''List devices which are (or may be) attached to this vm '''
|
||||
|
||||
for assignment in self.assignments():
|
||||
yield self._device(assignment)
|
||||
yield assignment.device
|
||||
|
||||
def persistent(self):
|
||||
''' Devices persistently attached and safe to access before libvirt
|
||||
@ -188,13 +214,7 @@ class DeviceCollection(object):
|
||||
'''
|
||||
|
||||
for assignment in self.assignments(True):
|
||||
yield self._device(assignment)
|
||||
|
||||
def _device(self, assignment):
|
||||
''' Helper method for geting a `qubes.devices.DeviceInfo` object from
|
||||
`qubes.devices.DeviceAssignment`. '''
|
||||
|
||||
return assignment.backend_domain.devices[self._class][assignment.ident]
|
||||
yield assignment.device
|
||||
|
||||
def available(self):
|
||||
'''List devices exposed by this vm'''
|
||||
|
@ -161,6 +161,12 @@ class TC_00_DeviceCollection(qubesadmin.tests.QubesTestCase):
|
||||
('test-vm', 'admin.vm.device.test.List', None, None)] = \
|
||||
b'0\0test-vm2+dev1\n' \
|
||||
b'test-vm3+dev2\n'
|
||||
self.app.expected_calls[
|
||||
('test-vm2', 'admin.vm.device.test.Available', None, None)] = \
|
||||
b'0\0dev1 description=desc\n'
|
||||
self.app.expected_calls[
|
||||
('test-vm3', 'admin.vm.device.test.Available', None, None)] = \
|
||||
b'0\0dev2 description=desc\n'
|
||||
assigns = list(self.vm.devices['test'].assignments())
|
||||
self.assertEqual(len(assigns), 2)
|
||||
self.assertIsInstance(assigns[0], qubesadmin.devices.DeviceAssignment)
|
||||
@ -170,6 +176,9 @@ class TC_00_DeviceCollection(qubesadmin.tests.QubesTestCase):
|
||||
self.assertEqual(assigns[0].frontend_domain,
|
||||
self.app.domains['test-vm'])
|
||||
self.assertEqual(assigns[0].options, {})
|
||||
self.assertEqual(assigns[0].devclass, 'test')
|
||||
self.assertEqual(assigns[0].device,
|
||||
self.app.domains['test-vm2'].devices['test']['dev1'])
|
||||
|
||||
self.assertIsInstance(assigns[1], qubesadmin.devices.DeviceAssignment)
|
||||
self.assertEqual(assigns[1].backend_domain,
|
||||
@ -178,6 +187,9 @@ class TC_00_DeviceCollection(qubesadmin.tests.QubesTestCase):
|
||||
self.assertEqual(assigns[1].frontend_domain,
|
||||
self.app.domains['test-vm'])
|
||||
self.assertEqual(assigns[1].options, {})
|
||||
self.assertEqual(assigns[1].devclass, 'test')
|
||||
self.assertEqual(assigns[1].device,
|
||||
self.app.domains['test-vm3'].devices['test']['dev2'])
|
||||
|
||||
self.assertAllCalled()
|
||||
|
||||
@ -196,6 +208,7 @@ class TC_00_DeviceCollection(qubesadmin.tests.QubesTestCase):
|
||||
self.app.domains['test-vm'])
|
||||
self.assertEqual(assigns[0].options, {'ro': 'True'})
|
||||
self.assertEqual(assigns[0].persistent, False)
|
||||
self.assertEqual(assigns[0].devclass, 'test')
|
||||
|
||||
self.assertIsInstance(assigns[1], qubesadmin.devices.DeviceAssignment)
|
||||
self.assertEqual(assigns[1].backend_domain,
|
||||
@ -205,6 +218,7 @@ class TC_00_DeviceCollection(qubesadmin.tests.QubesTestCase):
|
||||
self.app.domains['test-vm'])
|
||||
self.assertEqual(assigns[1].options, {'ro': 'False'})
|
||||
self.assertEqual(assigns[1].persistent, True)
|
||||
self.assertEqual(assigns[1].devclass, 'test')
|
||||
|
||||
self.assertAllCalled()
|
||||
|
||||
@ -223,6 +237,7 @@ class TC_00_DeviceCollection(qubesadmin.tests.QubesTestCase):
|
||||
self.app.domains['test-vm'])
|
||||
self.assertEqual(assigns[0].options, {})
|
||||
self.assertEqual(assigns[0].persistent, True)
|
||||
self.assertEqual(assigns[0].devclass, 'test')
|
||||
self.assertAllCalled()
|
||||
|
||||
def test_042_assignments_non_persistent(self):
|
||||
|
Loading…
Reference in New Issue
Block a user