Commit f3d076fba7d78925dce437ed3d1a26cd2472a4ea
1 parent
cc6b669f
Exists in
dev
Génération automatique des diagrammes PlantUML avec "pyros update"
Showing
10 changed files
with
168 additions
and
239 deletions
Show diff stats
.gitignore
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
install/REQUIREMENTS_WINDOWS.txt
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 -------------- | ... | ... |
... | ... | @@ -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 | ... | ... |