Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new device API #274

Merged
merged 43 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b03800d
A proposal for new devices API
marmarta Nov 20, 2023
ee1253e
q-dev: init
piotrbartman Nov 21, 2023
c2e0248
q-dev: (optional feature) qvm-device info
piotrbartman Nov 27, 2023
dc9d161
q-dev: partially implemented DeviceInfo API + Device Interfaces
piotrbartman Dec 5, 2023
ad0ad04
q-dev: add fronted_domain to keep one version of DeviceInfo API
piotrbartman Dec 11, 2023
73d9197
q-dev: catch errors in deserialize
piotrbartman Dec 13, 2023
a64ca39
q-dev: update DeviceInfo API
piotrbartman Dec 29, 2023
141ca73
q-dev: simplify parent_device
piotrbartman Dec 29, 2023
e5a4420
q-dev: DeviceInterface
piotrbartman Dec 30, 2023
5f7003d
q-dev: persistent -> required
piotrbartman Jan 4, 2024
e8f4817
q-dev: DeviceAssignment
piotrbartman Jan 5, 2024
02547cd
q-dev: Microphone Interface
piotrbartman Jan 18, 2024
3f260f1
q-dev: --list-device-classes do not require positional unused argument
piotrbartman Jan 20, 2024
4044935
q-dev: allow unassign unknown device
piotrbartman Jan 23, 2024
d206236
q-dev: readable serialization
piotrbartman Jan 23, 2024
160f50e
q-dev: DeviceAssignment serialization
piotrbartman Jan 29, 2024
ff0d883
q-dev: full identity
piotrbartman Jan 30, 2024
3f85ae7
q-dev: auto-attach and required as immutable properties
piotrbartman Jan 31, 2024
06da56f
q-dev: handle DeviceInfo.attachment
piotrbartman Feb 1, 2024
865173d
q-dev: warn user that (un)assign is not (de/at)tach
piotrbartman Feb 1, 2024
7f3519f
q-dev: prevent non-pci device as required
piotrbartman Feb 12, 2024
38f7e0b
q-dev: full_identity -> self_identity
piotrbartman Feb 17, 2024
b654864
q-dev: block auto-attach
piotrbartman Feb 19, 2024
2e3b1f8
q-dev: allow block devices to be required
piotrbartman Feb 19, 2024
de0e882
q-dev: port assignment
piotrbartman Feb 20, 2024
2e31a4b
q-dev: @marmarek comments
piotrbartman Mar 19, 2024
ac4d52a
q-dev: device protocol
piotrbartman Mar 19, 2024
9080609
q-dev: refactor device protocol
piotrbartman Mar 22, 2024
7f36eb4
q-dev: device protocol minor fixes
piotrbartman Mar 24, 2024
bd5c621
q-dev: broder allowance of names
piotrbartman Mar 24, 2024
f5265d4
q-dev: pylint
piotrbartman Mar 26, 2024
6468b20
q-dev: fix `qvm-start VM --drive cdrom`
piotrbartman Apr 19, 2024
a8650a7
q-dev: update tests for qvm-device and app
piotrbartman Apr 22, 2024
1ec3549
q-dev: update and fix tests for backup
piotrbartman Apr 23, 2024
dd7882b
q-dev: update and fix tests for qvm-start
piotrbartman Apr 23, 2024
b5d48c2
q-dev: make pylint happy
piotrbartman Apr 23, 2024
bbb2a02
q-dev: fix serialization
piotrbartman Apr 28, 2024
623c3ef
q-dev: update device protocol
piotrbartman Apr 30, 2024
dc2cda7
q-dev: update device protocol v2
piotrbartman May 8, 2024
dff2996
q-dev: update device protocol v3
piotrbartman May 13, 2024
9d3abb2
q-dev: make pylint happy
piotrbartman May 16, 2024
e11de7f
q-dev: update device protocol v4
piotrbartman May 18, 2024
7708545
q-dev: update tests
piotrbartman May 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions doc/manpages/qvm-device.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ Synopsis
| :command:`qvm-device` *DEVICE_CLASS* {list,ls,l} [*options*] <*vm-name*>
| :command:`qvm-device` *DEVICE_CLASS* {attach,at,a} [*options*] <*vm-name*> <*device*>
| :command:`qvm-device` *DEVICE_CLASS* {detach,dt,d} [*options*] <*vm-name*> [<*device*>]
| :command:`qvm-*DEVICE_CLASS*` {list,ls,l,attach,at,a,detach,dt,d} [*options*] <*vmname*> ...
| :command:`qvm-device` *DEVICE_CLASS* {assign,s} [*options*] <*vm-name*> <*device*>
| :command:`qvm-device` *DEVICE_CLASS* {unassign,u} [*options*] <*vm-name*> [<*device*>]
| :command:`qvm-device` *DEVICE_CLASS* {info,i} [*options*] <*vm-name*> [<*device*>]
| :command:`qvm-*DEVICE_CLASS*` {list,ls,l,attach,at,a,detach,dt,d,assign,s,unassign,u,info,i} [*options*] <*vmname*> ...

.. note:: :command:`qvm-block`, :command:`qvm-usb` and :command:`qvm-pci` are just aliases for :command:`qvm-device block`, :command:`qvm-device usb` and :command:`qvm-device pci` respectively.

Expand Down Expand Up @@ -73,7 +76,7 @@ Attach the device with *DEVICE_ID* from *BACKEND_DOMAIN* to the domain *VMNAME*

.. option:: --persistent, -p

Attach device persistently, which means have it attached also after qube restart.
Alias for `assign --required` for backward compatibility.

aliases: a, at

Expand All @@ -87,6 +90,52 @@ If no device is given, detach all *DEVICE_CLASS* devices.

aliases: d, dt

assign
^^^^^^

| :command:`qvm-device` *DEVICE_CLASS* assign [-h] [--verbose] [--quiet] [--ro] *VMNAME* *BACKEND_DOMAIN:DEVICE_ID*

Assign the device with *DEVICE_ID* from *BACKEND_DOMAIN* to the domain *VMNAME*

.. option:: --option, -o

Specify device-class specific option, use `name=value` format. You can
specify this option multiple times. See below for options specific to
different device classes.

.. option:: --ro

Alias for the `read-only=yes` option. If you specify both `--ro` and
`--option read-only=no`, `--ro` takes precedence.

.. option:: --required, -r

Assign device persistently which means it will be required to the qube's startup and then automatically attached.

.. option:: --port

Ignore device presented identity and attach any device connected to the given port number.

aliases: s

unassign
^^^^^^^^

| :command:`qvm-device` *DEVICE_CLASS* unassign [-h] [--verbose] [--quiet] *VMNAME* *BACKEND_DOMAIN:DEVICE_ID*

Remove assignment of device with *BACKEND_DOMAIN:DEVICE_ID* from domain *VMNAME*.
If no device is given, remove assignments of all *DEVICE_CLASS* devices.

aliases: u

info
^^^^

| :command:`qvm-device` *DEVICE_CLASS* info [-h] [--verbose] [--quiet] *VMNAME* *BACKEND_DOMAIN:DEVICE_ID*

Show info about the device with *DEVICE_ID* from *BACKEND_DOMAIN* attached to the domain *VMNAME*

aliases: i

Device classes
==============
Expand Down Expand Up @@ -127,5 +176,6 @@ Authors
| Rafal Wojtczuk <rafal at invisiblethingslab dot com>
| Marek Marczykowski <marmarek at invisiblethingslab dot com>
| Frédéric Pierret <frederic.pierret at qubes dash os dot org>
| Piotr Bartman-Szwarc <prbartman at invisiblethingslab dot com>

| For complete author list see: https://github.com/QubesOS/qubes-core-admin-client.git
2 changes: 1 addition & 1 deletion doc/manpages/qvm-volume.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. program:: qvm-volume

:program:`qvm-volume` -- Qubes volume and block device management
================================================================
=================================================================

Synopsis
--------
Expand Down
15 changes: 6 additions & 9 deletions qubesadmin/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import qubesadmin.utils
import qubesadmin.vm
import qubesadmin.config
import qubesadmin.devices
import qubesadmin.device_protocol

try:
import qubesdb
Expand Down Expand Up @@ -542,14 +542,11 @@ def clone_vm(self, src_vm, new_name, new_cls=None, pool=None, pools=None,
if not ignore_devices:
try:
for devclass in src_vm.devices:
for assignment in src_vm.devices[devclass].assignments(
persistent=True):
new_assignment = qubesadmin.devices.DeviceAssignment(
backend_domain=assignment.backend_domain,
ident=assignment.ident,
options=assignment.options,
persistent=assignment.persistent)
dst_vm.devices[devclass].attach(new_assignment)
for assignment in (
src_vm.devices[devclass].get_assigned_devices()):
new_assignment = assignment.clone(
frontend_domain=dst_vm)
dst_vm.devices[devclass].assign(new_assignment)
except qubesadmin.exc.QubesException:
if not ignore_errors:
del self.domains[dst_vm.name]
Expand Down
9 changes: 4 additions & 5 deletions qubesadmin/backup/core2.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,11 +336,10 @@ def import_core2_vm(self, element):
if pcidevs:
pcidevs = ast.literal_eval(pcidevs)
for pcidev in pcidevs:
if not pci_strictreset:
vm.devices['pci'][('dom0', pcidev.replace(':', '_'))] = {
'no-strict-reset': True}
else:
vm.devices['pci'][('dom0', pcidev.replace(':', '_'))] = {}
ident = pcidev.replace(':', '_')
options = {'no-strict-reset': True} if not pci_strictreset else {}
options['required'] = True
vm.devices['pci'][('dom0', ident)] = options

def load(self):
with open(self.store, encoding='utf-8') as fh:
Expand Down
4 changes: 4 additions & 0 deletions qubesadmin/backup/core3.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

import qubesadmin.backup
import qubesadmin.firewall
from qubesadmin import device_protocol


class Core3VM(qubesadmin.backup.BackupVM):
'''VM object'''
Expand Down Expand Up @@ -125,6 +127,8 @@ def import_core3_vm(self, element):
for opt_node in node.findall('./option'):
opt_name = opt_node.get('name')
options[opt_name] = opt_node.text
options['required'] = device_protocol.qbool(
node.get('required', 'yes'))
vm.devices[bus_name][(backend_domain, ident)] = options

# extract base properties
Expand Down
18 changes: 13 additions & 5 deletions qubesadmin/backup/restore.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
from qubesadmin.backup import BackupVM
from qubesadmin.backup.core2 import Core2Qubes
from qubesadmin.backup.core3 import Core3Qubes
from qubesadmin.devices import DeviceAssignment
from qubesadmin.device_protocol import DeviceAssignment
from qubesadmin.exc import QubesException
from qubesadmin.utils import size_to_human

Expand Down Expand Up @@ -2087,16 +2087,24 @@ def _restore_vms_metadata(self, restore_info):
for bus in vm.devices:
for backend_domain, ident in vm.devices[bus]:
options = vm.devices[bus][(backend_domain, ident)]
if 'required' in options:
required = options['required']
del options['required']
else:
required = False
assignment = DeviceAssignment(
backend_domain=backend_domain,
backend_domain=self.app.domains[backend_domain],
ident=ident,
devclass=bus,
options=options,
persistent=True)
attach_automatically=True,
required=required,
)
try:
if not self.options.verify_only:
new_vm.devices[bus].attach(assignment)
new_vm.devices[bus].assign(assignment)
except Exception as err: # pylint: disable=broad-except
self.log.error('Error attaching device %s:%s to %s: %s',
self.log.error('Error assigning device %s:%s to %s: %s',
bus, ident, vm.name, err)

# Set VM dependencies - only non-default setting
Expand Down
Loading