Commit f3d076fba7d78925dce437ed3d1a26cd2472a4ea

Authored by Etienne Pallier
1 parent cc6b669f
Exists in dev

Génération automatique des diagrammes PlantUML avec "pyros update"

.gitignore
... ... @@ -4,6 +4,7 @@ venv
4 4 __pycache__
5 5 *.pyc
6 6 *.py.bak
  7 +*.png
7 8 #/.settings/
8 9 #/.pydevproject
9 10 src/images/*_*
... ...
README.md
... ... @@ -67,13 +67,14 @@ This software has been tested and validated with the following configurations :
67 67 --------------------------------------------------------------------------------------------
68 68 ## LAST VERSION
69 69  
70   -Date: 02/04/2019
  70 +Date: 17/04/2019
71 71  
72 72 Author: E. Pallier
73 73  
74   -VERSION: 0.20.37
  74 +VERSION: 0.20.38
75 75  
76   -Comment: Implémentation complète du "Command state diag"
  76 +Comment:
  77 + Génération automatique des diagrammes PlantUML avec "pyros update"
77 78  
78 79 - Scenario de test :
79 80 - lancer agents A et B en mode simu (option -t): ./pyros.py -t start agentA,agentB
... ... @@ -88,6 +89,7 @@ Comment: Implémentation complète du "Command state diag"
88 89 - pour utiliser thread ou processus : il suffit de mettre la constante RUN_IN_THREAD de AgentA (ou AgentB ou AgentX) à False ou True
89 90  
90 91 - Historique des nouveautés implémentées :
  92 + - Implémentation complète du "Command state diag"
91 93 - Nouveaux diagrammes UML pour Command (state diag) et Agent (activity diag)
92 94 - Déplacé AgentM dans src/monitoring/ (pyros start agentM)
93 95 - Implémenté la commande "restart_init" (voir doc "play with a pyros agent") et refactorisation de run()
... ...
doc/PyROS dev-guide.pdf
No preview for this file type
install/REQUIREMENTS.txt
... ... @@ -29,6 +29,7 @@ zope.interface==4.5.0
29 29  
30 30 # For DEV
31 31 django-debug-toolbar==1.9.1
  32 +plantuml
32 33  
33 34 # For Celery:
34 35 ##celery==3.1.23
... ...
install/REQUIREMENTS_WINDOWS.txt
... ... @@ -32,6 +32,7 @@ zope.interface==4.5.0
32 32  
33 33 # For DEV
34 34 django-debug-toolbar==1.9.1
  35 +plantuml
35 36  
36 37 # For Celery:
37 38 ##celery==3.1.23
... ...
pyros.py
... ... @@ -3,6 +3,7 @@
3 3  
4 4 import argparse
5 5 import fileinput
  6 +import glob
6 7 import os
7 8 import platform
8 9 import signal
... ... @@ -18,7 +19,7 @@ import time
18 19 *****************************************************************
19 20 """
20 21  
21   -DEBUG = True
  22 +DEBUG = False
22 23  
23 24 INIT_FIXTURE = "initial_fixture.json"
24 25  
... ... @@ -121,7 +122,8 @@ def die(msg: str = ""):
121 122 #TODO: implement is_async
122 123 def execProcess(command, from_venv=False, is_async=False):
123 124 from_venv_str = " from venv ("+VENV_BIN+")" if from_venv else ""
124   - printFullTerm(Colors.BLUE, "Executing command" + " [" + command + "]" + from_venv_str)
  125 + #printFullTerm(Colors.BLUE, "Executing command" + " [" + command + "]" + from_venv_str)
  126 + print("Executing command" + " [" + command + "]" + from_venv_str)
125 127 if from_venv: command = VENV_BIN+' ' + command
126 128 process = subprocess.Popen(command, shell=True)
127 129 if is_async:
... ... @@ -303,11 +305,21 @@ TODO:
303 305 @pyros_launcher.command(help="Update (only if necessary) the python packages AND the source code AND the DB structure")
304 306 def update():
305 307 print("Running update command")
  308 +
306 309 # 1) Update source code (git pull)
  310 + printFullTerm(Colors.BLUE, "1) UPDATING SOURCE CODE: Running git pull")
307 311 _gitpull() or die()
  312 +
308 313 # 2) Update python packages (pip install requirements)
  314 + printFullTerm(Colors.BLUE, "2) UPDATING PYTHON PACKAGES")
309 315 _update_python_packages_from_requirements() or die()
310   - # 3) Update database structure (make migrations + migrate)
  316 +
  317 + # 3) Update PlantUML diagrams
  318 + printFullTerm(Colors.BLUE, "3) UPDATING PLANTUML DIAGRAMS")
  319 + _update_plantuml_diags() or die()
  320 +
  321 + # 4) Update database structure (make migrations + migrate)
  322 + printFullTerm(Colors.BLUE, "4) UPDATING DATABASE")
311 323 _updatedb() or die()
312 324 return True
313 325  
... ... @@ -412,11 +424,11 @@ def start(agent:str, configfile:str):
412 424 # Append this process ( [process id, agent_name, result=failure] )
413 425 # ("result" will be updated at the end of execution)
414 426 current_processes.append( [execProcessFromVenvAsync(cmd), agent_name, -1] )
415   - # self._change_dir("..")
  427 + # self.change_dir("..")
416 428 os.chdir(current_dir)
417 429  
418 430 # Go back to root folder (/)
419   - # self._change_dir('..')
  431 + # self.change_dir('..')
420 432 #os.chdir("..")
421 433 # Wait for end of each process execution
422 434 #for (p,agent) in current_processes:
... ... @@ -469,32 +481,42 @@ def _update_python_packages_from_requirements():
469 481 res = execProcessFromVenv("-m pip install -r install/"+REQUIREMENTS)
470 482 return res
471 483  
  484 +def _update_plantuml_diags():
  485 + change_dir("src")
  486 + for entry in os.listdir("."):
  487 + if os.path.isdir(entry):
  488 + change_dir(entry)
  489 + if glob.glob("*.pu"): res = execProcessFromVenv("-m plantuml *.pu")
  490 + change_dir("..")
  491 + change_dir("..")
  492 + return res
  493 +
472 494 def _migrate():
473   - _change_dir("src")
  495 + change_dir("src")
474 496 # Migrate only migrations for the app "common"
475 497 #res = execProcessFromVenv("manage.py migrate common")
476 498 # Migrate all migrations for ALL apps
477 499 res = execProcessFromVenv("manage.py migrate")
478   - _change_dir("..")
  500 + change_dir("..")
479 501 return res
480 502  
481 503 def _makemigrations():
482   - _change_dir("src")
  504 + change_dir("src")
483 505 #execProcessFromVenv(self.venv_bin + " manage.py makemigrations")
484 506 #res = execProcessFromVenv("manage.py makemigrations common")
485 507 res = execProcessFromVenv("manage.py makemigrations")
486   - _change_dir("..")
  508 + change_dir("..")
487 509 return res
488 510  
489 511 #TODO: mettre la fixture en date naive (sans time zone)
490 512 def _loaddata():
491   - _change_dir("src")
  513 + change_dir("src")
492 514 #execProcessFromVenv(self.venv_bin + " manage.py loaddata misc" + os.sep + "fixtures" + os.sep + self.INIT_FIXTURE)
493 515 res = execProcessFromVenv("manage.py loaddata misc" + os.sep + "fixtures" + os.sep + INIT_FIXTURE)
494   - _change_dir("..")
  516 + change_dir("..")
495 517 return res
496 518  
497   -def _change_dir(path):
  519 +def change_dir(path):
498 520 if DEBUG: print("Moving to : " + path)
499 521 os.chdir(path)
500 522 if DEBUG: print("Current directory : " + str(os.getcwd()))
... ...
src/agent/Agent.py
... ... @@ -17,6 +17,9 @@ DEBUG=False
17 17 """
18 18 =================================================================
19 19 SETUP FOR DJANGO
  20 +
  21 + (see https://docs.djangoproject.com/en/dev/topics/settings)
  22 + (see also https://docs.djangoproject.com/en/dev/ref/settings)
20 23 =================================================================
21 24 """
22 25  
... ... @@ -184,6 +187,9 @@ class StoppableThreadEvenWhenSleeping(threading.Thread):
184 187  
185 188 class Agent:
186 189 """
  190 +
  191 + See Agent_activity_diag.pu for PlantUML activity diagram
  192 +
187 193 Behavior of an agent:
188 194 - If idle :
189 195 - still does routine_process() and general_process()
... ... @@ -193,140 +199,6 @@ class Agent:
193 199 - If command is timed out or has been skipped or killed, then it is NOT re-executed at next iteration (except if needed explicitely)
194 200 """
195 201  
196   - """
197   - # --- Agent ACTIVIY DIAGRAM (plantUML) ---
198   - # NEW syntax => http://plantuml.com/fr/activity-diagram-beta
199   - # OLD syntax => http://plantuml.com/fr/activity-diagram-legacy
200   -
201   - @startuml
202   - version
203   - @enduml
204   -
205   - # Exemple de skin utilisable (celui de ChemCam) :
206   - skinparam activity {
207   - StartColor red
208   - EndColor Silver
209   - BackgroundColor Peru
210   - BackgroundColor<< Begin >> Olive
211   - BorderColor Peru
212   - FontName Impact
213   - }
214   -
215   - (NEW SYNTAX)
216   - @startuml
217   -
218   - title
219   - __**Agent.run() function : Activity Diagram**__
220   -
221   - end title
222   -
223   - start
224   -
225   - :DO_EXIT = False
226   - DO_RESTART = True;
227   -
228   - while (DO_RESTART ?) is (yes)
229   - :load_config();
230   - :init();
231   - :DO_MAIN_LOOP = True;
232   - while (DO_MAIN_LOOP ?) is (yes)
233   - partition main_loop() {
234   - :reload_config();
235   - note right
236   - only if changed
237   - end note
238   -
239   - :log_agent_status();
240   - note right
241   - Log this agent status in DB
242   - end note
243   -
244   - :routine_process();
245   -
246   - :cmd = get_next_valid_command();
247   - partition command_process(cmd) {
248   - note right
249   - only if there is a command
250   - end note
251   - :cmd = general_process(cmd);
252   - :specific_process(cmd);
253   - note right
254   - only if I am "active"
255   - end note
256   - }
257   - if (DO_RESTART or DO_EXIT ?) then (yes)
258   - :DO_MAIN_LOOP = False;
259   - endif
260   -
261   -
262   -
263   -
264   - }
265   - endwhile (no)
266   - endwhile (no)
267   -
268   - stop
269   -
270   - @enduml
271   -
272   -
273   - (OLD SYNTAX)
274   - @startuml
275   - title
276   - __** (OLD) Agent.run() function activity diagram **__
277   - end title
278   -
279   - (*) --> DO_EXIT=False & DO_RESTART=True
280   -
281   - partition while-DO_RESTART {
282   - --> load_config()
283   - --> init()
284   - --> DO_MAIN_LOOP = True
285   - --> main_loop()
286   -
287   - partition while-DO_MAIN_LOOP {
288   - partition main_loop() {
289   -
290   - ---> "reload_config()"
291   - note right
292   - only if changed
293   - end note
294   -
295   - --> log_agent_status()
296   - note right
297   - Log this agent status in DB
298   - end note
299   -
300   - --> routine_process()
301   -
302   - --> cmd = get_next_valid_command()
303   - --> cmd = command_process(cmd)
304   - note right
305   - only if there is a command
306   - end note
307   - partition command_process(cmd) {
308   - --> cmd = self.general_process(cmd)
309   - --> specific_process(cmd)
310   - note right
311   - only if there is a command and I am "active"
312   - end note
313   - }
314   - }
315   - }
316   -
317   - If "NEW ITERATION ?" then
318   - --> "reload_config()"
319   - else
320   - --> [No] (*)
321   - Endif
322   -
323   - }
324   -
325   - @enduml
326   - """
327   -
328   -
329   -
330 202 # Maximum duration of this agent (only for SIMULATION mode)
331 203 # If set to None, it will never exit except if asked (or CTRL-C)
332 204 # If set to 20, it will exit after 20s
... ...
src/agent/Agent_run_activitydiag.uml renamed to src/agent/Agent_activity_diag.pu
1   - ' Everything that starts with simple quote ' is a comment.
2   - ' NEW syntax => http://plantuml.com/fr/activity-diagram-beta
3   -
4   - @startuml
5   -
6   - title
7   - __**Agent.run() function : Activity Diagram **__
8   -
9   - end title
10   -
11   - start
12   -
13   - :DO_EXIT = False
14   - DO_RESTART = True;
15   -
16   - while (DO_RESTART ?) is (yes)
17   - :load_config();
18   - :init();
19   - :DO_MAIN_LOOP = True;
20   - while (DO_MAIN_LOOP ?) is (yes)
21   - partition main_loop() {
22   - :reload_config();
23   - note right
24   - only if changed
25   - end note
26   -
27   - :log_agent_status();
28   - note right
29   - Log this agent status in DB
30   - end note
31   -
32   - :routine_process();
33   -
34   - :cmd = get_next_valid_command();
35   - partition command_process(cmd) {
36   - :cmd = self.general_process(cmd);
37   - note right
38   - only if there is a command
39   - end note
40   - :specific_process(cmd);
  1 +
  2 +@startuml
  3 +
  4 +' --- Agent ACTIVIY DIAGRAM (plantUML) ---
  5 +
  6 +' NEW syntax => http://plantuml.com/fr/activity-diagram-beta
  7 +' OLD syntax => http://plantuml.com/fr/activity-diagram-legacy
  8 +' (See also https://plantweb.readthedocs.io)
  9 +' (See also https://pythonhosted.org/plantuml)
  10 +
  11 +' What is the current version of PlantUML (and Java) used ?
  12 +' startuml
  13 +' version
  14 +' enduml
  15 +
  16 +' Exemple de skin utilisable (celui de ChemCam) :
  17 +' skinparam activity {
  18 +' StartColor red
  19 +' EndColor Silver
  20 +' BackgroundColor Peru
  21 +' BackgroundColor<< Begin >> Olive
  22 +' BorderColor Peru
  23 +' FontName Impact
  24 +' }
  25 +
  26 +
  27 +title
  28 +__**Agent.run() function : Activity Diagram**__
  29 +
  30 +end title
  31 +
  32 +
  33 +start
  34 +
  35 +:DO_EXIT = False
  36 +DO_RESTART = True;
  37 +
  38 +while (DO_RESTART ?) is (yes)
  39 + :load_config();
  40 + :init();
  41 + :DO_MAIN_LOOP = True;
  42 + while (DO_MAIN_LOOP ?) is (yes)
  43 + partition main_loop() {
  44 + :reload_config();
  45 + note right
  46 + only if changed
  47 + end note
  48 +
  49 + :log_agent_status();
  50 + note right
  51 + Log this agent status in DB
  52 + end note
  53 +
  54 + :routine_process();
  55 +
  56 + :cmd = get_next_valid_command();
  57 + if (cmd ?) then
  58 + partition command_process(cmd) {
  59 + :cmd = general_process(cmd);
  60 + if (cmd ?) then
  61 + :specific_process(cmd);
  62 + else (no)
  63 + endif
41 64 note right
42   - only if there is a command and I am "active"
  65 + only if I am "active"
43 66 end note
44 67 }
45   - if (DO_RESTART or DO_EXIT ?) then (yes)
46   - :DO_MAIN_LOOP = False;
47   - endif
48   - }
49   - endwhile (no)
  68 + else (no)
  69 + endif
  70 + if (DO_RESTART or DO_EXIT ?) then (yes)
  71 + :DO_MAIN_LOOP = False;
  72 + endif
  73 +
  74 +
  75 +
  76 +
  77 + }
50 78 endwhile (no)
  79 +endwhile (no)
51 80  
52   - stop
  81 +stop
53 82  
54   - @enduml
  83 +@enduml
... ...
src/common/models.py
... ... @@ -321,49 +321,8 @@ class Command(models.Model):
321 321  
322 322 """
323 323 | id | sender | recipient | name | validity_duration (default=60) | s_deposit_time | r_read_time
324   - """
325   -
326   - """
327   - # --- Command STATE DIAGRAM ---
328   - # http://plantuml.com/fr/state-diagram
329   - @startuml
330   -
331   - title
332   - __**models.Command class : State Diagram**__
333   -
334   - end title
335   -
336   - [*] --> PENDING : **created by sender**
337   -
338   - ' --- (1) PENDING ---
339   - PENDING: + s_deposit_time \n+ r_read_time
340   - PENDING --> RUNNING : **launched**
341   - PENDING --> SKIPPED: **recipient is IDLE**
342   - PENDING --> EXPIRED: **command is too old**
343   - PENDING --> INVALIDATED: **cancelled by sender**
344   -
345   - ' --- (2) RUNNING, SKIPPED, or EXPIRED ---
346   - RUNNING: + r_start_time
347   - RUNNING --> EXECUTED : **finished**
348   - RUNNING --> KILLED: \l**aborted** \n(by sender or other allowed agent, \nwith command "abort" or "exit")
349   -
350   - SKIPPED: + end_time
351   - SKIPPED --> [*]
352   -
353   - EXPIRED --> [*]
354   - EXPIRED: + end_time \n+ killer_agent_name
355   -
356   - INVALIDATED --> [*]
357   - INVALIDATED: + end_time \n+ killer_agent_name
358   -
359   - ' --- (3) PROCESSED or KILLED ---
360   - EXECUTED: + end_time
361   - EXECUTED --> [*]
362   -
363   - KILLED --> [*]
364   - KILLED: + end_time \n+ killer_agent_name
365 324  
366   - @enduml
  325 + See models_Command_state_diag.pu for PlantUML state diagram
367 326 """
368 327  
369 328 # -------------- Command CONSTANTS --------------
... ...
src/common/models_Command_state_diag.pu 0 → 100644
... ... @@ -0,0 +1,42 @@
  1 +
  2 +@startuml
  3 +
  4 +' --- Command STATE DIAGRAM ---
  5 +' (see http://plantuml.com/fr/state-diagram)
  6 +
  7 +title
  8 +__**models.Command class : State Diagram**__
  9 +
  10 +end title
  11 +
  12 +[*] --> PENDING : **created by sender**
  13 +
  14 +' --- (1) PENDING ---
  15 +PENDING: + s_deposit_time \n+ r_read_time
  16 +PENDING --> RUNNING : **launched**
  17 +PENDING --> SKIPPED: **recipient is IDLE**
  18 +PENDING --> EXPIRED: **command is too old**
  19 +PENDING --> INVALIDATED: **cancelled by sender**
  20 +
  21 +' --- (2) RUNNING, SKIPPED, or EXPIRED ---
  22 +RUNNING: + r_start_time
  23 +RUNNING --> EXECUTED : **finished**
  24 +RUNNING --> KILLED: \l**aborted** \n(by sender or other allowed agent, \nwith command "abort" or "exit")
  25 +
  26 +SKIPPED: + end_time
  27 +SKIPPED --> [*]
  28 +
  29 +EXPIRED --> [*]
  30 +EXPIRED: + end_time \n+ killer_agent_name
  31 +
  32 +INVALIDATED --> [*]
  33 +INVALIDATED: + end_time \n+ killer_agent_name
  34 +
  35 +' --- (3) PROCESSED or KILLED ---
  36 +EXECUTED: + end_time
  37 +EXECUTED --> [*]
  38 +
  39 +KILLED --> [*]
  40 +KILLED: + end_time \n+ killer_agent_name
  41 +
  42 +@enduml
... ...