Commit d467c6d88506d48fb0c8e3af2dd76d107b522de1

Authored by Etienne Pallier
1 parent 4ba41afb
Exists in dev

Optimisation log_agent_status() (ex update_survey())

+ bugfix import celme
+ activity diag
@@ -73,9 +73,7 @@ Author: E. Pallier @@ -73,9 +73,7 @@ Author: E. Pallier
73 73
74 VERSION: 0.20.31 74 VERSION: 0.20.31
75 75
76 -Comment: AgentM  
77 -  
78 - - routine_process() : envoi commande n'est plus bloquant 76 +Comment: Optimisation log_agent_status() (ex update_survey())
79 77
80 - Scenario de test : 78 - Scenario de test :
81 - lancer agents A et B en mode simu (option -t): ./pyros.py -t start agentA,agentB 79 - lancer agents A et B en mode simu (option -t): ./pyros.py -t start agentA,agentB
@@ -89,7 +87,9 @@ Comment: AgentM @@ -89,7 +87,9 @@ Comment: AgentM
89 (ou encore: activer l'environnement virtuel, puis lancer "cd src/agent/ ; ./AgentA.py configfile") 87 (ou encore: activer l'environnement virtuel, puis lancer "cd src/agent/ ; ./AgentA.py configfile")
90 - pour utiliser thread ou processus : il suffit de mettre la constante RUN_IN_THREAD de AgentA (ou AgentB ou AgentX) à False ou True 88 - pour utiliser thread ou processus : il suffit de mettre la constante RUN_IN_THREAD de AgentA (ou AgentB ou AgentX) à False ou True
91 89
92 - - Autres remarques: 90 + - Historique des nouveautés :
  91 + - AgentM (début) pour remplacer progressivement l'agent monitoring
  92 + - routine_process() : envoi commande n'est plus bloquant
93 - pyros.py peut lancer plusieurs agents (A et B) en même temps 93 - pyros.py peut lancer plusieurs agents (A et B) en même temps
94 - run(N) : run only N iterations 94 - run(N) : run only N iterations
95 - send_command() implemented 95 - send_command() implemented
src/agent/Agent.py
@@ -72,12 +72,12 @@ print() @@ -72,12 +72,12 @@ print()
72 72
73 # --- GENERAL PURPOSE IMPORT --- 73 # --- GENERAL PURPOSE IMPORT ---
74 #from __future__ import absolute_import 74 #from __future__ import absolute_import
  75 +import utils.Logger as L
75 import platform 76 import platform
76 import random 77 import random
77 from threading import Thread 78 from threading import Thread
78 import threading, multiprocessing 79 import threading, multiprocessing
79 import time 80 import time
80 -import utils.Logger as L  
81 import socket 81 import socket
82 #import ctypes 82 #import ctypes
83 #import copy 83 #import copy
@@ -185,19 +185,82 @@ class StoppableThreadEvenWhenSleeping(threading.Thread): @@ -185,19 +185,82 @@ class StoppableThreadEvenWhenSleeping(threading.Thread):
185 class Agent: 185 class Agent:
186 """ 186 """
187 Behavior of an agent: 187 Behavior of an agent:
  188 + - If idle :
  189 + - still does routine_process() and general_process()
  190 + - does not do specific_process()
188 - Once a command has been sent to another agent : 191 - Once a command has been sent to another agent :
189 - - It waits for the end of execution of the command and get its result  
190 - - If command is timed out or has been skipped or killed, then same command will be re-executed at next iteration  
191 - - Then only, it goes to next iteration 192 + - It waits (non blocking) for the end of execution of the command and get its result
  193 + - If command is timed out or has been skipped or killed, then it is NOT re-executed at next iteration (except if needed explicitely)
192 """ 194 """
193 195
  196 + """
  197 + PLANTUML ACTIVITY DIAGRAM
  198 + # (http://plantuml.com/fr/activity-diagram-legacy)
  199 + """
  200 +
  201 + """
  202 + @startuml
  203 + version
  204 + @enduml
  205 + """
  206 +
  207 + """
  208 + @startuml
  209 +
  210 + title
  211 + __** Agent.run() function activity diagram **__
  212 + end title
  213 +
  214 + skinparam activity {
  215 + StartColor red
  216 + EndColor Silver
  217 + BackgroundColor Peru
  218 + BackgroundColor<< Begin >> Olive
  219 + BorderColor Peru
  220 + FontName Impact
  221 + }
  222 +
  223 + (*) --> load_config()
  224 +
  225 + --> init()
  226 +
  227 + partition infinite_loop {
  228 + ---> "reload_config()"
  229 + note right
  230 + only if changed
  231 + end note
  232 +
  233 + --> log_agent_status()
  234 + note right
  235 + Log this agent status in DB
  236 + end note
  237 +
  238 + --> routine_process()
  239 +
  240 + --> cmd = get_next_valid_command()
  241 + --> cmd = command_process(cmd)
  242 + note right
  243 + only if there is a command
  244 + end note
  245 + }
  246 +
  247 + If "NEW ITERATION ?" then
  248 + --> [Yes] "reload_config()"
  249 + else
  250 + --> (*)
  251 + Endif
  252 +
  253 + @enduml
  254 + """
  255 +
  256 +
194 257
195 # Maximum duration of this agent (only for SIMULATION mode) 258 # Maximum duration of this agent (only for SIMULATION mode)
196 # If set to None, it will never exit except if asked (or CTRL-C) 259 # If set to None, it will never exit except if asked (or CTRL-C)
197 # If set to 20, it will exit after 20s 260 # If set to 20, it will exit after 20s
198 SIMULATOR_MAX_DURATION_SEC = None 261 SIMULATOR_MAX_DURATION_SEC = None
199 #SIMULATOR_MAX_DURATION_SEC = 30 262 #SIMULATOR_MAX_DURATION_SEC = 30
200 - 263 +
201 # FOR TEST ONLY 264 # FOR TEST ONLY
202 # Run this agent in simulator mode 265 # Run this agent in simulator mode
203 SIMULATOR_MODE = True 266 SIMULATOR_MODE = True
@@ -345,10 +408,10 @@ class Agent: @@ -345,10 +408,10 @@ class Agent:
345 self.RUN_IN_THREAD = RUN_IN_THREAD 408 self.RUN_IN_THREAD = RUN_IN_THREAD
346 self.set_status(self.STATUS_LAUNCH) 409 self.set_status(self.STATUS_LAUNCH)
347 self.set_idle() 410 self.set_idle()
348 - 411 +
349 self._log = LogPyros() 412 self._log = LogPyros()
350 self._log.set_agent_alias(self.name) 413 self._log.set_agent_alias(self.name)
351 - 414 +
352 #self.set_mode(self.MODE_IDLE) 415 #self.set_mode(self.MODE_IDLE)
353 if not config_filename: 416 if not config_filename:
354 config_filename = self.DEFAULT_CONFIG_FILE_NAME 417 config_filename = self.DEFAULT_CONFIG_FILE_NAME
@@ -379,11 +442,11 @@ class Agent: @@ -379,11 +442,11 @@ class Agent:
379 #if len(tmp) == 0: 442 #if len(tmp) == 0:
380 #nb_agents = AgentSurvey.objects.filter(name=self.name).count() 443 #nb_agents = AgentSurvey.objects.filter(name=self.name).count()
381 #if nb_agents == 0: 444 #if nb_agents == 0:
382 - if not AgentSurvey.objects.filter(name=self.name).exists(): 445 + if AgentSurvey.objects.filter(name=self.name).exists():
  446 + self._agent_survey = AgentSurvey.objects.get(name=self.name)
  447 + else:
383 self._agent_survey = AgentSurvey.objects.create(name=self.name, validity_duration_sec=60, mode=self.mode, status=self.status) 448 self._agent_survey = AgentSurvey.objects.create(name=self.name, validity_duration_sec=60, mode=self.mode, status=self.status)
384 - self.printd("Agent survey is", self._agent_survey)  
385 - #self._agent_survey = AgentSurvey(name=self.name, validity_duration_sec=60, mode=self.mode, status=self.status)  
386 - #self._agent_survey.save() 449 + self.printd("Agent survey is", self._agent_survey)
387 450
388 def __repr__(self): 451 def __repr__(self):
389 return "I am agent " + self.name 452 return "I am agent " + self.name
@@ -417,7 +480,7 @@ class Agent: @@ -417,7 +480,7 @@ class Agent:
417 """ 480 """
418 481
419 self.load_config() 482 self.load_config()
420 - 483 +
421 if self.SIMULATOR_MODE: 484 if self.SIMULATOR_MODE:
422 self._log.print("[IN SIMULATOR MODE]") 485 self._log.print("[IN SIMULATOR MODE]")
423 else: 486 else:
@@ -440,11 +503,6 @@ class Agent: @@ -440,11 +503,6 @@ class Agent:
440 Command.delete_pending_commands_for_agent(self.name) 503 Command.delete_pending_commands_for_agent(self.name)
441 504
442 ''' 505 '''
443 - self.printd()  
444 - self.printd(self)  
445 - self.printd("FOR REAL ?", self.FOR_REAL)  
446 - self.printd("DB3 used is:", djangosettings.DATABASES["default"]["NAME"])  
447 -  
448 # SETUP 506 # SETUP
449 try: 507 try:
450 self.config = get_object_or_404(Config, id=1) 508 self.config = get_object_or_404(Config, id=1)
@@ -467,7 +525,7 @@ class Agent: @@ -467,7 +525,7 @@ class Agent:
467 525
468 # Bad number of iterations, so exit 526 # Bad number of iterations, so exit
469 if nb_iter is not None: 527 if nb_iter is not None:
470 - if nb_iter <= 0: break 528 + if nb_iter <= 0: break
471 # Number of iterations asked is reached, so exit 529 # Number of iterations asked is reached, so exit
472 if self._iter_num > nb_iter: 530 if self._iter_num > nb_iter:
473 print(f"Exit because number of iterations asked ({nb_iter}) has been reached") 531 print(f"Exit because number of iterations asked ({nb_iter}) has been reached")
@@ -488,8 +546,8 @@ class Agent: @@ -488,8 +546,8 @@ class Agent:
488 546
489 self.load_config() # only if changed 547 self.load_config() # only if changed
490 548
491 - # Update my current mode and status in DB  
492 - self.update_survey() 549 + # Log this agent status (update my current mode and status in DB)
  550 + self.log_agent_status()
493 551
494 self.printd("------START COMMMAND PROCESSING------") 552 self.printd("------START COMMMAND PROCESSING------")
495 553
@@ -500,18 +558,17 @@ class Agent: @@ -500,18 +558,17 @@ class Agent:
500 #Command.purge_old_commands_for_agent(self.name) 558 #Command.purge_old_commands_for_agent(self.name)
501 self.purge_old_commands_sent_to_me() 559 self.purge_old_commands_sent_to_me()
502 560
  561 + # ROUTINE process
  562 + #if self.is_active():
  563 + self.routine_process()
  564 + #self.printd("I am IDLE, so I bypass the routine_process (do not send any new command)")
  565 +
503 # Get next command to execute 566 # Get next command to execute
504 cmd = self.get_next_valid_command() 567 cmd = self.get_next_valid_command()
505 #if cmd: cmd = self.general_process(cmd) 568 #if cmd: cmd = self.general_process(cmd)
506 -  
507 # Process this (next) command (if exists) 569 # Process this (next) command (if exists)
508 if cmd: cmd = self.command_process(cmd) 570 if cmd: cmd = self.command_process(cmd)
509 571
510 - # ROUTINE process  
511 - #if self.is_active():  
512 - self.routine_process()  
513 - #self.printd("I am IDLE, so I bypass the routine_process (do not send any new command)")  
514 -  
515 self.printd("------END COMMMAND PROCESSING------") 572 self.printd("------END COMMMAND PROCESSING------")
516 573
517 #self.waitfor(self.mainloop_waittime) 574 #self.waitfor(self.mainloop_waittime)
@@ -519,7 +576,7 @@ class Agent: @@ -519,7 +576,7 @@ class Agent:
519 self.print("-"*20, "MAIN LOOP ITERATION (END)", "-"*20) 576 self.print("-"*20, "MAIN LOOP ITERATION (END)", "-"*20)
520 #self.do_log(LOG_DEBUG, "Ending main loop iteration") 577 #self.do_log(LOG_DEBUG, "Ending main loop iteration")
521 578
522 - # Exit if max duration is reached 579 + # (simulator only) Exit if max duration is reached
523 if self.SIMULATOR_MAX_DURATION_SEC and (time.time()-start_time > self.SIMULATOR_MAX_DURATION_SEC): 580 if self.SIMULATOR_MAX_DURATION_SEC and (time.time()-start_time > self.SIMULATOR_MAX_DURATION_SEC):
524 self.print("Exit because of max duration set to ", self.SIMULATOR_MAX_DURATION_SEC, "s") 581 self.print("Exit because of max duration set to ", self.SIMULATOR_MAX_DURATION_SEC, "s")
525 self.kill_running_specific_cmd_if_exists() 582 self.kill_running_specific_cmd_if_exists()
@@ -782,15 +839,21 @@ class Agent: @@ -782,15 +839,21 @@ class Agent:
782 self._log.set_home(home) 839 self._log.set_home(home)
783 840
784 841
785 - def update_survey(self):  
786 - self.printd("Updating the survey database table...") 842 + #def update_survey(self):
  843 + def log_agent_status(self):
  844 + """
  845 + Save (update) this agent current mode and status in DB
  846 + """
  847 + self.printd("Updating the agent survey database table...")
787 #self.printd("- fetching table line for agent", self.name) 848 #self.printd("- fetching table line for agent", self.name)
788 # only necessary when using process (not necessary with threads) 849 # only necessary when using process (not necessary with threads)
789 #with transaction.atomic(): 850 #with transaction.atomic():
790 - self._agent_survey = AgentSurvey.objects.get(name=self.name) 851 + #self._agent_survey = AgentSurvey.objects.get(name=self.name)
791 self._agent_survey.mode = self.mode 852 self._agent_survey.mode = self.mode
792 self._agent_survey.status = self.status 853 self._agent_survey.status = self.status
793 - self._agent_survey.save() 854 + #self._agent_survey.save()
  855 + self._agent_survey.save(update_fields=["mode", "status"])
  856 +
794 857
795 """ 858 """
796 def send_command(self, cmd_name): 859 def send_command(self, cmd_name):
src/agent/AgentA.py
@@ -69,6 +69,7 @@ class AgentA(Agent): @@ -69,6 +69,7 @@ class AgentA(Agent):
69 def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True): 69 def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True):
70 if name is None: name = self.__class__.__name__ 70 if name is None: name = self.__class__.__name__
71 super().__init__(name, config_filename, RUN_IN_THREAD) 71 super().__init__(name, config_filename, RUN_IN_THREAD)
  72 + self._log.print(f"init done for {name}")
72 73
73 # @override 74 # @override
74 def init(self): 75 def init(self):
src/agent/Agent_run_activitydiag.png 0 → 100644

39.4 KB

src/agent/logpyros.py
@@ -9,8 +9,8 @@ py_pwd = os.getcwd() + &quot;/../utils&quot; @@ -9,8 +9,8 @@ py_pwd = os.getcwd() + &quot;/../utils&quot;
9 if (py_pwd not in py_path): 9 if (py_pwd not in py_path):
10 (os.sys.path).append(py_pwd) 10 (os.sys.path).append(py_pwd)
11 11
12 -#import utils.celme as celme  
13 -import celme 12 +import utils.celme as celme
  13 +#import celme
14 14
15 class LogPyros: 15 class LogPyros:
16 16