#!/usr/bin/env python3 import time import sys, argparse ##import utils.Logger as L ##from .Agent import Agent ##sys.path.append("..") ###from agent.Agent import Agent, build_agent sys.path.append("../../../..") #from src.core.pyros_django.common.models import AgentCmd from src.core.pyros_django.agent.Agent import Agent, build_agent #from src.core.pyros_django.common.models import AgentCmd from typing import List, Tuple, Union, Any ##log = L.setupLogger("AgentXTaskLogger", "AgentX") class AgentBasic(Agent): # FOR TEST ONLY # Run this agent in simulator mode TEST_MODE = False # Run the assertion tests at the end TEST_WITH_FINAL_TEST = False #TEST_MAX_DURATION_SEC = None TEST_MAX_DURATION_SEC = 400 # Who should I send commands to ? TEST_COMMANDS_DEST = "myself" #TEST_COMMANDS_DEST = "AgentB" # Scenario to be executed # @override _AGENT_SPECIFIC_COMMANDS = { # Format : “cmd_name” : (timeout, exec_mode, tooltip) # Error raising commands "do_cmd_unimplemented_and_declared": (3, Agent.EXEC_MODE.SEQUENTIAL, ''), "cmd_misnamed_and_declared": (3, Agent.EXEC_MODE.SEQUENTIAL, ''), "do_cmd_raising_some_exception": (3, Agent.EXEC_MODE.SEQUENTIAL, ''), # Normal Commands #("set_specific2", 5, 0), "do_specific10": (1, Agent.EXEC_MODE.SEQUENTIAL, ''), "do_specific30": (3, Agent.EXEC_MODE.SEQUENTIAL, ''), "do_cmd_with_long_exec_time": (50, Agent.EXEC_MODE.THREAD, 'A command that takes a long time to exec'), } # Deactivate some tests, so that test scenario runs faster during DEV # on DEV COMMIT_ONLY = False # on commit only #COMMIT_ONLY = True VALIDITY=120 # @override _TEST_COMMANDS_LIST = [ # Format : (DO_IT, "self cmd_name cmd_args", validity, "expected_result", expected_status), #("self do_stop now", 200, '', Agent.CMD_STATUS.CMD_EXECUTED), # do_stop #("self do_stop now", 200, 'STOPPING now', Agent.CMD_STATUS.CMD_EXECUTED), #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), #("self do_stop asap", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), # get_specific_cmds # prio #(True, " self get_all_cmds ", 100, # noprio (True, " self get_all_cmds noprio ", 100, None, #'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30();do_cmd_raising_some_exception();do_cmd_unimplemented(U)', Agent.CMD_STATUS.CMD_EXECUTED ), (COMMIT_ONLY, "self do_restart asap", VALIDITY, 'RESTARTING asap', Agent.CMD_STATUS.CMD_EXECUTED), # do_restart (True, "self do_cmd_with_long_exec_time", VALIDITY, None, Agent.CMD_STATUS.CMD_EXECUTED), #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), # ---------------------------------------------------- # ------ A - ERROR CASES - from PENDING status ------- # ---------------------------------------------------- # - Error case 1 - CMD_INVALID # a) Misnamed commands (COMMIT_ONLY, "self cmd_misnamed_and_declared", VALIDITY, "Command misnamed, must start with do_, get_, or set_", Agent.CMD_STATUS.CMD_INVALID), (COMMIT_ONLY, "self cmd_misnamed_and_undeclared", VALIDITY, None, Agent.CMD_STATUS.CMD_INVALID), # b) Unknwon command ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN), (COMMIT_ONLY, "self do_cmd_unexisting", VALIDITY, 'EXCEPTION on command do_cmd_unexisting: Unknown command', Agent.CMD_STATUS.CMD_INVALID), # c) Bad parameters (missing or too many, or bad type) # - missing args (COMMIT_ONLY, "self do_specific10", VALIDITY, 'EXCEPTION on command do_specific10: Command has bad, missing, or too many argument(s)', Agent.CMD_STATUS.CMD_INVALID), # - missing args (COMMIT_ONLY, "self do_specific10 2 ", VALIDITY, None, Agent.CMD_STATUS.CMD_INVALID), # - too many args (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", VALIDITY, None, Agent.CMD_STATUS.CMD_INVALID), # - bad type (True, "self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", VALIDITY, None, Agent.CMD_STATUS.CMD_INVALID), (True, "self set_mode unknown_mode", VALIDITY, None, Agent.CMD_STATUS.CMD_INVALID), (True, "self do_eval bad_arg", VALIDITY, None, Agent.CMD_STATUS.CMD_INVALID), # - OK #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED), # - Error case 2 - Unimplemented command (in agent specific commands list) # - Error case 3 - CMD_UNIMPLEMENTED (True, "self do_cmd_unimplemented_and_declared", VALIDITY, None, Agent.CMD_STATUS.CMD_UNIMPLEMENTED), # - Error case 4 - CMD_EXPIRED # This command has a validity of 0s and thus should be tagged as "expired" (COMMIT_ONLY, "self set_mode ATTENTIVE", 0, None, Agent.CMD_STATUS.CMD_EXPIRED), # - Error case 5 - CMD_SKIPPED # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE (COMMIT_ONLY, "self set_mode ROUTINE", VALIDITY, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED), (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", VALIDITY, None, Agent.CMD_STATUS.CMD_SKIPPED), # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed (True, "self set_mode ATTENTIVE", VALIDITY, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED), (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", VALIDITY, '16.5', Agent.CMD_STATUS.CMD_EXECUTED), # ---------------------------------------------------- # ------ B - ERROR CASES - from RUNNING status ------- # ---------------------------------------------------- (True, "self do_cmd_raising_some_exception", VALIDITY, #"EXCEPTION on command do_cmd_raising_some_exception: StopIteration", "EXCEPTION on command do_cmd_raising_some_exception: StopIteration: Some exception was raised", Agent.CMD_STATUS.CMD_EXEC_ERROR), #(True, "self do_cmd_raising_some_exception", 200, "EXCEPTION on command do_cmd_raising_some_exception: Error during Execution", Agent.CMD_STATUS.CMD_EXEC_ERROR), # ------------------------------ # ------ C - NORMAL CASES ------- # ------------------------------ # do_restart => #iteration should restart at 1 (so at least it should be <= 4) #("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED), # FIXME: ajouter la possibilité d'utiliser des expressions pour tester le résultat : #("self get_iteration_number", 200, 'EXPR:<=4', Agent.CMD_STATUS.CMD_EXECUTED), # 1) First, 3 EXCEPTION CASES (uncomment to activate exception) # Each of these lines will stop execution with an exception # ------------------------------------------------------------ # - Agent command, unknown => ko, UnknownCmdException #("self do_unknown", 10, None,None), # - Agent general command malformed (missing arg) => ko, AgentCmdBadArgsException #("Agent set_mode", 10, None,None), # - Agent specific command, known but not implemented => ko, AgentCmdUnimplementedException #("self set_specific2", 10, None,None), # - Agent specific command, implemented but missing args => ko, AgentCmdBadArgsException #(" self do_specific1 1 ", 10, None,None), # 2) NORMAL CASES (test scenario) # All these commands should be executed without error, from the 1st to the last one # ------------------------------- # Agent general command (COMMIT_ONLY, "self set_mode ROUTINE", VALIDITY, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED), (COMMIT_ONLY, "self get_mode", VALIDITY, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED), (COMMIT_ONLY, "self set_mode ATTENTIVE", VALIDITY, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED), (COMMIT_ONLY, "self get_mode", VALIDITY, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED), # End test # prio (True, "self do_stop", VALIDITY, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), # noprio (True, "self do_stop noprio", VALIDITY, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), ] """ ================================================================= FUNCTIONS RUN INSIDE MAIN THREAD ================================================================= """ # @override ''' #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True): def __init__(self, config_filename=None): ##if name is None: name = self.__class__.__name__ #super().__init__(name, config_filename, RUN_IN_THREAD) super().__init__(config_filename) #self._log.print(f"init done for {name}") self._log.print("init done") ''' def __init__(self, name:str=None, simulated_computer=None): if name is None: name = self.__class__.__name__ super().__init__(simulated_computer=simulated_computer) #super().__init__(RUN_IN_THREAD) # @override def _init(self): # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) self.set_delay(3) # @override def _main_loop_start(self): print("AgentBasic LOOP START") # @override def _main_loop_end(self): if self.CC and self.CC.name != "get_specific_cmds": self.sleep(3) print("AgentBasic LOOP END"); # @override def _routine_process_iter_start_body(self): if self.CC and self.CC.name != "get_specific_cmds": self.sleep(2) # @override def _routine_process_iter_end_body(self): if self.CC and self.CC.name != "get_specific_cmds": self.sleep(2) ''' # @override def load_config(self): super().load_config() ''' ''' # @override def update_survey(self): super().update_survey() ''' ''' # @override def get_next_command(self): return super().get_next_command() ''' # @override def do_log(self): super().do_log() # @override def _sleep_as_soon_as_running(self): print("Make agent sleep as soon as a command has started running") print("so that we can see this command in the 'current command' column of agent web pages") if self.CC and self.CC.name not in ("get_all_cmds", "get_specific_cmds"): self.sleep(5) # @override def _do_things_before_exit(self, stopper_agent_name=None): print("AgentBasic fait quelques trucs à lui avant de stopper...") """ ================================================================= FUNCTIONS RUN INSIDE A SUB-THREAD (OR A PROCESS) (thread_*()) ================================================================= """ # Define your own command step(s) here def cmd_step1(self, step:int): cmd = self._current_specific_cmd cmd.result = f"in step #{step}/{self._thread_total_steps_number}" cmd.save() """ if self.RUN_IN_THREAD: print("(save from thread)") cmd.save() else: #@transaction.atomic print("(save from process)") with transaction.atomic(): cmd.save() #Command.objects.select_for_update() """ def cmd_step2(self, step:int): self.cmd_step1(step) def cmd_step3(self, step:int): self.cmd_step1(step) def cmd_step4(self, step:int): self.cmd_step1(step) """ # @override def thread_exec_specific_cmd_step(self, step:int, sleep_time:float=1.0): self.thread_stop_if_asked() cmd = self._current_specific_cmd print(f">>>>> Thread (cmd {cmd.name}): step #{step}/5") self.sleep(sleep_time) """ ''' # @override def exec_specific_cmd_start(self, cmd:Command, from_thread=True): super().exec_specific_cmd_start(cmd, from_thread) ''' # @override def simulator_test_results_main(self, commands): nb_asserted = 0 for cmd in commands: if cmd.name == "flush_commands": assert cmd.is_executed() nb_asserted+=1 # 2 times if cmd.name == "go_active": assert cmd.is_executed() nb_asserted+=1 # 2 times if cmd.name == "go_idle": assert cmd.is_executed() nb_asserted+=1 """ if cmd.name == "specific0": assert cmd.is_skipped() assert cmd.result == "in step #5/5" nb_asserted+=1 """ if cmd.name == "specific1": assert cmd.is_killed() nb_asserted+=1 if cmd.name == "specific2": assert cmd.is_executed() assert cmd.result == "in step #5/5" nb_asserted+=1 if cmd.name == "eval 4+3": assert cmd.is_executed() assert cmd.get_result() == "7" nb_asserted+=1 if cmd.name in ("abort"): assert cmd.is_executed() nb_asserted+=1 if cmd.name in ("exit"): assert cmd.is_executed() nb_asserted+=1 return nb_asserted ### # ================================================================================================ # AGENT SPECIFIC COMMANDS (functions) # (here just to serve as examples) # ================================================================================================ ### #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int: #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float: def do_cmd_raising_some_exception(self): ##raise CmdExceptionExecError(self.CC) #raise Exception() #raise Exception("Some exception was raised") #raise StopIteration() raise StopIteration("Some exception was raised") # Long time execution command def do_cmd_with_long_exec_time(self): nbsec=5 res = f"1 - now sleeping {nbsec} sec" self.CC.set_result(res, True) #self.CC.get_updated_result() while self.CC.get_updated_result() != res: self.sleep(1) print(res) self.sleep(nbsec) res = f"2 - now sleeping {nbsec} sec" self.CC.set_result(res, True) #self.CC.get_updated_result() while self.CC.get_updated_result() != res: self.sleep(1) print(res) self.sleep(nbsec) res = f"3 - now sleeping {nbsec} sec" self.CC.set_result(res, True) #self.CC.get_updated_result() while self.CC.get_updated_result() != res: self.sleep(1) print(res) self.sleep(nbsec) res = f"4 - now sleeping {nbsec} sec" self.CC.set_result(res, True) #self.CC.get_updated_result() while self.CC.get_updated_result() != res: self.sleep(1) print(res) self.sleep(nbsec) res = f"5 - now sleeping {nbsec} sec" self.CC.set_result(res, True) #self.CC.get_updated_result() while self.CC.get_updated_result() != res: self.sleep(1) print(res) self.sleep(nbsec) return f"should have taken >= {5*nbsec}s to execute" def do_specific10(self, arg1:int, arg2:int, arg3:float=3.1, arg4:str='toto', arg5:Tuple[int,str,int]=(1,'toto',3), #arg5:Tuple[int,int,int]=(1,2,3), arg6:List[int]=[] ) -> float: ''' arg1 = int(arg1) arg2 = int(arg2) arg3 = float(arg3) arg5 = ast.literal_eval(arg5) print(arg5[1]) arg6 = ast.literal_eval(arg6) ''' #print(arg4) res = arg1 + arg2 + arg3 + arg5[0] + arg5[2] if arg6: res += arg6[0] return res # Undefined specific cmd #def set_specific2(self, arg1:str, arg2:int): pass def do_specific30(self): pass """ ================================================================= MAIN FUNCTION ================================================================= """ if __name__ == "__main__": parser = argparse.ArgumentParser(description='Start the agent.') parser.add_argument("--computer",dest="computer",help='Launch agent with simulated computer hostname',action="store") parser.add_argument("-t", action="store_true") args = vars(parser.parse_args()) agent = build_agent(AgentBasic,param_constr=args) ''' TEST_MODE, configfile = extract_parameters() #agent = AgentX() agent = AgentA("AgentA", configfile, RUN_IN_THREAD) agent.setSimulatorMode(TEST_MODE) print(agent) ''' # Run only 4 iterations #agent.run(nb_iter=4) # Run indefinitely agent.run()