Skip to content

Commit 1b2934c

Browse files
committed
q-dev: virtual device
1 parent 1302bf9 commit 1b2934c

9 files changed

+52
-51
lines changed

qubes/api/admin.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import qubes.vm
4646
import qubes.vm.adminvm
4747
import qubes.vm.qubesvm
48-
from qubes.device_protocol import Port, Device, DeviceInfo
48+
from qubes.device_protocol import Port, VirtualDevice, DeviceInfo
4949

5050

5151
class QubesMgmtEventsDispatcher:
@@ -1323,7 +1323,7 @@ async def vm_device_assign(self, endpoint, untrusted_payload):
13231323

13241324
def load_device_info(self, devclass) -> DeviceInfo:
13251325
# qrexec already verified that no strange characters are in self.arg
1326-
_dev = Device.from_qarg(self.arg, devclass, self.app.domains)
1326+
_dev = VirtualDevice.from_qarg(self.arg, devclass, self.app.domains)
13271327
# load all info, may raise KeyError, either on domain or port_id
13281328
return self.app.domains[
13291329
_dev.backend_domain].devices[devclass][_dev.port_id]
@@ -1410,7 +1410,7 @@ async def vm_device_set_required(self, endpoint, untrusted_payload):
14101410
assignment = eval(untrusted_payload)
14111411
del untrusted_payload
14121412

1413-
dev = Device.from_qarg(self.arg, devclass, self.app.domains)
1413+
dev = VirtualDevice.from_qarg(self.arg, devclass, self.app.domains)
14141414

14151415
self.fire_event_for_permission(device=dev, assignment=assignment)
14161416

qubes/device_protocol.py

+23-22
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def pack_property(cls, key: str, value: Optional[str]):
134134

135135
@staticmethod
136136
def parse_basic_device_properties(
137-
expected_device: 'Device', properties: Dict[str, Any]):
137+
expected_device: 'VirtualDevice', properties: Dict[str, Any]):
138138
"""
139139
Validates properties against an expected port configuration.
140140
@@ -318,7 +318,7 @@ def devclass(self) -> str:
318318
return "peripheral"
319319

320320

321-
class Device:
321+
class VirtualDevice:
322322
def __init__(
323323
self,
324324
port: Optional[Port] = None,
@@ -376,7 +376,7 @@ def __hash__(self):
376376
return hash((self.port, self.device_id))
377377

378378
def __eq__(self, other):
379-
if isinstance(other, (Device, DeviceAssignment)):
379+
if isinstance(other, (VirtualDevice, DeviceAssignment)):
380380
result = (
381381
self.port == other.port
382382
and self.device_id == other.device_id
@@ -398,7 +398,7 @@ def __lt__(self, other):
398398
3. *:<devid>
399399
4. *:*
400400
"""
401-
if isinstance(other, (Device, DeviceAssignment)):
401+
if isinstance(other, (VirtualDevice, DeviceAssignment)):
402402
if self.port == '*' and other.port != '*':
403403
return True
404404
if self.port != '*' and other.port == '*':
@@ -409,7 +409,7 @@ def __lt__(self, other):
409409
reprs[obj].append(obj.device_id)
410410
return reprs[self] < reprs[other]
411411
elif isinstance(other, Port):
412-
_other = Device(other, '*')
412+
_other = VirtualDevice(other, '*')
413413
return self < _other
414414
else:
415415
raise TypeError(
@@ -430,7 +430,7 @@ def from_qarg(
430430
domains,
431431
blind=False,
432432
backend=None,
433-
) -> 'Device':
433+
) -> 'VirtualDevice':
434434
if backend is None:
435435
if blind:
436436
get_domain = domains.get_blind
@@ -444,7 +444,7 @@ def from_qarg(
444444
def from_str(
445445
cls, representation: str, devclass: Optional[str], domains,
446446
blind=False, backend=None
447-
) -> 'Device':
447+
) -> 'VirtualDevice':
448448
if backend is None:
449449
if blind:
450450
get_domain = domains.get_blind
@@ -462,7 +462,7 @@ def _parse(
462462
get_domain: Callable,
463463
backend,
464464
sep: str
465-
) -> 'Device':
465+
) -> 'VirtualDevice':
466466
if backend is None:
467467
backend_name, identity = representation.split(sep, 1)
468468
backend = get_domain(backend_name)
@@ -673,7 +673,7 @@ def _load_classes(bus: str):
673673
return result
674674

675675

676-
class DeviceInfo(Device):
676+
class DeviceInfo(VirtualDevice):
677677
""" Holds all information about a device """
678678

679679
def __init__(
@@ -813,7 +813,7 @@ def interfaces(self) -> List[DeviceInterface]:
813813
return self._interfaces
814814

815815
@property
816-
def parent_device(self) -> Optional[Device]:
816+
def parent_device(self) -> Optional[VirtualDevice]:
817817
"""
818818
The parent device, if any.
819819
@@ -823,7 +823,7 @@ def parent_device(self) -> Optional[Device]:
823823
return self._parent
824824

825825
@property
826-
def subdevices(self) -> List[Device]:
826+
def subdevices(self) -> List[VirtualDevice]:
827827
"""
828828
The list of children devices if any.
829829
@@ -844,7 +844,7 @@ def serialize(self) -> bytes:
844844
"""
845845
Serialize an object to be transmitted via Qubes API.
846846
"""
847-
properties = Device.serialize(self)
847+
properties = VirtualDevice.serialize(self)
848848
# 'attachment', 'interfaces', 'data', 'parent_device'
849849
# are not string, so they need special treatment
850850
default = DeviceInfo(self.port)
@@ -884,7 +884,7 @@ def deserialize(
884884
Recovers a serialized object, see: :py:meth:`serialize`.
885885
"""
886886
head, _, rest = serialization.partition(b' ')
887-
device = Device.from_str(
887+
device = VirtualDevice.from_str(
888888
head.decode('ascii', errors='ignore'), expected_devclass,
889889
domains=None, backend=expected_backend_domain)
890890

@@ -900,7 +900,7 @@ def deserialize(
900900
def _deserialize(
901901
cls,
902902
untrusted_serialization: bytes,
903-
expected_device: Device
903+
expected_device: VirtualDevice
904904
) -> 'DeviceInfo':
905905
"""
906906
Actually deserializes the object.
@@ -1000,13 +1000,13 @@ class DeviceAssignment:
10001000

10011001
def __init__(
10021002
self,
1003-
device: Device,
1003+
device: VirtualDevice,
10041004
frontend_domain=None,
10051005
options=None,
10061006
mode: Union[str, AssignmentMode] = "manual",
10071007
):
10081008
if isinstance(device, DeviceInfo):
1009-
device = Device(device.port, device.device_id)
1009+
device = VirtualDevice(device.port, device.device_id)
10101010
self._device_ident = device
10111011
self.__options = options or {}
10121012
if isinstance(mode, AssignmentMode):
@@ -1020,7 +1020,7 @@ def clone(self, **kwargs):
10201020
Clone object and substitute attributes with explicitly given.
10211021
"""
10221022
kwargs["device"] = kwargs.get(
1023-
"device", Device(
1023+
"device", VirtualDevice(
10241024
Port(self.backend_domain, self.port_id, self.devclass),
10251025
self.device_id
10261026
))
@@ -1042,7 +1042,7 @@ def __hash__(self):
10421042
return hash(self._device_ident)
10431043

10441044
def __eq__(self, other):
1045-
if isinstance(other, (Device, DeviceAssignment)):
1045+
if isinstance(other, (VirtualDevice, DeviceAssignment)):
10461046
result = (
10471047
self.port == other.port
10481048
and self.device_id == other.device_id
@@ -1053,7 +1053,7 @@ def __eq__(self, other):
10531053
def __lt__(self, other):
10541054
if isinstance(other, DeviceAssignment):
10551055
return self._device_ident < other._device_ident
1056-
if isinstance(other, Device):
1056+
if isinstance(other, VirtualDevice):
10571057
return self._device_ident < other
10581058
raise TypeError(
10591059
f"Comparing instances of {type(self)} and '{type(other)}' "
@@ -1078,7 +1078,8 @@ def device_id(self):
10781078
@property
10791079
def device(self) -> DeviceInfo:
10801080
"""Get DeviceInfo object corresponding to this DeviceAssignment"""
1081-
dev = self.backend_domain.devices[self.devclass][self.port_id]
1081+
if self.port_id:
1082+
dev = self.backend_domain.devices[self.devclass][self.port_id]
10821083
# TODO: device identity could not match
10831084
return dev
10841085

@@ -1162,7 +1163,7 @@ def serialize(self) -> bytes:
11621163
def deserialize(
11631164
cls,
11641165
serialization: bytes,
1165-
expected_device: Device,
1166+
expected_device: VirtualDevice,
11661167
) -> 'DeviceAssignment':
11671168
"""
11681169
Recovers a serialized object, see: :py:meth:`serialize`.
@@ -1177,7 +1178,7 @@ def deserialize(
11771178
def _deserialize(
11781179
cls,
11791180
untrusted_serialization: bytes,
1180-
expected_device: Device,
1181+
expected_device: VirtualDevice,
11811182
) -> 'DeviceAssignment':
11821183
"""
11831184
Actually deserializes the object.

qubes/devices.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
import qubes.exc
6666
import qubes.utils
6767
from qubes.device_protocol import (Port, DeviceInfo, UnknownDevice,
68-
DeviceAssignment, Device)
68+
DeviceAssignment, VirtualDevice)
6969

7070

7171
class DeviceNotAssigned(qubes.exc.QubesException, KeyError):
@@ -249,11 +249,11 @@ def load_assignment(self, device_assignment: DeviceAssignment):
249249
assert device_assignment.attach_automatically
250250
self._set.add(device_assignment)
251251

252-
async def update_required(self, device: Device, required: bool):
252+
async def update_required(self, device: VirtualDevice, required: bool):
253253
"""
254254
Update `required` flag of an already attached device.
255255
256-
:param Device device: device for which change required flag
256+
:param VirtualDevice device: device for which change required flag
257257
:param bool required: new assignment:
258258
`False` -> device will be auto-attached to qube
259259
`True` -> device is required to start qube

qubes/tests/devices.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import qubes.devices
2525
from qubes.device_protocol import (Port, DeviceInfo, DeviceAssignment,
26-
DeviceInterface, UnknownDevice, Device)
26+
DeviceInterface, UnknownDevice, VirtualDevice)
2727

2828
import qubes.tests
2929

@@ -515,7 +515,7 @@ def setUp(self):
515515
self.vm = TestVM(self.app, 'vm')
516516

517517
def test_010_serialize(self):
518-
assignment = DeviceAssignment(Device(Port(
518+
assignment = DeviceAssignment(VirtualDevice(Port(
519519
backend_domain=self.vm,
520520
port_id="1-1.1.1",
521521
devclass="bus",
@@ -530,7 +530,7 @@ def test_010_serialize(self):
530530

531531
def test_011_serialize_required(self):
532532
assignment = DeviceAssignment(
533-
Device(Port(
533+
VirtualDevice(Port(
534534
backend_domain=self.vm,
535535
port_id="1-1.1.1",
536536
devclass="bus",
@@ -547,7 +547,7 @@ def test_011_serialize_required(self):
547547

548548
def test_012_serialize_fronted(self):
549549
assignment = DeviceAssignment(
550-
Device(Port(
550+
VirtualDevice(Port(
551551
backend_domain=self.vm,
552552
port_id="1-1.1.1",
553553
devclass="bus",
@@ -564,7 +564,7 @@ def test_012_serialize_fronted(self):
564564

565565
def test_013_serialize_options(self):
566566
assignment = DeviceAssignment(
567-
Device(Port(
567+
VirtualDevice(Port(
568568
backend_domain=self.vm,
569569
port_id="1-1.1.1",
570570
devclass="bus",
@@ -581,7 +581,7 @@ def test_013_serialize_options(self):
581581

582582
def test_014_invalid_serialize(self):
583583
assignment = DeviceAssignment(
584-
Device(Port(
584+
VirtualDevice(Port(
585585
backend_domain=self.vm,
586586
port_id="1-1.1.1",
587587
devclass="bus",
@@ -596,10 +596,10 @@ def test_020_deserialize(self):
596596
b"device_id='*' port_id='1-1.1.1' frontend_domain='vm' "
597597
b"devclass='bus' backend_domain='vm' mode='auto-attach' "
598598
b"_read-only='yes'")
599-
expected_device = Device(Port(self.vm, '1-1.1.1', 'bus'))
599+
expected_device = VirtualDevice(Port(self.vm, '1-1.1.1', 'bus'))
600600
actual = DeviceAssignment.deserialize(serialized, expected_device)
601601
expected = DeviceAssignment(
602-
Device(Port(
602+
VirtualDevice(Port(
603603
backend_domain=self.vm,
604604
port_id="1-1.1.1",
605605
devclass="bus",
@@ -622,7 +622,7 @@ def test_021_invalid_deserialize(self):
622622
b"device_id='*' port_id='1-1.1.1' frontend_domain='vm' "
623623
b"devclass='bus' backend_domain='vm' mode='auto-attach' "
624624
b"_read'only='yes'")
625-
expected_device = Device(Port(self.vm, '1-1.1.1', 'bus'))
625+
expected_device = VirtualDevice(Port(self.vm, '1-1.1.1', 'bus'))
626626
with self.assertRaises(qubes.exc.ProtocolError):
627627
_ = DeviceAssignment.deserialize(serialized, expected_device)
628628

@@ -631,12 +631,12 @@ def test_022_invalid_deserialize_2(self):
631631
b"device_id='*' port_id='1-1.1.1' frontend_domain='vm' "
632632
b"devclass='bus' backend_domain='vm' mode='auto-attach' "
633633
b"read-only='yes'")
634-
expected_device = Device(Port(self.vm, '1-1.1.1', 'bus'))
634+
expected_device = VirtualDevice(Port(self.vm, '1-1.1.1', 'bus'))
635635
with self.assertRaises(qubes.exc.ProtocolError):
636636
_ = DeviceAssignment.deserialize(serialized, expected_device)
637637

638638
def test_030_serialize_and_deserialize(self):
639-
expected_device = Device(Port(self.vm, '1-1.1.1', 'bus'))
639+
expected_device = VirtualDevice(Port(self.vm, '1-1.1.1', 'bus'))
640640
expected = DeviceAssignment(
641641
expected_device,
642642
frontend_domain=self.vm,

qubes/tests/devices_block.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import qubes.tests
2727
import qubes.ext.block
2828
from qubes.device_protocol import DeviceInterface, Port, DeviceInfo, \
29-
DeviceAssignment, Device
29+
DeviceAssignment
3030

3131
modules_disk = '''
3232
<disk type='block' device='disk'>

qubes/tests/integ/audio.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ async def _check_audio_input_status(vm, status):
272272

273273
def attach_mic(self):
274274
deva = qubes.device_protocol.DeviceAssignment(
275-
qubes.device_protocol.Device(
275+
qubes.device_protocol.VirtualDevice(
276276
qubes.device_protocol.Port(self.app.domains[0], 'mic', 'mic')))
277277
self.loop.run_until_complete(
278278
self.testvm1.devices['mic'].attach(deva)
@@ -281,7 +281,7 @@ def attach_mic(self):
281281

282282
def detach_mic(self):
283283
deva = qubes.device_protocol.DeviceAssignment(
284-
qubes.device_protocol.Device(
284+
qubes.device_protocol.VirtualDevice(
285285
qubes.device_protocol.Port(self.app.domains[0], 'mic', 'mic')))
286286
self.loop.run_until_complete(
287287
self.testvm1.devices['mic'].detach(deva)

qubes/tests/integ/devices_block.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def setUp(self):
328328

329329
def test_000_attach_reattach(self):
330330
ass = qubes.device_protocol.DeviceAssignment(
331-
qubes.device_protocol.Device(
331+
qubes.device_protocol.VirtualDevice(
332332
qubes.device_protocol.Port(
333333
self.backend, self.device_ident, 'block')
334334
))

0 commit comments

Comments
 (0)