@@ -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-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,23 @@ def device_unassigned(self, vm, _event, device, **_kwargs):
360
368
# assigned. Cheers!
361
369
return
362
370
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
+
363
388
def update_single_feature (self , _vm , _event , feature , value = None , oldvalue = None ):
364
389
if not value :
365
390
new = set ()
@@ -533,8 +558,9 @@ def vm_start(self, vm, _event, **_kwargs):
533
558
internal , attachable = False , False
534
559
if attachable and not internal :
535
560
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 )
538
564
539
565
for devclass in DEV_TYPES :
540
566
try :
@@ -548,8 +574,9 @@ def vm_start(self, vm, _event, **_kwargs):
548
574
549
575
def vm_shutdown (self , vm , _event , ** _kwargs ):
550
576
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 )
553
580
554
581
self .vms .discard (wrapped_vm )
555
582
self .dispvm_templates .discard (wrapped_vm )
@@ -633,13 +660,13 @@ def show_menu(self, _unused, _event):
633
660
634
661
menu_items .append (device_item )
635
662
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 (
638
665
Gtk .MenuItem ,
639
666
"activate" ,
640
- actionable_widgets .StartSysUsb ( self . sysusb , theme ),
667
+ actionable_widgets .StartUSBVM ( wrapped_vm , theme ),
641
668
)
642
- menu_items .append (sysusb_item )
669
+ menu_items .append (usbvm_item )
643
670
644
671
for item in menu_items :
645
672
tray_menu .add (item )
0 commit comments