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