@@ -296,55 +296,54 @@ def perform_restart(self):
296296
297297 # clear err and perform shutdown/start
298298 self .err = ""
299- self .shutdown_domains (tmpls_to_shutdown )
300- self .restart_vms (to_restart )
301- self .shutdown_domains (to_shutdown )
299+ try :
300+ loop = asyncio .get_event_loop ()
301+ except RuntimeError :
302+ # changes between GLib versions and python versions mean that the above
303+ # can fail on some dom0/gui domain configurations
304+ loop = asyncio .new_event_loop ()
305+ loop .run_until_complete (self .shutdown_domains (tmpls_to_shutdown ))
306+ loop .run_until_complete (self .restart_vms (to_restart ))
307+ loop .run_until_complete (self .shutdown_domains (to_shutdown ))
302308
303309 if self .status is RestartStatus .NONE :
304310 self .status = RestartStatus .OK
305311
306- def shutdown_domains (self , to_shutdown ):
312+ async def shutdown_domains (self , to_shutdown ):
307313 """
308314 Try to shut down vms and wait to finish.
309315 """
310- try :
311- loop = asyncio .get_event_loop ()
312- except RuntimeError :
313- # changes between GLib versions and python versions mean that the above
314- # can fail on some dom0/gui domain configurations
315- loop = asyncio .new_event_loop ()
316- tasks = [asyncio .to_thread (vm .shutdown , force = True , wait = True ) for vm in to_shutdown ]
317- results = loop .run_until_complete (
318- asyncio .gather (* tasks , return_exceptions = True )
316+ failed = await qubesadmin .utils .shutdown (
317+ domains = to_shutdown , force = True , wait = True , logger = self .log
319318 )
320- done = []
321- for vm , res in zip (to_shutdown , results ):
322- if not isinstance (res , BaseException ):
323- self .log .info ("Shutdown %s" , vm .name )
324- done .append (vm )
325- continue
326- self .err += vm .name + " cannot shutdown: " + str (res ) + "\n "
327- self .log .error ("Cannot shutdown %s because %s" , vm .name , str (res ))
328- self .status = RestartStatus .ERROR_TMPL_DOWN
319+ unhandled , used , timedout = failed
320+ if not unhandled and not used and not timedout :
321+ return to_shutdown
322+ self .status = RestartStatus .ERROR_TMPL_DOWN
323+ all_failed = []
324+ if unhandled :
325+ for qube in unhandled :
326+ all_failed .append (qube )
327+ self .err += vm .name + " cannot shutdown: unknown reason\n "
328+ for qube in used :
329+ all_failed .append (qube )
330+ self .err += vm .name + " cannot shutdown: in use\n "
331+ for qube in timedout :
332+ all_failed .append (qube )
333+ self .err += vm .name + " cannot shutdown: timed out\n "
334+ done = [qube for qube in to_shutdown if qube not in all_failed ]
329335 return done
330336
331- def restart_vms (self , to_restart ):
337+ async def restart_vms (self , to_restart ):
332338 """
333339 Try to restart vms.
334340 """
335- shutdowns = self .shutdown_domains (to_restart )
341+ shutdowns = await self .shutdown_domains (to_restart )
336342
343+ # TODO: ben: decide if this is better or worse than the above method
337344 # restart shutdown qubes
338- try :
339- loop = asyncio .get_event_loop ()
340- except RuntimeError :
341- # changes between GLib versions and python versions mean that the above
342- # can fail on some dom0/gui domain configurations
343- loop = asyncio .new_event_loop ()
344345 tasks = [asyncio .to_thread (vm .start ) for vm in shutdowns ]
345- results = loop .run_until_complete (
346- asyncio .gather (* tasks , return_exceptions = True )
347- )
346+ results = await asyncio .gather (* tasks , return_exceptions = True )
348347 for vm , res in zip (shutdowns , results ):
349348 if not isinstance (res , qubesadmin .exc .QubesVMError ):
350349 self .log .info ("Restart %s" , vm .name )
0 commit comments