@@ -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,10 @@ 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 ("domain-delete" , self .remove_domain_item )
151+
147152 self .dispatcher .add_handler ("domain-shutdown" , self .vm_shutdown )
148153 self .dispatcher .add_handler ("domain-start-failed" , self .vm_shutdown )
149154 self .dispatcher .add_handler ("domain-start" , self .vm_start )
@@ -242,9 +247,12 @@ def initialize_vm_data(self):
242247 self .vms .add (wrapped_vm )
243248 if wrapped_vm .is_dispvm_template :
244249 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 )
248256 except qubesadmin .exc .QubesException :
249257 # we don't have access to VM state
250258 pass
@@ -360,6 +368,23 @@ def device_unassigned(self, vm, _event, device, **_kwargs):
360368 # assigned. Cheers!
361369 return
362370
371+ def pci_action (self , vm , _event , _device , ** _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+ wrapped_vm = backend .VM (vm )
385+ if wrapped_vm in self .dormant_usbvms :
386+ self .dormant_usbvms .discard (wrapped_vm )
387+
363388 def update_single_feature (self , _vm , _event , feature , value = None , oldvalue = None ):
364389 if not value :
365390 new = set ()
@@ -533,8 +558,9 @@ def vm_start(self, vm, _event, **_kwargs):
533558 internal , attachable = False , False
534559 if attachable and not internal :
535560 self .vms .add (wrapped_vm )
536- if wrapped_vm == self .sysusb :
537- self .sysusb .is_running = True
561+ if wrapped_vm in self .dormant_usbvms :
562+ self .dormant_usbvms .discard (wrapped_vm )
563+ self .active_usbvms .add (wrapped_vm )
538564
539565 for devclass in DEV_TYPES :
540566 try :
@@ -548,8 +574,9 @@ def vm_start(self, vm, _event, **_kwargs):
548574
549575 def vm_shutdown (self , vm , _event , ** _kwargs ):
550576 wrapped_vm = backend .VM (vm )
551- if wrapped_vm == self .sysusb :
552- self .sysusb .is_running = False
577+ if wrapped_vm in self .active_usbvms :
578+ self .active_usbvms .discard (wrapped_vm )
579+ self .dormant_usbvms .add (wrapped_vm )
553580
554581 self .vms .discard (wrapped_vm )
555582 self .dispvm_templates .discard (wrapped_vm )
@@ -633,13 +660,13 @@ def show_menu(self, _unused, _event):
633660
634661 menu_items .append (device_item )
635662
636- if not self .sysusb . is_running :
637- sysusb_item = actionable_widgets .generate_wrapper_widget (
663+ for wrapped_vm in self .dormant_usbvms :
664+ usbvm_item = actionable_widgets .generate_wrapper_widget (
638665 Gtk .MenuItem ,
639666 "activate" ,
640- actionable_widgets .StartSysUsb ( self . sysusb , theme ),
667+ actionable_widgets .StartUSBVM ( wrapped_vm , theme ),
641668 )
642- menu_items .append (sysusb_item )
669+ menu_items .append (usbvm_item )
643670
644671 for item in menu_items :
645672 tray_menu .add (item )
0 commit comments