@@ -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,23 @@ 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+ wrapped_vm = backend .VM (vm )
388+ if wrapped_vm in self .dormant_usbvms :
389+ self .dormant_usbvms .discard (wrapped_vm )
390+
363391 def update_single_feature (self , _vm , _event , feature , value = None , oldvalue = None ):
364392 if not value :
365393 new = set ()
@@ -533,8 +561,9 @@ def vm_start(self, vm, _event, **_kwargs):
533561 internal , attachable = False , False
534562 if attachable and not internal :
535563 self .vms .add (wrapped_vm )
536- if wrapped_vm == self .sysusb :
537- self .sysusb .is_running = True
564+ if wrapped_vm in self .dormant_usbvms :
565+ self .dormant_usbvms .discard (wrapped_vm )
566+ self .active_usbvms .add (wrapped_vm )
538567
539568 for devclass in DEV_TYPES :
540569 try :
@@ -548,8 +577,9 @@ def vm_start(self, vm, _event, **_kwargs):
548577
549578 def vm_shutdown (self , vm , _event , ** _kwargs ):
550579 wrapped_vm = backend .VM (vm )
551- if wrapped_vm == self .sysusb :
552- self .sysusb .is_running = False
580+ if wrapped_vm in self .active_usbvms :
581+ self .active_usbvms .discard (wrapped_vm )
582+ self .dormant_usbvms .add (wrapped_vm )
553583
554584 self .vms .discard (wrapped_vm )
555585 self .dispvm_templates .discard (wrapped_vm )
@@ -633,13 +663,13 @@ def show_menu(self, _unused, _event):
633663
634664 menu_items .append (device_item )
635665
636- if not self .sysusb . is_running :
637- sysusb_item = actionable_widgets .generate_wrapper_widget (
666+ for wrapped_vm in self .dormant_usbvms :
667+ usbvm_item = actionable_widgets .generate_wrapper_widget (
638668 Gtk .MenuItem ,
639669 "activate" ,
640- actionable_widgets .StartSysUsb ( self . sysusb , theme ),
670+ actionable_widgets .StartUSBVM ( wrapped_vm , theme ),
641671 )
642- menu_items .append (sysusb_item )
672+ menu_items .append (usbvm_item )
643673
644674 for item in menu_items :
645675 tray_menu .add (item )
0 commit comments