@@ -227,9 +227,18 @@ def __init__(self, vm):
227227 self .icon = getattr (vm , 'icon' , 'appvm-black' )
228228 self .auto_cleanup = getattr (vm , 'auto_cleanup' , False )
229229
230+ self .available = None
230231 self .state = {'power' : "" , 'outdated' : "" }
231232 self .updateable = getattr (vm , 'updateable' , False )
232- self .update (True )
233+ self .update (update_size_on_disk = True , update_availability = True )
234+
235+ def check_availability_state (self ):
236+ for volume in self .vm .volumes .values ():
237+ try :
238+ volume .validate ()
239+ except exc .QubesVMError :
240+ return False
241+ return True
233242
234243 def update_power_state (self ):
235244 try :
@@ -267,10 +276,15 @@ def update_power_state(self):
267276 except exc .QubesDaemonAccessError :
268277 pass
269278
270- def update (self , update_size_on_disk = False , event = None ):
279+ def update (self ,
280+ update_size_on_disk = False ,
281+ update_availability = False ,
282+ event = None
283+ ):
271284 """
272285 Update VmInfo
273286 :param update_size_on_disk: should disk utilization be updated?
287+ :param update_availability: should disk volume availability be updated?
274288 :param event: name of the event that caused the update, to avoid
275289 updating unnecessary properties; if event is none, update everything
276290 :return: None
@@ -341,6 +355,9 @@ def update(self, update_size_on_disk=False, event=None):
341355 self .disk_float = None
342356 self .disk = None
343357
358+ if self .vm .klass != 'AdminVM' and update_availability :
359+ self .available = self .check_availability_state ()
360+
344361 if self .vm .klass != 'AdminVM' :
345362 self .virt_mode = getattr (self .vm , 'virt_mode' , None )
346363 else :
@@ -691,6 +708,10 @@ def filterAcceptsRow(self, sourceRow, sourceParent):
691708 if not self .window .show_internal_action .isChecked () and vm .internal :
692709 return False
693710
711+ if not self .window .show_unavailable_pool_action .isChecked () and \
712+ not vm .available :
713+ return False
714+
694715 if self .window .show_user .isChecked () \
695716 and vm .klass in ['AppVM' , 'StandaloneVM' ] \
696717 and not getattr (vm .vm , 'template_for_dispvms' , False ) \
@@ -800,6 +821,11 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
800821 self .show_internal_action .setCheckable (True )
801822 self .show_internal_action .toggled .connect (self .invalidate )
802823
824+ self .show_unavailable_pool_action = self .menu_view .addAction (
825+ self .tr ('Show qubes stored on unavailable storage pools' ))
826+ self .show_unavailable_pool_action .setCheckable (True )
827+ self .show_unavailable_pool_action .toggled .connect (self .invalidate )
828+
803829 self .menu_view .addSeparator ()
804830 self .menu_view .addAction (self .action_toolbar )
805831 self .menu_view .addAction (self .action_menubar )
@@ -892,15 +918,27 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
892918 self .size_on_disk_timer .setInterval (1000 * 60 * 5 ) # every 5 mins
893919 self .size_on_disk_timer .start ()
894920
921+ self .volumes_available_timer = QTimer ()
922+ self .volumes_available_timer .timeout .connect (
923+ self .update_halted_availability
924+ )
925+ self .volumes_available_timer .setInterval (
926+ 1000 * 60 * 5
927+ ) # every 5 minutes
928+ self .volumes_available_timer .start ()
929+
895930 self .new_qube = QProcess ()
896931
897932 def eventFilter (self , _object , event ):
898- ''' refresh disk usage every 60s if focused & every 5m in background '''
933+ ''' refresh disk info every 60s if focused & every 5m in background '''
899934 if event .type () == QEvent .Type .WindowActivate :
900935 self .update_running_size ()
936+ self .update_halted_availability ()
901937 self .size_on_disk_timer .setInterval (1000 * 60 )
938+ self .volumes_available_timer .setInterval (1000 * 60 )
902939 elif event .type () == QEvent .Type .WindowDeactivate :
903940 self .size_on_disk_timer .setInterval (1000 * 60 * 5 )
941+ self .volumes_available_timer .setInterval (1000 * 60 * 5 )
904942 return False
905943
906944 def scroll_to_top (self ):
@@ -1018,6 +1056,8 @@ def save_showing(self):
10181056 self .show_standalone .isChecked ())
10191057 self .manager_settings .setValue ('show/internal' ,
10201058 self .show_internal_action .isChecked ())
1059+ self .manager_settings .setValue ('show/unavailable_pool' ,
1060+ self .show_unavailable_pool_action .isChecked ())
10211061 self .manager_settings .setValue ('show/user' ,
10221062 self .show_user .isChecked ())
10231063 self .manager_settings .setValue ('show/all' ,
@@ -1139,6 +1179,14 @@ def update_running_size(self, *_args):
11391179 self .qubes_cache .get_vm (qid = vm .qid ).update (
11401180 update_size_on_disk = True , event = 'disk_size' )
11411181
1182+ def update_halted_availability (self , * _args ):
1183+ if not self .show_unavailable_pool_action .isChecked ():
1184+ for vm in self .qubes_app .domains :
1185+ if not vm .is_running ():
1186+ self .qubes_cache .get_vm (qid = vm .qid ).update (
1187+ update_availability = True , event = 'volume_availability' )
1188+ self .invalidate ()
1189+
11421190 def on_domain_added (self , _submitter , _event , vm , ** _kwargs ):
11431191 try :
11441192 domain = self .qubes_app .domains [vm ]
@@ -1258,6 +1306,9 @@ def load_manager_settings(self):
12581306
12591307 self .show_internal_action .setChecked (self .manager_settings .value (
12601308 'show/internal' , "false" ) == "true" )
1309+ self .show_unavailable_pool_action .setChecked (
1310+ self .manager_settings .value (
1311+ 'show/unavailable_pool' , "false" ) == "true" )
12611312 # load last window size
12621313 self .resize (self .manager_settings .value ("window_size" ,
12631314 QSize (1100 , 600 )))
0 commit comments