@@ -216,6 +216,9 @@ class Services:
216216 # log file stream lag
217217 CAT_LOG_SLEEP = 1
218218
219+ # command timeout for commands which start schedulers
220+ START_TIMEOUT = 120
221+
219222 @staticmethod
220223 def _error (message : Union [Exception , str ]):
221224 """Format error case response."""
@@ -235,9 +238,9 @@ def _return(message: str):
235238 @classmethod
236239 async def clean (
237240 cls ,
241+ workflows_mgr : 'WorkflowsManager' ,
238242 workflows : Iterable ['Tokens' ],
239243 args : dict ,
240- workflows_mgr : 'WorkflowsManager' ,
241244 executor : 'Executor' ,
242245 log : 'Logger'
243246 ):
@@ -278,20 +281,21 @@ async def scan(
278281 return cls ._return ("Scan requested" )
279282
280283 @classmethod
281- async def play (
284+ async def run_command (
282285 cls ,
286+ command : tuple [str ],
283287 workflows : Iterable [Tokens ],
284288 args : Dict [str , Any ],
285- workflows_mgr : 'WorkflowsManager' ,
286289 log : 'Logger' ,
287- ) -> List [Union [bool , str ]]:
288- """Calls `cylc play`."""
290+ timeout : int ,
291+ ) -> List [bool | str ]:
292+ """Calls the specified Cylc command."""
289293 cylc_version = args .pop ('cylc_version' , None )
290294 results : Dict [str , str ] = {}
291295 failed = False
292296 for tokens in workflows :
293297 try :
294- cmd = _build_cmd (['cylc' , 'play' , '--color=never' ], args )
298+ cmd = _build_cmd (['cylc' , * command , '--color=never' ], args )
295299
296300 if tokens ['user' ] and tokens ['user' ] != getuser ():
297301 return cls ._error (
@@ -322,7 +326,7 @@ async def play(
322326 stderr = PIPE ,
323327 text = True
324328 )
325- ret_code = proc .wait (timeout = 120 )
329+ ret_code = proc .wait (timeout = timeout )
326330
327331 if ret_code :
328332 msg = f"Command failed ({ ret_code } ): { cmd_repr } "
@@ -335,7 +339,7 @@ async def play(
335339 )
336340 failed = True
337341 else :
338- results [wflow ] = 'started '
342+ results [wflow ] = 'Command succeeded '
339343
340344 except Exception as exc : # unexpected error
341345 log .exception (exc )
@@ -351,10 +355,53 @@ async def play(
351355 )
352356 )
353357
358+ return []
359+
360+ @classmethod
361+ async def play (
362+ cls , workflows_mgr : 'WorkflowsManager' , * args , ** kwargs
363+ ) -> List [Union [bool , str ]]:
364+ """Calls `cylc play`."""
365+ # run `cylc play`
366+ ret = await cls .run_command (
367+ ('play' ,),
368+ * args ,
369+ ** kwargs ,
370+ timeout = cls .START_TIMEOUT ,
371+ )
372+
354373 # trigger a re-scan
355374 await workflows_mgr .scan ()
356- # send a success message
357- return cls ._return ('Workflow(s) started' )
375+
376+ # return results
377+ if ret :
378+ return ret
379+ else :
380+ # send a success message
381+ return cls ._return ('Workflow(s) started' )
382+
383+ @classmethod
384+ async def validate_reinstall (
385+ cls , workflows_mgr : 'WorkflowsManager' , * args , ** kwargs
386+ ) -> List [Union [bool , str ]]:
387+ """Calls `cylc validate-reinstall`."""
388+ # run `cylc play`
389+ ret = await cls .run_command (
390+ ('validate-reinstall' , '--yes' ),
391+ * args ,
392+ ** kwargs ,
393+ timeout = cls .START_TIMEOUT ,
394+ )
395+
396+ # trigger a re-scan
397+ await workflows_mgr .scan ()
398+
399+ # return results
400+ if ret :
401+ return ret
402+ else :
403+ # send a success message
404+ return cls ._return ('Workflow(s) reinstalled' )
358405
359406 @staticmethod
360407 async def enqueue (stream , queue ):
@@ -592,19 +639,26 @@ async def service(
592639
593640 if command == 'clean' : # noqa: SIM116
594641 return await Services .clean (
642+ self .workflows_mgr ,
595643 workflows ,
596644 kwargs ,
597- self .workflows_mgr ,
598645 log = self .log ,
599646 executor = self .executor
600647 )
601648 elif command == 'play' :
602649 return await Services .play (
650+ self .workflows_mgr ,
603651 workflows ,
604652 kwargs ,
605- self .workflows_mgr ,
606653 log = self .log
607654 )
655+ elif command == 'validate_reinstall' :
656+ return await Services .validate_reinstall (
657+ self .workflows_mgr ,
658+ workflows ,
659+ kwargs ,
660+ log = self .log ,
661+ )
608662 elif command == 'scan' :
609663 return await Services .scan (
610664 kwargs ,
0 commit comments