@@ -112,7 +112,8 @@ def __init__(self, app_name, qapp, dispatcher):
112112 self .vms : Set [backend .VM ] = set ()
113113 self .dispvm_templates : Set [backend .VM ] = set ()
114114 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 ()
116117 self .dev_update_queue : Set = set ()
117118 self .vm_update_queue : Set = set ()
118119
@@ -144,6 +145,13 @@ def __init__(self, app_name, qapp, dispatcher):
144145 "device-unassign:" + devclass , self .device_unassigned
145146 )
146147
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+
147155 self .dispatcher .add_handler ("domain-shutdown" , self .vm_shutdown )
148156 self .dispatcher .add_handler ("domain-start-failed" , self .vm_shutdown )
149157 self .dispatcher .add_handler ("domain-start" , self .vm_start )
@@ -242,9 +250,12 @@ def initialize_vm_data(self):
242250 self .vms .add (wrapped_vm )
243251 if wrapped_vm .is_dispvm_template :
244252 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 )
248259 except qubesadmin .exc .QubesException :
249260 # we don't have access to VM state
250261 pass
@@ -360,6 +371,24 @@ def device_unassigned(self, vm, _event, device, **_kwargs):
360371 # assigned. Cheers!
361372 return
362373
374+ def pci_action (self , vm , _event , _device , ** _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+
363392 def update_single_feature (self , _vm , _event , feature , value = None , oldvalue = None ):
364393 if not value :
365394 new = set ()
@@ -533,8 +562,9 @@ def vm_start(self, vm, _event, **_kwargs):
533562 internal , attachable = False , False
534563 if attachable and not internal :
535564 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 )
538568
539569 for devclass in DEV_TYPES :
540570 try :
@@ -548,8 +578,9 @@ def vm_start(self, vm, _event, **_kwargs):
548578
549579 def vm_shutdown (self , vm , _event , ** _kwargs ):
550580 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 )
553584
554585 self .vms .discard (wrapped_vm )
555586 self .dispvm_templates .discard (wrapped_vm )
@@ -633,13 +664,13 @@ def show_menu(self, _unused, _event):
633664
634665 menu_items .append (device_item )
635666
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 (
638669 Gtk .MenuItem ,
639670 "activate" ,
640- actionable_widgets .StartSysUsb ( self . sysusb , theme ),
671+ actionable_widgets .StartUSBVM ( wrapped_vm , theme ),
641672 )
642- menu_items .append (sysusb_item )
673+ menu_items .append (usbvm_item )
643674
644675 for item in menu_items :
645676 tray_menu .add (item )
0 commit comments