From 25148854b97ee884ea9194af74e483f7b53c13ef Mon Sep 17 00:00:00 2001 From: Piotr Bartman-Szwarc Date: Tue, 20 Aug 2024 07:39:02 +0200 Subject: [PATCH] q-dev: assignment.device --- qubes/device_protocol.py | 17 +++++++++++++++++ qubes/devices.py | 6 +++--- qubes/ext/utils.py | 2 +- templates/libvirt/xen.xml | 18 ++++++++++-------- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/qubes/device_protocol.py b/qubes/device_protocol.py index f40d4500f..caaa4ef4a 100644 --- a/qubes/device_protocol.py +++ b/qubes/device_protocol.py @@ -1127,6 +1127,23 @@ def devices(self) -> List[DeviceInfo]: result.append(dev) return result + @property + def device(self) -> DeviceInfo: + """ + Get single DeviceInfo object or raise an error. + + If port id is set we have exactly one device + since we can attach ony one device to one port. + If assignment is more general we can get 0 or many devices. + """ + devices = self.devices + if len(devices) == 1: + return devices[0] + if len(devices) > 1: + raise ProtocolError("Too many devices matches to assignment") + if len(devices) == 0: + raise ProtocolError("Any devices matches to assignment") + @property def port(self) -> Port: """ diff --git a/qubes/devices.py b/qubes/devices.py index 23cbcb4f7..3f7c26b15 100644 --- a/qubes/devices.py +++ b/qubes/devices.py @@ -209,8 +209,8 @@ async def attach(self, assignment: DeviceAssignment): raise ValueError( f'Cannot attach ambiguous {assignment.devclass} device.') - device = assignment.devices[0] - if device in [ass.devices[0] for ass in self.get_attached_devices()]: + device = assignment.device + if device in [ass.device for ass in self.get_attached_devices()]: raise DeviceAlreadyAttached( 'device {!s} of class {} already attached to {!s}'.format( device, self._bus, self._vm)) @@ -307,7 +307,7 @@ async def detach(self, port: Port): "You need to unassign device first.") # use the local object, only one device can match - port = assignment.devices[0].port + port = assignment.device.port await self._vm.fire_event_async( 'device-pre-detach:' + self._bus, pre_event=True, port=port) diff --git a/qubes/ext/utils.py b/qubes/ext/utils.py index 2841edca1..4a7ae9bf1 100644 --- a/qubes/ext/utils.py +++ b/qubes/ext/utils.py @@ -79,7 +79,7 @@ def device_list_change( for port_id, frontends in to_attach.items(): if len(frontends) > 1: # unique - device = tuple(frontends.values())[0].devices[0] + device = tuple(frontends.values())[0].device target_name = confirm_device_attachment(device, frontends) for front in frontends: if front.name == target_name: diff --git a/templates/libvirt/xen.xml b/templates/libvirt/xen.xml index c4d2f819d..80acf3397 100644 --- a/templates/libvirt/xen.xml +++ b/templates/libvirt/xen.xml @@ -157,9 +157,10 @@ {# start external devices from xvdi #} {% set counter = {'i': 4} %} {% for assignment in vm.devices.block.get_assigned_devices(True) %} - {% set device = assignment.devices[0] %} - {% set options = assignment.options %} - {% include 'libvirt/devices/block.xml' %} + {% for device in assignment.devices %} + {% set options = assignment.options %} + {% include 'libvirt/devices/block.xml' %} + {% endfor %} {% endfor %} {% if vm.netvm %} @@ -167,11 +168,12 @@ {% endif %} {% for assignment in vm.devices.pci.get_assigned_devices(True) %} - {% set device = assignment.devices[0] %} - {% set options = assignment.options %} - {% set power_mgmt = - vm.app.domains[0].features.get('suspend-s0ix', False) %} - {% include 'libvirt/devices/pci.xml' %} + {% for device in assignment.devices %} + {% set options = assignment.options %} + {% set power_mgmt = + vm.app.domains[0].features.get('suspend-s0ix', False) %} + {% include 'libvirt/devices/pci.xml' %} + {% endfor %} {% endfor %} {% if vm.virt_mode == 'hvm' %}