Blame view

pyros.py 20.8 KB
efbcac9e   Etienne Pallier   1st version of NE...
1
2
#!/usr/bin/env python3

ddb06a2a   Etienne Pallier   new pyros2 launch...
3
4
5

import argparse
import fileinput
f3d076fb   Etienne Pallier   Génération automa...
6
import glob
efbcac9e   Etienne Pallier   1st version of NE...
7
import os
efbcac9e   Etienne Pallier   1st version of NE...
8
import platform
efbcac9e   Etienne Pallier   1st version of NE...
9
import signal
ddb06a2a   Etienne Pallier   new pyros2 launch...
10
11
12
import subprocess
import sys
import time
efbcac9e   Etienne Pallier   1st version of NE...
13

1f6376dd   Etienne Pallier   pyros2 refactor &...
14

1f6376dd   Etienne Pallier   pyros2 refactor &...
15
16
17
18
19
20
21

"""
*****************************************************************
******************** GENERAL CONSTANTS **************************
*****************************************************************
"""

f3d076fb   Etienne Pallier   Génération automa...
22
DEBUG = False
a3015e31   Etienne Pallier   table des commandes
23

ad6d274a   Etienne Pallier   Restructuration d...
24
25
PYROS_DJANGO_BASE_DIR = "src/core/pyros_django"

a3015e31   Etienne Pallier   table des commandes
26
INIT_FIXTURE = "initial_fixture.json"
01348735   Etienne Pallier   Bugfix pyros.py s...
27

ad6d274a   Etienne Pallier   Restructuration d...
28
29
_previous_dir = None

eac3e2ab   Etienne Pallier   New AgentX
30
AGENTS = {
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
31
    #"agentX" : "agent", 
ff0550d2   Etienne Pallier   Multi-agents : Ag...
32
    "agent" : "Agent", 
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
33
34
    "agentX" : "AgentX", 
    "agentA" : "AgentA", 
c84ca326   Etienne Pallier   Multi-agents (3 a...
35
    "agentB" : "AgentB", 
5b835b38   Etienne Pallier   agentM
36
    "agentM" : "AgentM", 
6308819c   Etienne Pallier   déplacé le dossie...
37
    "agentDevice" : "AgentDevice", 
128e1a71   Etienne Pallier   AgentDevice + Age...
38
    "agentTelescopeRequester" : "AgentTelescopeRequester", 
eac3e2ab   Etienne Pallier   New AgentX
39
40
41
42
43
44
45
    "webserver" : "webserver", 
    "monitoring" : "monitoring", 
    "majordome" : "majordome", 
    "scheduler" : "scheduler", 
    "alert_manager" : "alert_manager"
}
#AGENTS = ["agentX", "webserver", "monitoring", "majordome", "scheduler", "alert_manager"]
1f6376dd   Etienne Pallier   pyros2 refactor &...
46
47
48
49
#AGENTS = ["all", "webserver", "monitoring", "majordome", "scheduler", "alert"]

#COMMANDS = {"install": [], "start": AGENTS, "stop": AGENTS}

082ccda3   Etienne Pallier   pyros.py : enrich...
50
51
52
53
54
REQUIREMENTS = 'REQUIREMENTS.txt'
b_in_dir = "bin"
PYTHON = "python3"
# should also be ok from venv:
#PYTHON = "python"
1f6376dd   Etienne Pallier   pyros2 refactor &...
55

082ccda3   Etienne Pallier   pyros.py : enrich...
56
IS_WINDOWS = platform.system() == "Windows"
1f6376dd   Etienne Pallier   pyros2 refactor &...
57
if IS_WINDOWS:
082ccda3   Etienne Pallier   pyros.py : enrich...
58
    REQUIREMENTS = 'REQUIREMENTS_WINDOWS.txt'
a3015e31   Etienne Pallier   table des commandes
59
    b_in_dir = "Scripts"
1f6376dd   Etienne Pallier   pyros2 refactor &...
60
    PYTHON = "python.exe"
082ccda3   Etienne Pallier   pyros.py : enrich...
61
62

my_abs_path = os.path.dirname(os.path.realpath(__file__))
1f6376dd   Etienne Pallier   pyros2 refactor &...
63
64
VENV_BIN = (
    my_abs_path
77f1c546   Etienne Pallier   Ajouté options "t...
65
    + os.sep + "venv"
1f6376dd   Etienne Pallier   pyros2 refactor &...
66
    + os.sep + "venv_py3_pyros"
a3015e31   Etienne Pallier   table des commandes
67
    + os.sep + b_in_dir
1f6376dd   Etienne Pallier   pyros2 refactor &...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    + os.sep + PYTHON
)

class Colors:
    HEADER = "\033[95m"
    BLUE = "\033[94m"
    GREEN = "\033[92m"
    WARNING = "\033[93m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"




ddb06a2a   Etienne Pallier   new pyros2 launch...
84
85
86
87
88
# First, install the click package !!!
#import fire
try:
    import click # https://click.palletsprojects.com
except:
1f6376dd   Etienne Pallier   pyros2 refactor &...
89
90
    #pip = "pip" if platform.system() == "Windows" else "pip3"
    pip = "pip" if IS_WINDOWS else "pip3"
ddb06a2a   Etienne Pallier   new pyros2 launch...
91
92
93
94
95
96
97
98
99
100
101
    process = subprocess.Popen(pip + " install --upgrade click", shell=True)
    process.wait()
    if process.returncode == 0:
        print("click package installation successfull")
        # self.addExecuted(self.current_command, command)
        import click
    else:
        print("click package installation failed")
        # self.addError(self.current_command, command)
        
    
efbcac9e   Etienne Pallier   1st version of NE...
102

efbcac9e   Etienne Pallier   1st version of NE...
103
104


efbcac9e   Etienne Pallier   1st version of NE...
105

1f6376dd   Etienne Pallier   pyros2 refactor &...
106
107
108
109
110
"""
**************************************************************************
******************** GENERAL AND UTIL FUNCTIONS **************************
**************************************************************************
"""
efbcac9e   Etienne Pallier   1st version of NE...
111

a3015e31   Etienne Pallier   table des commandes
112
def _in_dir(dirname: str = ""):
b2e9866d   Etienne Pallier   bugfix start_agen...
113
    return os.path.basename(os.getcwd()) == dirname
efbcac9e   Etienne Pallier   1st version of NE...
114

efbcac9e   Etienne Pallier   1st version of NE...
115

a3015e31   Etienne Pallier   table des commandes
116
def _in_abs_dir(dirname: str = ""):
b2e9866d   Etienne Pallier   bugfix start_agen...
117
    return os.getcwd() == dirname
efbcac9e   Etienne Pallier   1st version of NE...
118
119


a3015e31   Etienne Pallier   table des commandes
120
121
122
def die(msg: str = ""):
    print()
    print("...ERROR...")
b2e9866d   Etienne Pallier   bugfix start_agen...
123
    print(msg)
a3015e31   Etienne Pallier   table des commandes
124
    print()
b2e9866d   Etienne Pallier   bugfix start_agen...
125
    exit(1)
a3015e31   Etienne Pallier   table des commandes
126
    
efbcac9e   Etienne Pallier   1st version of NE...
127

1f6376dd   Etienne Pallier   pyros2 refactor &...
128
129
#TODO: implement is_async
def execProcess(command, from_venv=False, is_async=False):
67f74b9e   Etienne Pallier   cleanup
130
    from_venv_str = " from venv ("+VENV_BIN+")" if from_venv else ""
f3d076fb   Etienne Pallier   Génération automa...
131
132
    #printFullTerm(Colors.BLUE, "Executing command" + " [" + command + "]" + from_venv_str)
    print("Executing command" + " [" + command + "]" + from_venv_str)
1f6376dd   Etienne Pallier   pyros2 refactor &...
133
    if from_venv: command = VENV_BIN+' ' + command
b2e9866d   Etienne Pallier   bugfix start_agen...
134
    process = subprocess.Popen(command, shell=True)
31e31f3b   Etienne Pallier   pyros.py peut lan...
135
136
137
138
    if is_async:
        #current_processes.append(process)
        return process
    # Not is_async => Wait for end of execution
b2e9866d   Etienne Pallier   bugfix start_agen...
139
140
141
142
143
144
145
    process.wait()
    if process.returncode == 0:
        printFullTerm(Colors.GREEN, "Process executed successfully")
        # self.addExecuted(self.current_command, command)
    else:
        printFullTerm(Colors.WARNING, "Process execution failed")
        # self.addError(self.current_command, command)
f4fd20f9   Etienne Pallier   pyros.py script i...
146
147
    #return process.returncode
    return True if process.returncode==0 else False
efbcac9e   Etienne Pallier   1st version of NE...
148

31e31f3b   Etienne Pallier   pyros.py peut lan...
149
150
151
def execProcessFromVenv(command:str, is_async=False):
    #return execProcess(command, from_venv=True, is_async)
    return execProcess(command, True, is_async)
efbcac9e   Etienne Pallier   1st version of NE...
152

1f6376dd   Etienne Pallier   pyros2 refactor &...
153
154
#TODO: fusionner dans execProcess avec param is_async
def execProcessFromVenvAsync(command:str):
31e31f3b   Etienne Pallier   pyros.py peut lan...
155
156
    return execProcessFromVenv(command, True)
    """
b2e9866d   Etienne Pallier   bugfix start_agen...
157
158
159
160
161
162
163
164
165
166
    args = command.split()
    printFullTerm(
        Colors.BLUE, "Executing command from venv [" + str(" ".join(args[1:])) + "]"
    )
    p = subprocess.Popen(args)
    subproc.append((p, " ".join(args[1:])))
    printFullTerm(Colors.GREEN, "Process launched successfully")
    # self.addExecuted(self.current_command, str(' '.join(args[1:])))
    # p.wait()
    return p
31e31f3b   Etienne Pallier   pyros.py peut lan...
167
    """
efbcac9e   Etienne Pallier   1st version of NE...
168

b2e9866d   Etienne Pallier   bugfix start_agen...
169
def printColor(color: Colors, message, file=sys.stdout, eol=os.linesep, forced=False):
1f6376dd   Etienne Pallier   pyros2 refactor &...
170
    #system = platform.system()
b2e9866d   Etienne Pallier   bugfix start_agen...
171
172
    """
    if (self.disp == False and forced == False):
efbcac9e   Etienne Pallier   1st version of NE...
173
        return 0
b2e9866d   Etienne Pallier   bugfix start_agen...
174
    """
1f6376dd   Etienne Pallier   pyros2 refactor &...
175
176
    #if system == "Windows":
    if IS_WINDOWS:
b2e9866d   Etienne Pallier   bugfix start_agen...
177
178
179
180
        print(message, file=file, end=eol)
    else:
        print(color + message + Colors.ENDC, file=file, end=eol)
    return 0
efbcac9e   Etienne Pallier   1st version of NE...
181
182


b2e9866d   Etienne Pallier   bugfix start_agen...
183
def printFullTerm(color: Colors, string: str):
1f6376dd   Etienne Pallier   pyros2 refactor &...
184
    #system = platform.system()
b2e9866d   Etienne Pallier   bugfix start_agen...
185
186
187
188
189
190
191
192
193
    columns = 100
    row = 1000
    disp = True
    value = int(columns / 2 - len(string) / 2)
    printColor(color, "-" * value, eol="")
    printColor(color, string, eol="")
    value += len(string)
    printColor(color, "-" * (columns - value))
    return 0
efbcac9e   Etienne Pallier   1st version of NE...
194

efbcac9e   Etienne Pallier   1st version of NE...
195

f4fd20f9   Etienne Pallier   pyros.py script i...
196
197


ddb06a2a   Etienne Pallier   new pyros2 launch...
198
199

"""
1f6376dd   Etienne Pallier   pyros2 refactor &...
200
201
202
********************************************************************************
******************** CLI COMMANDS DEFINITION (click format) ********************
********************************************************************************
ddb06a2a   Etienne Pallier   new pyros2 launch...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
"""

'''
_global_test_options = [
    click.option('--test', '-t', is_flag=True, help="don't do it for real, just show what it would do"),
    click.option('--verbose', '-v', 'verbosity', flag_value=2, default=1, help='Verbose output'),
    click.option('--quiet', '-q', 'verbosity', flag_value=0, help='Minimal output'),
    #click.option('--fail-fast', '--failfast', '-f', 'fail_fast', is_flag=True, default=False, help='Stop on failure'),
]
def global_test_options(func):
    for option in reversed(_global_test_options):
        func = option(func)
    return func
'''

GLOBAL_OPTIONS = {}
def verbose_mode(): return GLOBAL_OPTIONS["verbose"]
def test_mode(): return GLOBAL_OPTIONS["test"]

@click.group()
@click.option('--test', '-t', is_flag=True, help="don't do it for real, just show what it would do")
@click.option('--verbose', '-v', is_flag=True, help='Verbose output')
#@click.option('--verbose', '-v', 'verbosity', flag_value=2, default=1, help='Verbose output'),
#@click.option('--quiet', '-q', 'verbosity', flag_value=0, help='Minimal output'),
#@click.option('--fail-fast', '--failfast', '-f', 'fail_fast', is_flag=True, default=False, help='Stop on failure'),
def pyros_launcher(test, verbose):
    #pass
    if test: click.echo('Test mode')
    if verbose: click.echo('Verbose mode')
    GLOBAL_OPTIONS["test"] = test
    GLOBAL_OPTIONS["verbose"] = verbose



af5d8b11   Etienne Pallier   Nouveau shell pyr...
237
238
239
240
241
@pyros_launcher.command(help="Run a pyros shell (django included)")
#@global_test_options
def shell():
    print()
    print("Launching a pyros shell")
17ad5e75   Etienne Pallier   updated message d...
242
243
244
245
246
    print()
    print("NB1: If you want to play with an agent, type:")
    print("    >>> from agent.AgentA import AgentA")
    print("    >>> agent=AgentA('agent_toto')")
    print("    >>> agent")
15afe6e1   Etienne Pallier   bugfix Agent.run(...
247
    print("    >>> agent.run(2) (=> will run 2 iterations)")
17ad5e75   Etienne Pallier   updated message d...
248
249
    print("    >>> cmd = agent.send_command('AgentB','eval 2+2')")
    print("    >>> cmd")
ad6d274a   Etienne Pallier   Restructuration d...
250
    print("    >>> cmd.get_updated_result()")
15afe6e1   Etienne Pallier   bugfix Agent.run(...
251
252
    print("    >>> ...")
    print("    - See documentation, section 'Play with a pyros agent' inside the chapter 'Running pyros' for more details")
17ad5e75   Etienne Pallier   updated message d...
253
254
255
256
257
258
259
260
    print()
    print("NB2: If you want to play with the pyros objects, type:")
    print("    >>> from common.models import *")
    print("    - (This will import all the pyros objects)")
    print("    - Then, you can create any pyros object just by typing its name.")
    print("    - For example, to create an AgentSurvey object, type:")
    print("    >>> agent_survey = AgentSurvey()")
    print("    >>> agent_survey")
15afe6e1   Etienne Pallier   bugfix Agent.run(...
261
262
    print("    >>> ...")
    print("    - See documentation, section 'Play with the pyros objects' inside the chapter 'Running pyros' for more details")
17ad5e75   Etienne Pallier   updated message d...
263
    print()
af5d8b11   Etienne Pallier   Nouveau shell pyr...
264
265
    print("Type 'exit()' to quit")
    print()
ad6d274a   Etienne Pallier   Restructuration d...
266
267
    change_dir(PYROS_DJANGO_BASE_DIR)

af5d8b11   Etienne Pallier   Nouveau shell pyr...
268
    # execProcess("python install.py install")
12a0badc   Etienne Pallier   update
269
    if not test_mode(): execProcessFromVenv("manage.py shell")
af5d8b11   Etienne Pallier   Nouveau shell pyr...
270
    # Go back to the initial dir
ad6d274a   Etienne Pallier   Restructuration d...
271
272
    #os.chdir("../")
    change_dir("PREVIOUS")
af5d8b11   Etienne Pallier   Nouveau shell pyr...
273
274
275
    return True


fcfc6200   Etienne Pallier   ajout nouvelle co...
276
277
278
279
@pyros_launcher.command(help="Run a database (Mysql) shell")
def dbshell():
    print()
    print("Launching a database (mysql) shell")
082ccda3   Etienne Pallier   pyros.py : enrich...
280
    print("From this shell, you can type 'show tables;' to see all the pyros tables")
fcfc6200   Etienne Pallier   ajout nouvelle co...
281
282
283
284
    print("Then for example, type 'select * from config;' to see the content of the 'config' table")
    print("Type 'exit' to quit")
    print()
    # execProcess("python install.py install")
ad6d274a   Etienne Pallier   Restructuration d...
285
    if not test_mode(): execProcessFromVenv(PYROS_DJANGO_BASE_DIR+"/manage.py dbshell")
fcfc6200   Etienne Pallier   ajout nouvelle co...
286
287
288
289
    # Go back to the initial dir
    return True


af5d8b11   Etienne Pallier   Nouveau shell pyr...
290
@pyros_launcher.command(help="Install the pyros software")
3a36c853   Etienne Pallier   "./pyros install ...
291
292
@click.option('--packages_only', '-p', is_flag=True, help='install only the python packages (no database installation)')
@click.option('--database_only', '-d', is_flag=True, help='install only the pyros database (no python packages installation)')
ddb06a2a   Etienne Pallier   new pyros2 launch...
293
#@global_test_options
3a36c853   Etienne Pallier   "./pyros install ...
294
def install(packages_only, database_only):
1f6376dd   Etienne Pallier   pyros2 refactor &...
295
    print("Running install command")
3a36c853   Etienne Pallier   "./pyros install ...
296
297
    print("packages_only", packages_only)
    print("database_only", database_only)
ddb06a2a   Etienne Pallier   new pyros2 launch...
298
299
300
    #if test_mode(): print("in test mode")
    # self.execProcess("python3 install/install.py install")
    # if (os.path.basename(os.getcwd()) != "private"):
ddb06a2a   Etienne Pallier   new pyros2 launch...
301
    start_dir = os.getcwd()
a3015e31   Etienne Pallier   table des commandes
302
    os.chdir("install/") ; _in_dir("install") or die("Bad dir")
1f6376dd   Etienne Pallier   pyros2 refactor &...
303
    # execProcess("python install.py install")
3a36c853   Etienne Pallier   "./pyros install ...
304
305
306
307
    option=''
    if packages_only: option='-p'
    if database_only: option='-d'
    test_mode() or execProcess(PYTHON + " install.py " + option)
ddb06a2a   Etienne Pallier   new pyros2 launch...
308
309
    # cd -
    # os.chdir("-")
a3015e31   Etienne Pallier   table des commandes
310
    os.chdir(start_dir) ; _in_abs_dir(start_dir) or die("Bad dir")
ddb06a2a   Etienne Pallier   new pyros2 launch...
311
312
313
    # return 0
    return True

f4fd20f9   Etienne Pallier   pyros.py script i...
314
315


77f1c546   Etienne Pallier   Ajouté options "t...
316
317
318
319
320
321
322
@pyros_launcher.command(help="Run some tests")
def test():
    print("Running tests")
    #start_dir = os.getcwd()
    apps = ['common', 'scheduler', 'routine_manager', 'user_manager', 'alert_manager.tests.TestStrategyChange']
    for app in apps:
        _loaddata() or die()
ad6d274a   Etienne Pallier   Restructuration d...
323
        change_dir(PYROS_DJANGO_BASE_DIR)
80d4ac71   Etienne Pallier   updated version a...
324
325
326
327
        # Delete test_pyros database after tests
        #execProcessFromVenv('manage.py test ' + app) or die()
        # KEEP test_pyros database after tests
        execProcessFromVenv('manage.py test --keep ' + app) or die()
ad6d274a   Etienne Pallier   Restructuration d...
328
        change_dir("PREVIOUS")
77f1c546   Etienne Pallier   Ajouté options "t...
329
330
331
332
333
    # execProcess("python install.py install")
    return True

@pyros_launcher.command(help="Run ALL tests")
def testall():
ad6d274a   Etienne Pallier   Restructuration d...
334
    change_dir(PYROS_DJANGO_BASE_DIR)
80d4ac71   Etienne Pallier   updated version a...
335
336
337
338
    # Delete test_pyros database after tests
    # execProcessFromVenvAsync("manage.py test")
    # KEEP test_pyros database after tests
    execProcessFromVenvAsync("manage.py test --keep")
ad6d274a   Etienne Pallier   Restructuration d...
339
    change_dir("PREVIOUS")
77f1c546   Etienne Pallier   Ajouté options "t...
340
341
342
343
    return True



f4fd20f9   Etienne Pallier   pyros.py script i...
344
    
01348735   Etienne Pallier   Bugfix pyros.py s...
345
346
347
'''
TODO:
'''
30b22ee6   Etienne Pallier   Agent : agentX wo...
348
@pyros_launcher.command(help="Update (only if necessary) the python packages AND the source code AND the DB structure")
01348735   Etienne Pallier   Bugfix pyros.py s...
349
350
def update():
    print("Running update command")
f3d076fb   Etienne Pallier   Génération automa...
351

f936f035   Etienne Pallier   bugfix update com...
352
    # 1) Update source code (git pull)
f3d076fb   Etienne Pallier   Génération automa...
353
    printFullTerm(Colors.BLUE, "1) UPDATING SOURCE CODE: Running git pull")
30b22ee6   Etienne Pallier   Agent : agentX wo...
354
    _gitpull() or die()
f3d076fb   Etienne Pallier   Génération automa...
355
    
f936f035   Etienne Pallier   bugfix update com...
356
    # 2) Update python packages (pip install requirements)
f3d076fb   Etienne Pallier   Génération automa...
357
    printFullTerm(Colors.BLUE, "2) UPDATING PYTHON PACKAGES")
f936f035   Etienne Pallier   bugfix update com...
358
    _update_python_packages_from_requirements() or die()
f3d076fb   Etienne Pallier   Génération automa...
359
360
361
362
363
364
365
    
    # 3) Update PlantUML diagrams
    printFullTerm(Colors.BLUE, "3) UPDATING PLANTUML DIAGRAMS")
    _update_plantuml_diags() or die()
    
    # 4) Update database structure (make migrations + migrate)
    printFullTerm(Colors.BLUE, "4) UPDATING DATABASE")
f4fd20f9   Etienne Pallier   pyros.py script i...
366
    _updatedb() or die()
01348735   Etienne Pallier   Bugfix pyros.py s...
367
368
    return True

01348735   Etienne Pallier   Bugfix pyros.py s...
369

f4fd20f9   Etienne Pallier   pyros.py script i...
370
371
372
373
374
def _gitpull():
    print("-- running git pull")
    GIT = "git.exe" if IS_WINDOWS else "git"
    if not test_mode(): return execProcess(f"{GIT} pull")
    return True
01348735   Etienne Pallier   Bugfix pyros.py s...
375

f4fd20f9   Etienne Pallier   pyros.py script i...
376
377
378
379
380
381
382
#@pyros_launcher.command(help="Update the pyros database")
def _updatedb():
    print("-- update db (make migrations + migrate)")
    if not test_mode() :
        _makemigrations() or die()
        _migrate() or die()
    return True
ddb06a2a   Etienne Pallier   new pyros2 launch...
383
384


f4fd20f9   Etienne Pallier   pyros.py script i...
385
386
387
388
389
390
391
@pyros_launcher.command(help="Update the pyros database and fill it with initial fixture data")
def initdb():
    if not test_mode():
        #updatedb()
        _makemigrations()
        _migrate()
        _loaddata()
ddb06a2a   Etienne Pallier   new pyros2 launch...
392
393
394
    return True


f4fd20f9   Etienne Pallier   pyros.py script i...
395

ddb06a2a   Etienne Pallier   new pyros2 launch...
396
397
398
399
400
401
402
403
@pyros_launcher.command(help="Launch an agent")
#@global_test_options
@click.argument('agent')
@click.option('--configfile', '-c', help='the configuration file to be used')
#@click.option('--format', '-f', type=click.Choice(['html', 'xml', 'text']), default='html', show_default=True)
#@click.option('--port', default=8000)
#def start(agent:str, configfile:str, test, verbosity):
def start(agent:str, configfile:str):
1f6376dd   Etienne Pallier   pyros2 refactor &...
404
    print("Running start command")
112f32f4   Etienne Pallier   start_agent_agent...
405
406
407
    if configfile: 
        print("With config file", configfile)
    else: 
ad6d274a   Etienne Pallier   Restructuration d...
408
        configfile = ''
ddb06a2a   Etienne Pallier   new pyros2 launch...
409
410
    #if test_mode(): print("in test mode")
    #if verbose_mode(): print("in verbose mode")
7d679ea0   Etienne Pallier   Commande EVAL ok
411
412
413
414
415
416
417
418
419
    
    # Check if multiple agents:
    agents = None
    if "," in agent:
        agents = agent.split(",")
        for a in agents: 
            if not _check_agent(a): return
        print("Agents are:", agents)
    # 1 agent only
31e31f3b   Etienne Pallier   pyros.py peut lan...
420
421
422
423
424
425
    else:
        agents = [agent]
        if not _check_agent(agent): return

    # Start Agents (processes)
    current_processes = []
eac3e2ab   Etienne Pallier   New AgentX
426
    for agent_name,agent_folder in AGENTS.items():
112f32f4   Etienne Pallier   start_agent_agent...
427

31e31f3b   Etienne Pallier   pyros.py peut lan...
428
429
        #if agent in ("all", agent_name) :
        if agent=="all" or agent_name in agents:
112f32f4   Etienne Pallier   start_agent_agent...
430
            # Default case, launch agentX
630dd6e4   Etienne Pallier   Renommé script st...
431
432
433
434
435
436
437
            #if agent_name == "agentX":

            # execProcessFromVenvAsync(VENV_BIN + " manage.py runserver")
            print(VENV_BIN)
            print("Launching agent", agent_name, "...")
            #if not test_mode(): execProcess(VENV_BIN + " manage.py runserver")
            #if not test_mode(): execProcessFromVenv("start_agent_" + agent_name + ".py " + configfile)
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
438
            
31e31f3b   Etienne Pallier   pyros.py peut lan...
439
440
            current_dir = os.getcwd()

a7887020   Etienne Pallier   GROSSE OPTIM : pl...
441
            # OLD format agents: majordome, monitoring, alert...
630dd6e4   Etienne Pallier   Renommé script st...
442
            cmd = "start_agent.py " + agent_name + " " + configfile
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
443
444
            
            # Agent "webserver"
630dd6e4   Etienne Pallier   Renommé script st...
445
446
            if agent_name == "webserver": 
                cmd = "manage.py runserver"
ad6d274a   Etienne Pallier   Restructuration d...
447
                os.chdir(PYROS_DJANGO_BASE_DIR)
630dd6e4   Etienne Pallier   Renommé script st...
448
            #if not test_mode(): execProcessFromVenv("start_agent.py " + agent_name + " " + configfile)
471cc5b9   Etienne Pallier   Déplacé AgentM da...
449
450

            elif agent_name == "agentM": 
ad6d274a   Etienne Pallier   Restructuration d...
451
                os.chdir(PYROS_DJANGO_BASE_DIR+"/monitoring/")
471cc5b9   Etienne Pallier   Déplacé AgentM da...
452
453
454
                cmd = f"Agent{agent_name[5:]}.py"
                if test_mode(): cmd += " -t"
                if configfile: cmd += " {configfile}"
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
455
456
            
            # Agent "agentA", "agentB", "agentX", ...            
471cc5b9   Etienne Pallier   Déplacé AgentM da...
457
            elif agent_name.startswith("agent"):
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
458
459
                # Run agent without actual commands sent to devices (FOR_REAL=False)
                ##agentX.run(FOR_REAL=True)
ad6d274a   Etienne Pallier   Restructuration d...
460
                os.chdir(PYROS_DJANGO_BASE_DIR+"/agent/")
a7887020   Etienne Pallier   GROSSE OPTIM : pl...
461
                #cmd = "-m AgentX"
c7318a4a   Etienne Pallier   Nouveau mode test...
462
463
464
465
466
467
468
469
                #cmd = f" Agent{agent_name[5:]}.py {configfile}"
                cmd = f"Agent{agent_name[5:]}.py"
                if test_mode(): cmd += " -t"
                if configfile: cmd += " {configfile}"
            #if not test_mode(): current_processes.append( [execProcessFromVenvAsync(cmd), agent_name, -1] )
            # Append this process ( [process id, agent_name, result=failure] )
            # ("result" will be updated at the end of execution)
            current_processes.append( [execProcessFromVenvAsync(cmd), agent_name, -1] )
f3d076fb   Etienne Pallier   Génération automa...
470
            # self.change_dir("..")
31e31f3b   Etienne Pallier   pyros.py peut lan...
471
            os.chdir(current_dir)
ddb06a2a   Etienne Pallier   new pyros2 launch...
472

b2e9866d   Etienne Pallier   bugfix start_agen...
473
    # Go back to root folder (/)
f3d076fb   Etienne Pallier   Génération automa...
474
    # self.change_dir('..')
31e31f3b   Etienne Pallier   pyros.py peut lan...
475
476
    #os.chdir("..")
    # Wait for end of each process execution
db13d8ac   Etienne Pallier   updates: go_idle ...
477
478
479
    #for (p,agent) in current_processes:
    for process in current_processes:
        p,agent,_ = process
31e31f3b   Etienne Pallier   pyros.py peut lan...
480
481
        print(f"************ Waiting for end of execution of agent {agent} ************")
        p.wait()
db13d8ac   Etienne Pallier   updates: go_idle ...
482
        process[2] = p.returncode
31e31f3b   Etienne Pallier   pyros.py peut lan...
483
484
485
486
487
488
489
490
        print(f"************ END of execution of agent {agent} ************")
        if p.returncode == 0:
            printFullTerm(Colors.GREEN, f"Process {agent} executed successfully")
            # self.addExecuted(self.current_command, command)
        else:
            printFullTerm(Colors.WARNING, f"Process {agent} execution failed")
            # self.addError(self.current_command, command)
    
db13d8ac   Etienne Pallier   updates: go_idle ...
491
492
493
494
495
    print()
    print()
    print("Synthesis of the results:")
    for process in current_processes:
        p,agent,returncode = process
db13d8ac   Etienne Pallier   updates: go_idle ...
496
497
498
499
500
501
502
        if returncode == 0:
            printFullTerm(Colors.GREEN, f"Process {agent} executed successfully")
            # self.addExecuted(self.current_command, command)
        else:
            printFullTerm(Colors.WARNING, f"Process {agent} execution failed")
            # self.addError(self.current_command, command)
        
31e31f3b   Etienne Pallier   pyros.py peut lan...
503
504
    #print("************ end of START() ************")
    # Only according to the last process status:
db13d8ac   Etienne Pallier   updates: go_idle ...
505
    #return True if p.returncode==0 else False
31e31f3b   Etienne Pallier   pyros.py peut lan...
506
    return True if p.returncode==0 else False
b2e9866d   Etienne Pallier   bugfix start_agen...
507
508


ddb06a2a   Etienne Pallier   new pyros2 launch...
509
510
511
@pyros_launcher.command(help="Kill an agent")
@click.argument('agent')
def stop(agent):
1f6376dd   Etienne Pallier   pyros2 refactor &...
512
    print("Running stop command")
f4fd20f9   Etienne Pallier   pyros.py script i...
513
    if not _check_agent(agent): return
ddb06a2a   Etienne Pallier   new pyros2 launch...
514
515
516



f4fd20f9   Etienne Pallier   pyros.py script i...
517
518
519
520
521
522
"""
********************************************************************************
******************** PRIVATE FUNCTIONS DEFINITION ******************************
********************************************************************************
"""

082ccda3   Etienne Pallier   pyros.py : enrich...
523
def _update_python_packages_from_requirements():
f34862ce   Etienne Pallier   bugfix requirements
524
    res = execProcessFromVenv("-m pip install -r install/"+REQUIREMENTS)
082ccda3   Etienne Pallier   pyros.py : enrich...
525
526
    return res

f3d076fb   Etienne Pallier   Génération automa...
527
def _update_plantuml_diags():
085a32e3   Etienne Pallier   bugfix
528
    res = False
ad6d274a   Etienne Pallier   Restructuration d...
529
    for dirpath, dirnames, files in os.walk(PYROS_DJANGO_BASE_DIR):
caabbdea   Etienne Pallier   plantUML diagrams...
530
531
532
        if os.path.basename(dirpath) == "doc":
            diagrams = glob.glob(dirpath+os.sep+"*.pu")
            for diag in diagrams: res = execProcessFromVenv("-m plantuml "+diag)
f3d076fb   Etienne Pallier   Génération automa...
533
534
    return res

f4fd20f9   Etienne Pallier   pyros.py script i...
535
def _migrate():
ad6d274a   Etienne Pallier   Restructuration d...
536
    change_dir(PYROS_DJANGO_BASE_DIR)
7d679ea0   Etienne Pallier   Commande EVAL ok
537
538
539
    # Migrate only migrations for the app "common"
    #res = execProcessFromVenv("manage.py migrate common")
    # Migrate all migrations for ALL apps
f4fd20f9   Etienne Pallier   pyros.py script i...
540
    res = execProcessFromVenv("manage.py migrate")
ad6d274a   Etienne Pallier   Restructuration d...
541
    change_dir("PREVIOUS")
f4fd20f9   Etienne Pallier   pyros.py script i...
542
543
544
    return res

def _makemigrations():
ad6d274a   Etienne Pallier   Restructuration d...
545
    change_dir(PYROS_DJANGO_BASE_DIR)
f4fd20f9   Etienne Pallier   pyros.py script i...
546
    #execProcessFromVenv(self.venv_bin + " manage.py makemigrations")
7d679ea0   Etienne Pallier   Commande EVAL ok
547
    #res = execProcessFromVenv("manage.py makemigrations common")
f4fd20f9   Etienne Pallier   pyros.py script i...
548
    res = execProcessFromVenv("manage.py makemigrations")
ad6d274a   Etienne Pallier   Restructuration d...
549
    change_dir("PREVIOUS")
f4fd20f9   Etienne Pallier   pyros.py script i...
550
551
552
553
    return res

#TODO: mettre la fixture en date naive (sans time zone)
def _loaddata():
ad6d274a   Etienne Pallier   Restructuration d...
554
    change_dir(PYROS_DJANGO_BASE_DIR)
a3015e31   Etienne Pallier   table des commandes
555
556
    #execProcessFromVenv(self.venv_bin + " manage.py loaddata misc" + os.sep + "fixtures" + os.sep + self.INIT_FIXTURE)
    res = execProcessFromVenv("manage.py loaddata misc" + os.sep + "fixtures" + os.sep + INIT_FIXTURE)
ad6d274a   Etienne Pallier   Restructuration d...
557
    change_dir("PREVIOUS")
f4fd20f9   Etienne Pallier   pyros.py script i...
558
559
    return res

77f1c546   Etienne Pallier   Ajouté options "t...
560

f3d076fb   Etienne Pallier   Génération automa...
561
def change_dir(path):
ad6d274a   Etienne Pallier   Restructuration d...
562
563
564
    global _previous_dir
    if path == "PREVIOUS": path=_previous_dir
    _previous_dir = os.getcwd()
f4fd20f9   Etienne Pallier   pyros.py script i...
565
566
567
568
569
570
571
572
    if DEBUG: print("Moving to : " + path)
    os.chdir(path)
    if DEBUG: print("Current directory : " + str(os.getcwd()))



def _check_agent(agent):
    # Check that agent exists
7d679ea0   Etienne Pallier   Commande EVAL ok
573
574
    if agent != "all" and agent not in AGENTS.keys() :
        # Check if multiple agents:
f4fd20f9   Etienne Pallier   pyros.py script i...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
        print("This agent does not exist")
        print("Here is the allowed list of agents:")
        print("- all => will launch ALL agents")
        for agent_name in AGENTS.keys(): print('-',agent_name)
        return False
    return True



"""
********************************************************************************
********************************* main() FUNCTION ******************************
********************************************************************************
"""
ddb06a2a   Etienne Pallier   new pyros2 launch...
589
590
591
592
def main():
    pyros_launcher()
    
    
1f6376dd   Etienne Pallier   pyros2 refactor &...
593
# AVIRER
ddb06a2a   Etienne Pallier   new pyros2 launch...
594
595
596
597
598
599
600
601
602
603
#@click.command()
#@click.argument('start')
def oldmain():
    '''
    cli()
    return
    '''
    
    #fire.Fire(Commands)
    #return
efbcac9e   Etienne Pallier   1st version of NE...
604

b2e9866d   Etienne Pallier   bugfix start_agen...
605
606
607
608
609
610
611
612
613
614
615
    # if len(sys.argv) == 3 and sys.argv[1].startswith("simulator"): SIMULATOR_CONFIG_FILE = sys.argv[2]
    # print(sys.argv)
    """
    system = platform.system()
    columns = 100
    row = 1000
    disp = True
    """

    # Read command
    if len(sys.argv) <= 1:
a3015e31   Etienne Pallier   table des commandes
616
        die("You must give a command name")
b2e9866d   Etienne Pallier   bugfix start_agen...
617
618
    command = sys.argv[1]
    if not command in COMMANDS.keys():
a3015e31   Etienne Pallier   table des commandes
619
        die("This command does not exist")
b2e9866d   Etienne Pallier   bugfix start_agen...
620
621
622
623
624
625
    command_all_args = COMMANDS[command]

    # Read command args if should be
    command_arg = None
    if command_all_args:
        if len(sys.argv) <= 2:
a3015e31   Etienne Pallier   table des commandes
626
            die("This command should be given an argument")
b2e9866d   Etienne Pallier   bugfix start_agen...
627
628
        command_arg = sys.argv[2]
        if not command_arg in command_all_args:
a3015e31   Etienne Pallier   table des commandes
629
            die("This argument does not exist for command " + command)
b2e9866d   Etienne Pallier   bugfix start_agen...
630
631
632
633
634
635
636
637
638
639
640

    print("Executing command", command)
    if command_arg:
        print("with arg", command_arg)

    # command(command_arg)
    if command_arg:
        globals()[command](command_arg)
    else:
        globals()[command]()
    # sys.exit(pyros.exec())
ddb06a2a   Etienne Pallier   new pyros2 launch...
641
642
643
644



if __name__ == "__main__": main()