Commit 0ddc9733d010523531caf944d24fa474fb1d5042

Authored by Alexis Koralewski
2 parents 5299f92b 0f0a8970
Exists in dev

Merge branch 'dev' of https://gitlab.irap.omp.eu/epallier/pyros into dev

privatedev/plugin/agent/AgentBasic.py
... ... @@ -9,7 +9,7 @@ import sys
9 9 ##sys.path.append("..")
10 10 ###from agent.Agent import Agent, build_agent
11 11 sys.path.append("../../../..")
12   -from src.core.pyros_django.agent.Agent import Agent, build_agent
  12 +from src.core.pyros_django.agent.Agent import Agent, CmdExceptionExecError, build_agent
13 13  
14 14 from typing import List, Tuple, Union, Any
15 15  
... ... @@ -37,9 +37,16 @@ class AgentBasic(Agent):
37 37 ("do_specific10", 10, 0),
38 38 #("set_specific2", 5, 0),
39 39 ("do_specific30", 3, 0),
40   - ###("existing_but_unimplemented_cmd", 3, 0),
  40 + ##("cmd_existing_but_unimplemented", 3, 0),
  41 + ("cmd_raising_error_exec", 3, 0)
41 42 ]
42 43  
  44 + # Deactivate some tests, so that test scenario runs faster during DEV
  45 + # on DEV
  46 + #COMMIT_ONLY = False
  47 + # on commit only
  48 + COMMIT_ONLY = True
  49 +
43 50 # @override
44 51 TEST_COMMANDS_LIST = [
45 52  
... ... @@ -54,52 +61,58 @@ class AgentBasic(Agent):
54 61  
55 62 # do_restart
56 63  
57   - ("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
  64 + (COMMIT_ONLY, "self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
58 65 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
59 66  
60   - # ------------------------------
61   - # ------ A - ERROR CASES -------
62   - # ------------------------------
  67 + # ----------------------------------------------------
  68 + # ------ A - ERROR CASES - from PENDING status -------
  69 + # ----------------------------------------------------
63 70  
64 71 # - Error case 1 - unimplemented command in agent specific commands list
65   - # get_specific_cmds KO (with existing_but_unimplemented_cmd)
66   - #("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR),
  72 + # get_specific_cmds KO (with cmd_existing_but_unimplemented)
  73 + ##("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: cmd_existing_but_unimplemented', Agent.CMD_STATUS.CMD_EXEC_ERROR),
67 74 # get_specific_cmds OK (all commands implemented)
68   - ("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED),
  75 + (COMMIT_ONLY, " self get_specific_cmds ", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30();cmd_raising_error_exec()', Agent.CMD_STATUS.CMD_EXECUTED),
69 76  
70 77 # - Error case 2 - CMD_INVALID
71 78 # unknwon command
72 79 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN),
73   - ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  80 + (COMMIT_ONLY, "self cmd_unexisting", 200, 'EXCEPTION on command cmd_unexisting: Unknown command', Agent.CMD_STATUS.CMD_INVALID),
74 81 # bad parameters (missing or too many, or bad type)
75 82 # missing args
76   - ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  83 + (COMMIT_ONLY, "self do_specific10", 200, 'EXCEPTION on command do_specific10: Command has bad, missing, or too many argument(s)', Agent.CMD_STATUS.CMD_INVALID),
77 84 # missing args
78   - ("self do_specific10 2", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  85 + (COMMIT_ONLY, "self do_specific10 2 ", 200, None, Agent.CMD_STATUS.CMD_INVALID),
79 86 # - too many args
80   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  87 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, None, Agent.CMD_STATUS.CMD_INVALID),
81 88 # - bad type
82   - ("self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  89 + (COMMIT_ONLY, "self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_INVALID),
83 90 # - OK
84 91 #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
85 92  
86 93 # - Error case 3 - CMD_UNIMPLEMENTED
87   - ("self existing_but_unimplemented_cmd", 200, '', Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
  94 + ##("self cmd_existing_but_unimplemented", 200, None, Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
88 95  
89 96 # - Error case 4 - CMD_EXPIRED
90 97 # This command has a validity of 0s and thus should be tagged as "expired"
91   - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
  98 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
92 99  
93 100 # - Error case 5 - CMD_SKIPPED
94 101 # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE
95   - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
96   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
  102 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  103 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
97 104 # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed
98   - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
99   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  105 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  106 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  107 +
  108 + # ----------------------------------------------------
  109 + # ------ B - ERROR CASES - from RUNNING status -------
  110 + # ----------------------------------------------------
  111 +
  112 + (True, "self cmd_raising_error_exec", 200, "EXCEPTION on command cmd_raising_error_exec: Error during Execution", Agent.CMD_STATUS.CMD_EXEC_ERROR),
100 113  
101 114 # ------------------------------
102   - # ------ B - NORMAL CASES -------
  115 + # ------ C - NORMAL CASES -------
103 116 # ------------------------------
104 117  
105 118 # do_restart => #iteration should restart at 1 (so at least it should be <= 4)
... ... @@ -129,13 +142,13 @@ class AgentBasic(Agent):
129 142 # -------------------------------
130 143  
131 144 # Agent general command
132   - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
133   - ("self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
134   - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
135   - ("self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  145 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  146 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  147 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  148 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
136 149  
137 150 # End test
138   - ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
  151 + (True, "self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
139 152  
140 153 ]
141 154  
... ... @@ -324,6 +337,9 @@ class AgentBasic(Agent):
324 337 #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int:
325 338 #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float:
326 339  
  340 + def cmd_raising_error_exec(self):
  341 + raise CmdExceptionExecError(self.CURRENT_CMD)
  342 +
327 343 def do_specific10(self,
328 344 arg1:int,
329 345 arg2:int,
... ...
src/core/pyros_django/agent/Agent.py
... ... @@ -41,7 +41,7 @@ and execute them on reception at each iteration :
41 41  
42 42 # For cmd parsing
43 43 from array import array
44   -from typing import List, Tuple, Union, Any
  44 +from typing import List, Tuple, Union, Any, Optional
45 45 import ast
46 46 from inspect import signature
47 47  
... ... @@ -127,6 +127,7 @@ import random
127 127 import threading
128 128 #import multiprocessing
129 129 import time
  130 +import re
130 131 '''
131 132 from threading import Thread
132 133 import socket
... ... @@ -259,9 +260,21 @@ class StoppableThreadEvenWhenSleeping(threading.Thread):
259 260 class CmdException(Exception):
260 261 ''' Base class for all Agent command exceptions '''
261 262 # pass
262   - def __init__( self, cmd: Union[AgentCmd,str] ):
  263 + def __init__( self, cmd:Union[AgentCmd,str], msg:str=None):
263 264 self.cmd = cmd
  265 + self._msg = msg
264 266 self.cmd_name = cmd if isinstance(cmd,str) else cmd.name
  267 + @property
  268 + def msg(self):
  269 + msg = "EXCEPTION on command "+self.cmd_name
  270 + return msg if not self._msg else msg+': '+self._msg
  271 + # Default message if print exception
  272 + def __str__(self):
  273 + return self.msg
  274 + '''
  275 + msg = "EXCEPTION on command "+self.cmd_name
  276 + return msg if not self.msg else msg+': '+self.msg
  277 + '''
265 278 '''
266 279 def __str__(self):
267 280 return f"The Agent command '{self.cmd.name}' is unknown to the agent"
... ... @@ -269,41 +282,57 @@ class CmdException(Exception):
269 282 '''
270 283  
271 284 # --- CMD PENDING (non running) EXCEPTIONS ---
272   -class CmdUnknownException(CmdException):
  285 +
  286 +# @Override
  287 +class CmdExceptionUnknown(CmdException):
273 288 ''' Raised when a PENDING (non running) Agent (specific) cmd is NOT known by the agent '''
274   - def __str__(self):
275   - return f"The Agent command '{self.cmd_name}' is unknown to the agent"
276   - #return f"({type(self).__name__}): Device Generic command has no implementation in the controller"
  289 + # @Override
  290 + def __init__( self, cmd, msg:str=None):
  291 + super().__init__(cmd, msg if msg else "Unknown command")
  292 + #def __str__(self): return self.msg if self.msg else f"The Agent command '{self.cmd_name}' is unknown to the agent"
277 293  
278   -class CmdUnimplementedException(CmdException):
  294 +# @Override
  295 +class CmdExceptionUnimplemented(CmdException):
279 296 ''' Raised when a PENDING (non running) Agent Specific cmd is known by the agent but not implemented '''
280   - def __str__(self):
281   - return f"The Agent command '{self.cmd_name}' is known by the agent but not implemented"
282   - #return f"({type(self).__name__}): Device Generic command has no implementation in the controller"
  297 + # @Override
  298 + def __init__( self, cmd, msg:str=None):
  299 + super().__init__(cmd, msg if msg else "Command is known by the agent but not implemented")
  300 + #def __str__(self): return f"The Agent command '{self.cmd_name}' is known by the agent but not implemented"
283 301  
284   -class CmdBadArgsException(CmdException):
  302 +# @Override
  303 +class CmdExceptionBadArgs(CmdException):
285 304 ''' Raised when a PENDING (non running) Agent cmd has bad, missing, or too many argument(s) '''
286   - def __str__(self):
287   - return f"The Agent command '{self.cmd_name}' has bad, missing, or too many argument(s)"
288   - #return f"({type(self).__name__}): Device Generic command has no implementation in the controller"
  305 + # @Override
  306 + def __init__( self, cmd, msg:str=None):
  307 + super().__init__(cmd, msg if msg else "Command has bad, missing, or too many argument(s)")
  308 + #def __str__(self): return f"The Agent command '{self.cmd_name}' has bad, missing, or too many argument(s)"
289 309  
290 310  
291 311 # --- CMD RUNNING EXCEPTIONS ---
292 312  
293   -class CmdExecErrorException(CmdException):
  313 +# @Override
  314 +class CmdExceptionExecError(CmdException):
294 315 ''' Raised when a RUNNING Agent cmd has had a running error '''
295   - def __str__(self):
296   - return f"The running Agent command '{self.cmd_name}' has had an error (during execution)"
  316 + # @Override
  317 + def __init__( self, cmd, msg:str=None):
  318 + super().__init__(cmd, msg if msg else "Error during Execution")
  319 + #def __str__(self): return f"The running Agent command '{self.cmd_name}' has had an error (during execution)"
297 320  
298   -class CmdExecTimeoutException(CmdException):
  321 +# @Override
  322 +class CmdExceptionExecTimeout(CmdException):
299 323 ''' Raised when a RUNNING Agent cmd is timeout '''
300   - def __str__(self):
301   - return f"The running Agent command '{self.cmd_name}' is timeout"
  324 + # @Override
  325 + def __init__( self, cmd, msg:str=None):
  326 + super().__init__(cmd, msg if msg else "Execution is TIMEOUT")
  327 + #def __str__(self): return f"The running Agent command '{self.cmd_name}' is timeout"
302 328  
303   -class CmdExecKilledException(CmdException):
  329 +# @Override
  330 +class CmdExceptionExecKilled(CmdException):
304 331 ''' Raised when a RUNNING Agent cmd has been aborted (by another agent) '''
305   - def __str__(self):
306   - return f"The running Agent command '{self.cmd_name}' has been killed (by another agent)"
  332 + # @Override
  333 + def __init__( self, cmd, msg:str=None):
  334 + super().__init__(cmd, msg if msg else "Command was KILLED during Execution (by another agent")
  335 + #def __str__(self): return f"The running Agent command '{self.cmd_name}' has been killed (by another agent)"
307 336  
308 337 ###
309 338 # =================================================================
... ... @@ -390,6 +419,8 @@ class Agent:
390 419 #
391 420 # Format : List of tuples (command, validity, expected_res, expected_status), with :
392 421 #
  422 + # - DO_IT : execute this command yes (true) or no (false) ? (yes by default)
  423 +
393 424 # - command : the format is "recipient cmd args", with :
394 425 # - recipient : name of the Agent that the command is to be sent to (use "self" to mean himself)
395 426 # - cmd : the command name
... ... @@ -407,11 +438,12 @@ class Agent:
407 438 # - "self set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to MYSELF
408 439 # - "self do_restart_loop" => means to send the command "do_restart_loop" to MYSELF (no args)
409 440 #
410   - TEST_COMMANDS_LIST: List[ Tuple[ str, int, Union[str,None], Union[int,None] ] ] = [
  441 + #TEST_COMMANDS_LIST: List[ Tuple[ str, int, Union[str,None], Union[int,None], Optional[bool] ] ] = [
  442 + TEST_COMMANDS_LIST: List[ Tuple[bool, str, int, Optional[str], Optional[int]] ] = [
411 443  
412 444 # Format : ("self cmd_name cmd_args", timeout, "expected_result", expected_status),
413 445 #("self do_stop now", 200, '15.5', None),
414   - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None),
  446 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None),
415 447  
416 448 # 1) First, 3 EXCEPTION CASES (uncomment to activate exception)
417 449 # Each of these lines will stop execution with an exception
... ... @@ -435,38 +467,38 @@ class Agent:
435 467 # -------------------------------
436 468  
437 469 # This command has a validity of 0s and thus should be tagged as "expired"
438   - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXPIRED),
  470 + (True, "self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXPIRED),
439 471  
440 472 # Agent general command
441   - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXECUTED),
  473 + (True, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXECUTED),
442 474 # => should get "ATTENTIVE"
443   - ("self get_mode", 100, "MODE is ATTENTIVE", None),
  475 + (True, "self get_mode", 100, "MODE is ATTENTIVE", None),
444 476  
445 477 # => should get "7"
446   - ("self do_eval 3+5-1", 200, '7', None),
  478 + (True, "self do_eval 3+5-1", 200, '7', None),
447 479  
448 480 # END, will not go further
449 481 #("self do_exit", 2, "STOPPING"),
450 482  
451 483 # Agent specific commands => should be executed
452   - ("self do_specific3", 200, '', None),
453   - ("self do_exit", 500, "STOPPING", None),
454   - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None),
  484 + (True, "self do_specific3", 200, '', None),
  485 + (True, "self do_exit", 500, "STOPPING", None),
  486 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None),
455 487  
456 488  
457   - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", None),
  489 + (True, "self set_mode ROUTINE", 200, "MODE is ROUTINE", None),
458 490 # => should get "ROUTINE"
459   - ("self get_mode", 200, "MODE is ROUTINE", None),
  491 + (True, "self get_mode", 200, "MODE is ROUTINE", None),
460 492 # Agent specific command => should be skipped (because not ATTENTIVE)
461   - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, "SKIPPED", None),
  493 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, "SKIPPED", None),
462 494  
463 495 # From now on, should not run anymore process_before/after
464 496 # => and should skip next specific commands
465   - ("self set_mode IDLE", 200, "MODE is IDLE", None),
  497 + (True, "self set_mode IDLE", 200, "MODE is IDLE", None),
466 498 # => should get "IDLE"
467   - ("self get_mode", 200, "MODE is IDLE", None),
  499 + (True, "self get_mode", 200, "MODE is IDLE", None),
468 500 # Agent specific command => should be skipped (because not ATTENTIVE)
469   - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, 'SKIPPED', None),
  501 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, 'SKIPPED', None),
470 502  
471 503 # TODO: test priority commands : do_abort, do_flush_cmds, ...
472 504 # - Stop executing new commands (just let them accumulate)
... ... @@ -483,10 +515,10 @@ class Agent:
483 515 ##("self do_resume_exec",),
484 516  
485 517 # Restart the restart loop (from init())
486   - ("self do_restart", 200, "RESTARTING", None),
  518 + (True, "self do_restart", 200, "RESTARTING", None),
487 519  
488 520 # Now stop
489   - ("self do_exit", 200, "STOPPING", None),
  521 + (True, "self do_exit", 200, "STOPPING", None),
490 522  
491 523 '''
492 524 # specific0 not_executed_because_idle
... ... @@ -1082,27 +1114,41 @@ class Agent:
1082 1114 #print(cmd)
1083 1115 except (
1084 1116 # PENDING (non running) cmd exceptions
1085   - CmdUnimplementedException, CmdBadArgsException, CmdUnknownException,
  1117 + CmdExceptionUnknown, CmdExceptionUnimplemented, CmdExceptionBadArgs,
1086 1118 # RUNNING cmd exceptions
1087   - CmdExecErrorException, CmdExecTimeoutException, CmdExecKilledException
  1119 + CmdExceptionExecError, CmdExceptionExecKilled, CmdExceptionExecTimeout,
1088 1120 ) as e :
1089   - #print(e)
1090   - log.error(f"EXCEPTION on Agent command '{e.cmd_name}'")
  1121 + print(e)
  1122 + log.error(e)
  1123 + #log.error(f"EXCEPTION on Agent command '{e.cmd_name}'")
1091 1124 if isinstance(e.cmd, AgentCmd) :
1092 1125 cmd = e.cmd
1093   - if type(e) is CmdUnimplementedException:
1094   - if cmd.name != "get_specific_cmds":
1095   - cmd.set_as_unimplemented("EXCEPTION: command known but unimplemented")
1096   - elif type(e) in (CmdBadArgsException, CmdUnknownException):
1097   - # set back to "pending" if ever was wrongly marked "running"
1098   - #cmd.set_as_pending()
1099   - cmd.set_as_invalid("EXCEPTION: command unknown or bad args")
1100   - # Execution Exception
1101   - elif type(e) != CmdExecErrorException:
1102   - cmd.set_result("EXCEPTION: Problem during execution")
  1126 + # - Exception from PENGING
  1127 + if type(e) in (CmdExceptionUnknown, CmdExceptionUnimplemented, CmdExceptionBadArgs):
  1128 + if type(e) is CmdExceptionUnimplemented:
  1129 + if cmd.name != "get_specific_cmds":
  1130 + cmd.set_as_unimplemented(e.msg)
  1131 + #cmd.set_as_unimplemented("EXCEPTION: Command known but unimplemented")
  1132 + else:
  1133 + # set back to "pending" if ever was wrongly marked "running"
  1134 + #cmd.set_as_pending()
  1135 + cmd.set_as_invalid(e.msg)
  1136 + #cmd.set_as_invalid("EXCEPTION: Command unknown or bad args")
  1137 + # - Exception from RUNNING (Execution Exception)
  1138 + else:
  1139 + if type(e) == CmdExceptionExecError:
  1140 + print(e)
  1141 + cmd.set_as_exec_error(e.msg)
  1142 + print(e)
  1143 + #cmd.set_as_exec_error(e.msg if e.msg else "EXCEPTION: Error during execution")
  1144 + else:
  1145 + #FIXME: S'assurer que cmd.set_as_killed() or cmd.set_as_timeout() a bien รฉtรฉ fait !!!
  1146 + cmd.set_result(e.msg)
  1147 + #cmd.set_result("EXCEPTION: Problem during execution")
1103 1148 # isinstance(e.cmd, str)
1104 1149 else:
1105   - raise Exception("Abnormal error case...")
  1150 + raise CmdException(cmd, "EXCEPTION: Abnormal error case...")
  1151 + #raise Exception("EXCEPTION: Abnormal error case...")
1106 1152  
1107 1153  
1108 1154  
... ... @@ -1251,7 +1297,7 @@ class Agent:
1251 1297 if self._is_agent_general_cmd(cmd):
1252 1298 try:
1253 1299 self._process_agent_general_cmd(cmd)
1254   - except (CmdUnimplementedException, CmdBadArgsException) :
  1300 + except (CmdExceptionUnimplemented, CmdExceptionBadArgs) :
1255 1301 # cmd should not be set as "running"
1256 1302 cmd.set_as_pending()
1257 1303 # These exceptions are managed at higher level :
... ... @@ -1269,7 +1315,7 @@ class Agent:
1269 1315 self._process_agent_specific_cmd(cmd)
1270 1316 #self._exec_agent_cmd(cmd)
1271 1317 #except AttributeError as e:
1272   - except (CmdUnimplementedException, CmdBadArgsException) as e:
  1318 + except (CmdExceptionUnimplemented, CmdExceptionBadArgs) as e:
1273 1319 # cmd should not be set as "running"
1274 1320 #cmd.set_as_pending()
1275 1321 # These exceptions are managed at higher level :
... ... @@ -1291,7 +1337,7 @@ class Agent:
1291 1337 ##cmd.set_as_skipped("ERROR: INVALID AGENT COMMAND")
1292 1338 ##self._cleanup_before_exit()
1293 1339 ##raise UnknownCmdException(cmd.name)
1294   - raise CmdUnknownException(cmd)
  1340 + raise CmdExceptionUnknown(cmd)
1295 1341  
1296 1342 #print()
1297 1343 #log.info("*"*10 + " NEXT COMMAND PROCESSING (END) " + "*"*10 + "\n")
... ... @@ -1447,7 +1493,7 @@ class Agent:
1447 1493 try:
1448 1494 f = getattr(self, cmd_name)
1449 1495 except AttributeError:
1450   - raise CmdUnimplementedException(cmd_name) from None
  1496 + raise CmdExceptionUnimplemented(cmd_name) from None
1451 1497 args = signature(f)
1452 1498 #specific_commands += str(args)
1453 1499 specific_commands += "("
... ... @@ -1485,9 +1531,9 @@ class Agent:
1485 1531  
1486 1532 def get_status(self):
1487 1533 return self.status
1488   - # @deprecated
  1534 +
1489 1535 def get_state(self):
1490   - return self.get_status()
  1536 + return f"MODE {self.get_mode()} ; STATUS {self.get_status()} ; ITERATION #{self._iter_num}"
1491 1537  
1492 1538 def _set_status(self, status:str):
1493 1539 #self.printd(f"[{status}] (switching from status {self.status})")
... ... @@ -1797,7 +1843,7 @@ class Agent:
1797 1843 which is relevant to this agent.
1798 1844 Commands are read in chronological order
1799 1845 """
1800   - self._set_status(self.AGT_STATUS.IN_GET_NEXT_CMD)
  1846 + self._set_and_log_status(self.AGT_STATUS.IN_GET_NEXT_CMD)
1801 1847 log.info("Looking for a new command to process (sent by another agent):")
1802 1848  
1803 1849 # 1) Get all pending commands for me (return if None)
... ... @@ -2046,12 +2092,12 @@ class Agent:
2046 2092  
2047 2093 elif cmd_name == "set_mode":
2048 2094 #if not cmd_args: raise ValueError()
2049   - if not cmd_args: raise CmdBadArgsException(cmd)
  2095 + if not cmd_args: raise CmdExceptionBadArgs(cmd)
2050 2096 mode = cmd_args[0]
2051 2097 if mode == "IDLE": self.set_idle()
2052 2098 elif mode == "ROUTINE": self.set_routine()
2053 2099 elif mode == "ATTENTIVE": self.set_attentive()
2054   - else: raise CmdBadArgsException(cmd)
  2100 + else: raise CmdExceptionBadArgs(cmd)
2055 2101 #cmd.set_result("I am now " + state)
2056 2102 result = "MODE is " + mode
2057 2103 #time.sleep(1)
... ... @@ -2066,7 +2112,7 @@ class Agent:
2066 2112  
2067 2113 elif cmd_name == "do_eval":
2068 2114 #if not cmd_args: raise ValueError()
2069   - if not cmd_args: raise CmdBadArgsException(cmd)
  2115 + if not cmd_args: raise CmdExceptionBadArgs(cmd)
2070 2116 #cmd.set_result(eval(cmd_args))
2071 2117 #result = eval(cmd_args)
2072 2118 result = self.do_eval(cmd_args[0])
... ... @@ -2075,10 +2121,10 @@ class Agent:
2075 2121 # CmdUnimplementedException if one specific command (in the list) is unknown
2076 2122 try:
2077 2123 result = self.get_specific_cmds()
2078   - except CmdUnimplementedException as e:
  2124 + except CmdExceptionUnimplemented as e:
2079 2125 # raise CmdUnimplementedException("get_specific_cmds.unknown_cmd_name")
2080   - cmd.set_as_exec_error("EXCEPTION - One specific cmd is unimplemented: "+e.cmd_name)
2081   - raise CmdExecErrorException(cmd) from None
  2126 + #cmd.set_as_exec_error("EXCEPTION - One specific cmd is unimplemented: "+e.cmd_name)
  2127 + raise CmdExceptionExecError(cmd, "EXCEPTION - One specific cmd is unimplemented => "+e.cmd_name) from None
2082 2128  
2083 2129 cmd.set_as_processed(result)
2084 2130 log.info("...Agent level GENERAL cmd has been executed")
... ... @@ -2114,7 +2160,7 @@ class Agent:
2114 2160 # This can raise an exception (caught by this method caller)
2115 2161 try:
2116 2162 res = self._exec_cmd_from_its_name(cmd)
2117   - except (CmdUnimplementedException, CmdBadArgsException) as e:
  2163 + except (CmdExceptionUnimplemented, CmdExceptionBadArgs) as e:
2118 2164 ##cmd.set_as_pending()
2119 2165 # These exceptions are managed at higher level :
2120 2166 raise
... ... @@ -2160,7 +2206,7 @@ class Agent:
2160 2206 methods_list = [method for method in dir(self) if callable(getattr(self, method))]
2161 2207 #print(methodsList)
2162 2208 func = cmd.name
2163   - if func not in methods_list: raise CmdUnimplementedException(cmd)
  2209 + if func not in methods_list: raise CmdExceptionUnimplemented(cmd)
2164 2210 ##f = getattr(self, func)
2165 2211 ###print(func, ' => ', signature(f))
2166 2212  
... ... @@ -2188,9 +2234,10 @@ class Agent:
2188 2234 return getattr(self, func)(*args)
2189 2235 '''
2190 2236 args = []
  2237 + print(cmd.args)
2191 2238 # Convert all args to their real type
2192 2239 for arg in cmd.args:
2193   - #print(arg)
  2240 + print(arg)
2194 2241 #try:
2195 2242 # Evaluate arg only if it is not a word (letters) :
2196 2243 # - a word like "toto" is not evaluated => stays as is (=str)
... ... @@ -2217,7 +2264,7 @@ class Agent:
2217 2264 cmd.set_as_pending()
2218 2265 #raise e
2219 2266 # "from None" pour ne pas afficher l'exception AttributeError (car interne)
2220   - raise CmdBadArgsException(cmd) from None
  2267 + raise CmdExceptionBadArgs(cmd) from None
2221 2268 #print("I know this specific command but it is not yet implemented : ", func)
2222 2269 ##tb = sys.exc_info()[2]
2223 2270 ##raise AgentCmdUnimplementedException(cmd).with_traceback(tb)
... ... @@ -2287,7 +2334,7 @@ class Agent:
2287 2334 # NOT PRIO
2288 2335 if what == "noprio": pass
2289 2336 # Bad arg
2290   - raise CmdBadArgsException(self.CURRENT_CMD)
  2337 + raise CmdExceptionBadArgs(self.CURRENT_CMD)
2291 2338  
2292 2339 # Stop currently running cmd or routine
2293 2340 def do_stop_current(self, what:str):
... ... @@ -2297,7 +2344,7 @@ class Agent:
2297 2344 self.do_stop_current_cmd()
2298 2345 self.do_stop_current_routine()
2299 2346 # Bad arg
2300   - raise CmdBadArgsException(self.CURRENT_CMD)
  2347 + raise CmdExceptionBadArgs(self.CURRENT_CMD)
2301 2348 def do_stop_current_cmd(self):
2302 2349 pass
2303 2350 def do_stop_current_routine(self):
... ... @@ -2309,7 +2356,7 @@ class Agent:
2309 2356 def do_stop(self, when:str='asap'): self.do_stop_or_restart(False, when)
2310 2357 def do_restart(self, when:str='asap'): self.do_stop_or_restart(True, when)
2311 2358 def do_stop_or_restart(self, restart:bool=False, when:str='asap'):
2312   - if when not in ('asap','now','noprio'): raise CmdBadArgsException(self.CURRENT_CMD)
  2359 + if when not in ('asap','now','noprio'): raise CmdExceptionBadArgs(self.CURRENT_CMD)
2313 2360 # NOT PRIO
2314 2361 if when == "noprio":
2315 2362 pass
... ... @@ -2419,13 +2466,14 @@ class Agent:
2419 2466  
2420 2467 def _TEST_get_next_command_to_send(self)->AgentCmd:
2421 2468 #cmd_full_name, validity, res_expected, after_status = next(self.TEST_COMMANDS, (None,None,None,None))
2422   - cmd_full_name, validity, expected_res, expected_status = next(self.TEST_COMMANDS, (None,None,None,None))
  2469 + DO_IT = False
  2470 + while not DO_IT:
  2471 + DO_IT, cmd_full_name, validity, expected_res, expected_status = next(self.TEST_COMMANDS, (False,None,None,None,None))
2423 2472 #print(expected_final_status)
2424 2473 #print(cmd_full_name, res_expected)
2425 2474 #return cmd_name
2426 2475 if cmd_full_name is None: return None
2427   - # Remove excessive spaces
2428   - import re
  2476 + # Remove excessive spaces => already done in AgentCmd.create()
2429 2477 cmd_full_name = re.sub(r"\s+", " ", cmd_full_name).strip()
2430 2478 if ' ' not in cmd_full_name: raise Exception('Command is malformed:', cmd_full_name)
2431 2479 agent_recipient, cmd_name_and_args = cmd_full_name.split(' ', 1)
... ...
src/core/pyros_django/agent/AgentBasic.py
... ... @@ -9,7 +9,7 @@ import sys
9 9 ##sys.path.append("..")
10 10 ###from agent.Agent import Agent, build_agent
11 11 sys.path.append("../../../..")
12   -from src.core.pyros_django.agent.Agent import Agent, build_agent
  12 +from src.core.pyros_django.agent.Agent import Agent, CmdExceptionExecError, build_agent
13 13  
14 14 from typing import List, Tuple, Union, Any
15 15  
... ... @@ -37,9 +37,16 @@ class AgentBasic(Agent):
37 37 ("do_specific10", 10, 0),
38 38 #("set_specific2", 5, 0),
39 39 ("do_specific30", 3, 0),
40   - ###("existing_but_unimplemented_cmd", 3, 0),
  40 + ##("cmd_existing_but_unimplemented", 3, 0),
  41 + ("cmd_raising_error_exec", 3, 0)
41 42 ]
42 43  
  44 + # Deactivate some tests, so that test scenario runs faster during DEV
  45 + # on DEV
  46 + #COMMIT_ONLY = False
  47 + # on commit only
  48 + COMMIT_ONLY = True
  49 +
43 50 # @override
44 51 TEST_COMMANDS_LIST = [
45 52  
... ... @@ -54,52 +61,58 @@ class AgentBasic(Agent):
54 61  
55 62 # do_restart
56 63  
57   - ("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
  64 + (COMMIT_ONLY, "self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
58 65 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
59 66  
60   - # ------------------------------
61   - # ------ A - ERROR CASES -------
62   - # ------------------------------
  67 + # ----------------------------------------------------
  68 + # ------ A - ERROR CASES - from PENDING status -------
  69 + # ----------------------------------------------------
63 70  
64 71 # - Error case 1 - unimplemented command in agent specific commands list
65   - # get_specific_cmds KO (with existing_but_unimplemented_cmd)
66   - #("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR),
  72 + # get_specific_cmds KO (with cmd_existing_but_unimplemented)
  73 + ##("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: cmd_existing_but_unimplemented', Agent.CMD_STATUS.CMD_EXEC_ERROR),
67 74 # get_specific_cmds OK (all commands implemented)
68   - ("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED),
  75 + (COMMIT_ONLY, " self get_specific_cmds ", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30();cmd_raising_error_exec()', Agent.CMD_STATUS.CMD_EXECUTED),
69 76  
70 77 # - Error case 2 - CMD_INVALID
71 78 # unknwon command
72 79 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN),
73   - ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  80 + (COMMIT_ONLY, "self cmd_unexisting", 200, 'EXCEPTION on command cmd_unexisting: Unknown command', Agent.CMD_STATUS.CMD_INVALID),
74 81 # bad parameters (missing or too many, or bad type)
75 82 # missing args
76   - ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  83 + (COMMIT_ONLY, "self do_specific10", 200, 'EXCEPTION on command do_specific10: Command has bad, missing, or too many argument(s)', Agent.CMD_STATUS.CMD_INVALID),
77 84 # missing args
78   - ("self do_specific10 2", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  85 + (COMMIT_ONLY, "self do_specific10 2 ", 200, None, Agent.CMD_STATUS.CMD_INVALID),
79 86 # - too many args
80   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  87 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, None, Agent.CMD_STATUS.CMD_INVALID),
81 88 # - bad type
82   - ("self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  89 + (COMMIT_ONLY, "self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_INVALID),
83 90 # - OK
84 91 #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
85 92  
86 93 # - Error case 3 - CMD_UNIMPLEMENTED
87   - ("self existing_but_unimplemented_cmd", 200, '', Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
  94 + ##("self cmd_existing_but_unimplemented", 200, None, Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
88 95  
89 96 # - Error case 4 - CMD_EXPIRED
90 97 # This command has a validity of 0s and thus should be tagged as "expired"
91   - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
  98 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
92 99  
93 100 # - Error case 5 - CMD_SKIPPED
94 101 # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE
95   - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
96   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
  102 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  103 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
97 104 # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed
98   - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
99   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  105 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  106 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  107 +
  108 + # ----------------------------------------------------
  109 + # ------ B - ERROR CASES - from RUNNING status -------
  110 + # ----------------------------------------------------
  111 +
  112 + (True, "self cmd_raising_error_exec", 200, "EXCEPTION on command cmd_raising_error_exec: Error during Execution", Agent.CMD_STATUS.CMD_EXEC_ERROR),
100 113  
101 114 # ------------------------------
102   - # ------ B - NORMAL CASES -------
  115 + # ------ C - NORMAL CASES -------
103 116 # ------------------------------
104 117  
105 118 # do_restart => #iteration should restart at 1 (so at least it should be <= 4)
... ... @@ -129,13 +142,13 @@ class AgentBasic(Agent):
129 142 # -------------------------------
130 143  
131 144 # Agent general command
132   - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
133   - ("self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
134   - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
135   - ("self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  145 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  146 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  147 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  148 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
136 149  
137 150 # End test
138   - ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
  151 + (True, "self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
139 152  
140 153 ]
141 154  
... ... @@ -324,6 +337,9 @@ class AgentBasic(Agent):
324 337 #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int:
325 338 #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float:
326 339  
  340 + def cmd_raising_error_exec(self):
  341 + raise CmdExceptionExecError(self.CURRENT_CMD)
  342 +
327 343 def do_specific10(self,
328 344 arg1:int,
329 345 arg2:int,
... ...
src/core/pyros_django/common/models.py
... ... @@ -12,6 +12,9 @@ from dateutil.relativedelta import relativedelta
12 12 import os
13 13 import sys
14 14 from typing import Any, List, Tuple
  15 +import re
  16 +
  17 +# Django imports
15 18 from django.core.validators import MaxValueValidator, MinValueValidator
16 19  
17 20 # DJANGO imports
... ... @@ -575,8 +578,10 @@ class AgentCmd(models.Model):
575 578 # GET commands
576 579 # ------------
577 580  
578   - # - Get agent current STATE (IN_MAIN_LOOP, ...)
  581 + # - Get agent current STATUS or STEP (IN_MAIN_LOOP, ...)
  582 + "get_status",
579 583 ##"get_current_state",
  584 + # @deprecated
580 585 "get_state",
581 586  
582 587 # - Get agent current MODE (idle, routine, attentive)
... ... @@ -644,6 +649,7 @@ class AgentCmd(models.Model):
644 649 # Priority commands, executed as soon as in the received commands list (BEFORE any other pending command)
645 650 # NB : must be a subset of _AGENT_GENERAL_COMMANDS
646 651 _AGENT_GENERAL_PRIORITY_COMMANDS = [
  652 + "get_specific_cmds",
647 653 #"do_exit",
648 654 "do_flush_commands",
649 655 "do_exec_commands"
... ... @@ -666,7 +672,10 @@ class AgentCmd(models.Model):
666 672 if '.' in agent_to:
667 673 agent_to, component_name = agent_to.split('.')
668 674 cmd_name = component_name+'.'+cmd_name
  675 + # remove all excessive spaces
  676 + print(cmd_args)
669 677 if cmd_args:
  678 + cmd_args = re.sub(r"\s+", " ", cmd_args).strip()
670 679 cmd_name += ' ' + cmd_args
671 680 # cls._device_command=DeviceCommand(cmd_name)
672 681 if cmd_validity is None: cmd_validity = cls.DEFAULT_VALIDITY_DURATION
... ... @@ -1091,13 +1100,15 @@ class AgentCmd(models.Model):
1091 1100 if result:
1092 1101 self.set_result(result, False)
1093 1102  
  1103 + '''
1094 1104 # - Changing state to PENDING (from None)
1095 1105 if status_new == self.CMD_STATUS_CODES.CMD_PENDING:
1096 1106 self.s_deposit_time = now_time
  1107 + '''
1097 1108  
1098 1109 # - Changing state from PENDING
1099 1110 #if status_new in (self.CMD_STATUS_CODES.CMD_RUNNING, self.CMD_STATUS_CODES.CMD_SKIPPED, self.CMD_STATUS_CODES.CMD_EXPIRED):
1100   - elif status_new in (
  1111 + if status_new in (
1101 1112 # Errors cases
1102 1113 self.CMD_STATUS_CODES.CMD_INVALID,
1103 1114 self.CMD_STATUS_CODES.CMD_UNIMPLEMENTED,
... ... @@ -1119,7 +1130,7 @@ class AgentCmd(models.Model):
1119 1130  
1120 1131 # - Changing state from RUNNING (CMD_EXECUTED, CMD_EXEC_...)
1121 1132 #elif status_new in (self.CMD_STATUS_CODES.CMD_EXECUTED, self.CMD_STATUS_CODES.CMD_EXEC_KILLED):
1122   - else:
  1133 + elif status_new != self.CMD_STATUS_CODES.CMD_PENDING:
1123 1134 assert self.is_running()
1124 1135 self.r_end_time = now_time
1125 1136 if status_new == self.CMD_STATUS_CODES.CMD_EXEC_KILLED:
... ...