Skip to content

Commit cbf3e74

Browse files
committed
q-dev: add self_identity do device identity
1 parent 182cf50 commit cbf3e74

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

qubesadmin/device_protocol.py

+33-12
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ def check_device_properties(
236236

237237
if properties.get('ident', expected.ident) != expected.ident:
238238
raise UnexpectedDeviceProperty(
239-
f"Got device with id: {properties['ident']} "
240-
f"when expected id: {expected.ident}.")
239+
f"Got device from port: {properties['ident']} "
240+
f"when expected port: {expected.ident}.")
241241
properties['ident'] = expected.ident
242242

243243
if properties.get('devclass', expected.devclass) != expected.devclass:
@@ -679,12 +679,16 @@ def deserialize(
679679
"""
680680
Recovers a serialized object, see: :py:meth:`serialize`.
681681
"""
682-
ident, _, rest = serialization.partition(b' ')
683-
ident = ident.decode('ascii', errors='ignore')
682+
identity, _, rest = serialization.partition(b' ')
683+
identity = identity.decode('ascii', errors='ignore')
684+
ident, devid = identity.split(':', 1)
685+
if devid == 'None': # TODO
686+
devid = None
684687
device = UnknownDevice(
685688
backend_domain=expected_backend_domain,
686689
ident=ident,
687690
devclass=expected_devclass,
691+
self_identity=devid
688692
)
689693

690694
try:
@@ -699,27 +703,34 @@ def deserialize(
699703
def _deserialize(
700704
cls,
701705
untrusted_serialization: bytes,
702-
expected_port: Port
706+
expected_device: 'DeviceInfo'
703707
) -> 'DeviceInfo':
704708
"""
705709
Actually deserializes the object.
706710
"""
707711
properties, options = cls.unpack_properties(untrusted_serialization)
708712
properties.update(options)
709713

710-
cls.check_device_properties(expected_port, properties)
714+
cls.check_device_properties(expected_device, properties)
711715

712716
if 'attachment' not in properties or not properties['attachment']:
713717
properties['attachment'] = None
714718
else:
715-
app = expected_port.backend_domain.app
719+
app = expected_device.backend_domain.app
716720
properties['attachment'] = app.domains.get_blind(
717721
properties['attachment'])
718722

719-
if properties['devclass'] != expected_port.devclass:
723+
if properties['devclass'] != expected_device.devclass:
720724
raise UnexpectedDeviceProperty(
721725
f"Got {properties['devclass']} device "
722-
f"when expected {expected_port.devclass}.")
726+
f"when expected {expected_device.devclass}.")
727+
728+
if (expected_device.self_identity is not None and
729+
properties['self_identity'] != expected_device.self_identity):
730+
raise UnexpectedDeviceProperty(
731+
f"Unrecognized device identity '{properties['self_identity']}' "
732+
f"expected '{expected_device.self_identity}'"
733+
)
723734

724735
if 'interfaces' in properties:
725736
interfaces = properties['interfaces']
@@ -730,7 +741,7 @@ def _deserialize(
730741

731742
if 'parent_ident' in properties:
732743
properties['parent'] = Port(
733-
backend_domain=expected_port.backend_domain,
744+
backend_domain=expected_device.backend_domain,
734745
ident=properties['parent_ident'],
735746
devclass=properties['parent_devclass'],
736747
)
@@ -986,12 +997,14 @@ def deserialize(
986997
cls,
987998
serialization: bytes,
988999
expected_port: Port,
1000+
expected_identity: Optional[str],
9891001
) -> 'DeviceAssignment':
9901002
"""
9911003
Recovers a serialized object, see: :py:meth:`serialize`.
9921004
"""
9931005
try:
994-
result = cls._deserialize(serialization, expected_port)
1006+
result = cls._deserialize(
1007+
serialization, expected_port, expected_identity)
9951008
except Exception as exc:
9961009
raise ProtocolError() from exc
9971010
return result
@@ -1001,16 +1014,24 @@ def _deserialize(
10011014
cls,
10021015
untrusted_serialization: bytes,
10031016
expected_port: Port,
1017+
expected_identity: Optional[str],
10041018
) -> 'DeviceAssignment':
10051019
"""
10061020
Actually deserializes the object.
10071021
"""
10081022
properties, options = cls.unpack_properties(untrusted_serialization)
10091023
properties['options'] = options
1024+
import sys; print(f'{expected_identity=}', f'{expected_port=}', file=sys.stderr) # TODO debug
10101025

10111026
cls.check_device_properties(expected_port, properties)
10121027
del properties['backend_domain']
10131028
del properties['ident']
10141029
del properties['devclass']
10151030

1016-
return cls(expected_port, **properties)
1031+
assignment = cls(expected_port, **properties)
1032+
if (expected_identity
1033+
and assignment.device.self_identity != expected_identity):
1034+
raise UnexpectedDeviceProperty(
1035+
f"Got device with identity {assignment.device.self_identity}"
1036+
f"when expected devices with identity {expected_identity}.")
1037+
return assignment

qubesadmin/devices.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,17 @@ def get_attached_devices(self) -> Iterable[DeviceAssignment]:
154154
None, 'admin.vm.device.{}.Attached'.format(self._class)).decode()
155155
for assignment_str in assignments_str.splitlines():
156156
device, _, untrusted_rest = assignment_str.partition(' ')
157-
backend_domain_name, ident = device.split('+', 1)
157+
backend_domain_name, identity = device.split('+', 1)
158+
ident, devid = identity.split(':', 1)
159+
if devid == 'None': # TODO
160+
devid = None
158161
backend_domain = self._vm.app.domains.get_blind(backend_domain_name)
162+
import sys; print(f"{identity=}, {ident=}, {devid=}", file=sys.stderr) # TODO debug
159163

160164
yield DeviceAssignment.deserialize(
161165
untrusted_rest.encode('ascii'),
162-
expected_port=Port(backend_domain, ident, self._class)
166+
expected_port=Port(backend_domain, ident, self._class),
167+
expected_identity=devid,
163168
)
164169

165170
def get_assigned_devices(
@@ -173,13 +178,17 @@ def get_assigned_devices(
173178
assignments_str = self._vm.qubesd_call(
174179
None, 'admin.vm.device.{}.Assigned'.format(self._class)).decode()
175180
for assignment_str in assignments_str.splitlines():
176-
port, _, untrusted_rest = assignment_str.partition(' ')
177-
backend_domain_name, ident = port.split('+', 1)
181+
device, _, untrusted_rest = assignment_str.partition(' ')
182+
backend_domain_name, identity = device.split('+', 1)
183+
ident, devid = identity.split(':', 1)
184+
if devid == 'None': # TODO
185+
devid = None
178186
backend_domain = self._vm.app.domains.get_blind(backend_domain_name)
179187

180188
assignment = DeviceAssignment.deserialize(
181189
untrusted_rest.encode('ascii'),
182-
expected_port=Port(backend_domain, ident, self._class)
190+
expected_port=Port(backend_domain, ident, self._class),
191+
expected_identity=devid,
183192
)
184193
if not required_only or assignment.required:
185194
yield assignment

0 commit comments

Comments
 (0)