@@ -227,9 +227,31 @@ 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+             if  volume .ephemeral :
238+                 continue 
239+             if  volume .pool  not  in   self .vm .app .pools :
240+                 return  False 
241+             if  volume .source  is  not   None :
242+                 if  volume .source  not  in   (
243+                     pool_volume .vid 
244+                     for  pool  in  self .vm .app .pools .values ()
245+                     for  pool_volume  in  pool .volumes 
246+                 ):
247+                     return  False 
248+             elif  volume .vid  !=  "" :
249+                 if  volume .vid  not  in   (
250+                     pool_volume .vid 
251+                     for  pool_volume  in  self .vm .app .pools [volume .pool ].volumes 
252+                 ):
253+                     return  False 
254+         return  True 
233255
234256    def  update_power_state (self ):
235257        try :
@@ -267,10 +289,15 @@ def update_power_state(self):
267289        except  exc .QubesDaemonAccessError :
268290            pass 
269291
270-     def  update (self , update_size_on_disk = False , event = None ):
292+     def  update (self ,
293+         update_size_on_disk = False ,
294+         update_availability = False ,
295+         event = None 
296+     ):
271297        """ 
272298        Update VmInfo 
273299        :param update_size_on_disk: should disk utilization be updated? 
300+         :param update_availability: should disk volume availability be updated? 
274301        :param event: name of the event that caused the update, to avoid 
275302        updating unnecessary properties; if event is none, update everything 
276303        :return: None 
@@ -341,6 +368,9 @@ def update(self, update_size_on_disk=False, event=None):
341368                self .disk_float  =  None 
342369                self .disk  =  None 
343370
371+         if  self .vm .klass  !=  'AdminVM'  and  update_availability :
372+             self .available  =  self .check_availability_state ()
373+ 
344374        if  self .vm .klass  !=  'AdminVM' :
345375            self .virt_mode  =  getattr (self .vm , 'virt_mode' , None )
346376        else :
@@ -691,6 +721,10 @@ def filterAcceptsRow(self, sourceRow, sourceParent):
691721        if  not  self .window .show_internal_action .isChecked () and  vm .internal :
692722            return  False 
693723
724+         if  not  self .window .show_unavailable_pool_action .isChecked () and  \
725+                 not  vm .available :
726+             return  False 
727+ 
694728        if  self .window .show_user .isChecked () \
695729                and  vm .klass  in  ['AppVM' , 'StandaloneVM' ] \
696730                and  not  getattr (vm .vm , 'template_for_dispvms' , False ) \
@@ -800,6 +834,11 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
800834        self .show_internal_action .setCheckable (True )
801835        self .show_internal_action .toggled .connect (self .invalidate )
802836
837+         self .show_unavailable_pool_action  =  self .menu_view .addAction (
838+             self .tr ('Show qubes stored on unavailable storage pools' ))
839+         self .show_unavailable_pool_action .setCheckable (True )
840+         self .show_unavailable_pool_action .toggled .connect (self .invalidate )
841+ 
803842        self .menu_view .addSeparator ()
804843        self .menu_view .addAction (self .action_toolbar )
805844        self .menu_view .addAction (self .action_menubar )
@@ -892,15 +931,27 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
892931        self .size_on_disk_timer .setInterval (1000  *  60  *  5 )  # every 5 mins 
893932        self .size_on_disk_timer .start ()
894933
934+         self .volumes_available_timer  =  QTimer ()
935+         self .volumes_available_timer .timeout .connect (
936+             self .update_halted_availability 
937+         )
938+         self .volumes_available_timer .setInterval (
939+             1000  *  60  *  5 
940+         )  # every 5 minutes 
941+         self .volumes_available_timer .start ()
942+ 
895943        self .new_qube  =  QProcess ()
896944
897945    def  eventFilter (self , _object , event ):
898-         ''' refresh disk usage  every 60s if focused & every 5m in background ''' 
946+         ''' refresh disk info  every 60s if focused & every 5m in background ''' 
899947        if  event .type () ==  QEvent .Type .WindowActivate :
900948            self .update_running_size ()
949+             self .update_halted_availability ()
901950            self .size_on_disk_timer .setInterval (1000  *  60 )
951+             self .volumes_available_timer .setInterval (1000  *  60 )
902952        elif  event .type () ==  QEvent .Type .WindowDeactivate :
903953            self .size_on_disk_timer .setInterval (1000  *  60  *  5 )
954+             self .volumes_available_timer .setInterval (1000  *  60  *  5 )
904955        return  False 
905956
906957    def  scroll_to_top (self ):
@@ -1018,6 +1069,8 @@ def save_showing(self):
10181069                self .show_standalone .isChecked ())
10191070        self .manager_settings .setValue ('show/internal' ,
10201071                self .show_internal_action .isChecked ())
1072+         self .manager_settings .setValue ('show/unavailable_pool' ,
1073+                 self .show_unavailable_pool_action .isChecked ())
10211074        self .manager_settings .setValue ('show/user' ,
10221075                self .show_user .isChecked ())
10231076        self .manager_settings .setValue ('show/all' ,
@@ -1139,6 +1192,14 @@ def update_running_size(self, *_args):
11391192                self .qubes_cache .get_vm (qid = vm .qid ).update (
11401193                    update_size_on_disk = True , event = 'disk_size' )
11411194
1195+     def  update_halted_availability (self , * _args ):
1196+         if  self .show_unavailable_pool_action .isChecked ():
1197+             for  vm  in  self .qubes_app .domains :
1198+                 if  not  vm .is_running ():
1199+                     self .qubes_cache .get_vm (qid = vm .qid ).update (
1200+                         update_availability = True , event = 'volume_availability' )
1201+             self .invalidate ()
1202+ 
11421203    def  on_domain_added (self , _submitter , _event , vm , ** _kwargs ):
11431204        try :
11441205            domain  =  self .qubes_app .domains [vm ]
@@ -1258,6 +1319,9 @@ def load_manager_settings(self):
12581319
12591320        self .show_internal_action .setChecked (self .manager_settings .value (
12601321            'show/internal' , "false" ) ==  "true" )
1322+         self .show_unavailable_pool_action .setChecked (
1323+             self .manager_settings .value (
1324+                 'show/unavailable_pool' , "false" ) ==  "true" )
12611325        # load last window size 
12621326        self .resize (self .manager_settings .value ("window_size" ,
12631327                                                QSize (1100 , 600 )))
0 commit comments