@@ -112,7 +112,8 @@ def __init__(self, app_name, qapp, dispatcher):
112
112
self .vms : Set [backend .VM ] = set ()
113
113
self .dispvm_templates : Set [backend .VM ] = set ()
114
114
self .parent_ports_to_hide = []
115
- self .sysusb : backend .VM | None = None
115
+ self .active_usbvms : Set [backend .VM ] = set ()
116
+ self .dormant_usbvms : Set [backend .VM ] = set ()
116
117
self .dev_update_queue : Set = set ()
117
118
self .vm_update_queue : Set = set ()
118
119
@@ -144,6 +145,13 @@ def __init__(self, app_name, qapp, dispatcher):
144
145
"device-unassign:" + devclass , self .device_unassigned
145
146
)
146
147
148
+ self .dispatcher .add_handler ("device-assign:pci" , self .pci_action )
149
+ self .dispatcher .add_handler ("device-unassign:pci" , self .pci_action )
150
+ self .dispatcher .add_handler (
151
+ "domain-pre-delete" ,
152
+ self .remove_domain_item
153
+ )
154
+
147
155
self .dispatcher .add_handler ("domain-shutdown" , self .vm_shutdown )
148
156
self .dispatcher .add_handler ("domain-start-failed" , self .vm_shutdown )
149
157
self .dispatcher .add_handler ("domain-start" , self .vm_start )
@@ -242,9 +250,12 @@ def initialize_vm_data(self):
242
250
self .vms .add (wrapped_vm )
243
251
if wrapped_vm .is_dispvm_template :
244
252
self .dispvm_templates .add (wrapped_vm )
245
- if vm .name == "sys-usb" :
246
- self .sysusb = wrapped_vm
247
- self .sysusb .is_running = vm .is_running ()
253
+ # Keep track of USBVMs
254
+ if wrapped_vm .is_usbvm :
255
+ if vm .is_running ():
256
+ self .active_usbvms .add (wrapped_vm )
257
+ else :
258
+ self .dormant_usbvms .add (wrapped_vm )
248
259
except qubesadmin .exc .QubesException :
249
260
# we don't have access to VM state
250
261
pass
@@ -360,6 +371,24 @@ def device_unassigned(self, vm, _event, device, **_kwargs):
360
371
# assigned. Cheers!
361
372
return
362
373
374
+ def pci_action (self , vm , _event , ** _kwargs ):
375
+ # We assume PCI controllers could be assigned only when qube is shutdown
376
+ wrapped_vm = backend .VM (vm )
377
+ if wrapped_vm .is_usbvm :
378
+ if wrapped_vm not in self .dormant_usbvms :
379
+ self .dormant_usbvms .add (wrapped_vm )
380
+ elif wrapped_vm in self .dormant_usbvms :
381
+ self .dormant_usbvms .discard (wrapped_vm )
382
+
383
+ def remove_domain_item (self , _submitter , _event , vm , ** _kwargs ):
384
+ # In a perfect world, core should trigger `device-unassign:pci` event
385
+ # for PCI devices attached to an HVM before actually removing it and
386
+ # this method should not be necessary. But we are not certain :/
387
+ for wrapped_vm in self .dormant_usbvms :
388
+ if wrapped_vm .name == vm :
389
+ self .dormant_usbvms .discard (wrapped_vm )
390
+ break
391
+
363
392
def update_single_feature (self , _vm , _event , feature , value = None , oldvalue = None ):
364
393
if not value :
365
394
new = set ()
@@ -533,8 +562,9 @@ def vm_start(self, vm, _event, **_kwargs):
533
562
internal , attachable = False , False
534
563
if attachable and not internal :
535
564
self .vms .add (wrapped_vm )
536
- if wrapped_vm == self .sysusb :
537
- self .sysusb .is_running = True
565
+ if wrapped_vm in self .dormant_usbvms :
566
+ self .dormant_usbvms .discard (wrapped_vm )
567
+ self .active_usbvms .add (wrapped_vm )
538
568
539
569
for devclass in DEV_TYPES :
540
570
try :
@@ -548,8 +578,9 @@ def vm_start(self, vm, _event, **_kwargs):
548
578
549
579
def vm_shutdown (self , vm , _event , ** _kwargs ):
550
580
wrapped_vm = backend .VM (vm )
551
- if wrapped_vm == self .sysusb :
552
- self .sysusb .is_running = False
581
+ if wrapped_vm in self .active_usbvms :
582
+ self .active_usbvms .discard (wrapped_vm )
583
+ self .dormant_usbvms .add (wrapped_vm )
553
584
554
585
self .vms .discard (wrapped_vm )
555
586
self .dispvm_templates .discard (wrapped_vm )
@@ -633,13 +664,13 @@ def show_menu(self, _unused, _event):
633
664
634
665
menu_items .append (device_item )
635
666
636
- if not self .sysusb . is_running :
637
- sysusb_item = actionable_widgets .generate_wrapper_widget (
667
+ for wrapped_vm in self .dormant_usbvms :
668
+ usbvm_item = actionable_widgets .generate_wrapper_widget (
638
669
Gtk .MenuItem ,
639
670
"activate" ,
640
- actionable_widgets .StartSysUsb ( self . sysusb , theme ),
671
+ actionable_widgets .StartUSBVM ( wrapped_vm , theme ),
641
672
)
642
- menu_items .append (sysusb_item )
673
+ menu_items .append (usbvm_item )
643
674
644
675
for item in menu_items :
645
676
tray_menu .add (item )
0 commit comments