#!/usr/bin/env python import sys import os import subprocess import platform import fileinput import argparse import time import signal # For USE_CELERY global variable #from src.pyros import settings USE_CELERY = False #USE_CELERY = True DEBUG = True SIMULATOR_CONFIG_FILE = "conf.json" #default config file ''' Pyros Manager, able to launch processes and handle all project commands ''' class Utils: system = platform.system() columns = 100 row = 1000 disp = True def __init__(self): if (platform.system() != 'Windows'): try: rows, columns = os.popen('stty size', 'r').read().split() self.columns = int(columns) except: self.columns = 100 if DEBUG: print("Could not get terminal size") def printFullTerm(self, color, string): value = int(self.columns / 2 - len(string) / 2) self.printColor(color, "-" * value, eol='') self.printColor(color, string, eol='') value += len(string) self.printColor(color, "-" * (self.columns - value)) return 0 def changeDirectory(self, path): if DEBUG: print("Moving to : " + path) os.chdir(path) if DEBUG: print("Current directory : " + str(os.getcwd())) return 0 def replacePatternInFile(self, pattern, replace, file_path): #try: with fileinput.FileInput(file_path, inplace=True, backup='.bak') as file: for line in file: print(line.replace(pattern, replace), end='') ''' except: return 1 return 0 ''' # Now, check that replacement has been done or else ERROR !!! #pattern = "CELERY_TEST = "+str(set_it) FOUND=False #with fileinput.FileInput(file_path) as file: with open(file_path) as file: for line in file: #if replace in line: if line.startswith(replace): FOUND = True break #if FOUND: print("pattern "+pattern+" found in file "+file_path) if not FOUND: raise(Exception("pattern "+replace+" not found in file "+file_path)) def printColor(self, color, message, file=sys.stdout, eol=os.linesep, forced=False): if (self.disp == False and forced == False): return 0 if (self.system == 'Windows'): print(message, file=file, end=eol) else: print(color + message + Colors.ENDC, file=file, end=eol) return 0 def askQuestion(self, message, default = ""): self.printColor(Colors.BLUE, message, forced=True) self.printColor(Colors.BOLD, "Answer (default="+default+"): ", eol='', forced=True) sys.stdout.flush() ret = sys.stdin.readline().replace('\n', '').replace('\r', '') if ret == "": return default return ret def sleep(self, t): time.sleep(t) return 0 ''' Manager class : manager of your project ''' class AManager(Utils): path = os.path.realpath(__file__) path_dir = os.getcwd() path_dir_file = os.path.dirname(os.path.realpath(__file__)) python_path = sys.executable python_version = sys.version_info bin_dir = "" celery = "celery" venv_pip = "pip" venv_bin = "python" wait = True current_command = "" config = None commandMatcher = {} commandDescription = {} commands = [] errors = {} executed = {} subproc = [] def __init__(self, param): super(AManager, self).__init__() self.wait = param.getWait() self.commands = param.getCommandList() self.disp = param.getPrint() config = param.getConfig() self.config = config signal.signal(signal.SIGINT, self.signal_handler) self.changeDirectory(self.path_dir_file) if self.system == 'Windows': self.bin_dir = "Scripts" self.bin_name = "python.exe" self.pip_name = "pip.exe" self.celery = "celery.exe" else: self.bin_dir = "bin" self.bin_name = "python" self.pip_name = "pip" self.celery = "celery" self.venv_pip = self.path_dir_file + os.sep + config["path"] + os.sep + config["env"] + os.sep + self.bin_dir + os.sep + self.pip_name self.venv_bin = self.path_dir_file + os.sep + config["path"] + os.sep + config["env"] + os.sep + self.bin_dir + os.sep + self.bin_name self.venv_cel = self.path_dir_file + os.sep + config["path"] + os.sep + config["env"] + os.sep + self.bin_dir + os.sep + self.celery def help(self): print("This function must be implemented") raise(NotImplementedError("Function not implemented")) def set_celery_test_and_simulator_modes_to(self, set_it:bool, simulator:bool=True): file_path = "pyros/settings.py" ''' self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", file_path) if simulator: self.replacePatternInFile("SIMULATOR = False", "SIMULATOR = True", file_path) ''' self.replacePatternInFile("CELERY_TEST = "+str(not set_it), "CELERY_TEST = "+str(set_it), file_path) if simulator: self.replacePatternInFile("SIMULATOR = "+str(not set_it), "SIMULATOR = "+str(set_it), file_path) def signal_handler(self, signal, frame): self.printFullTerm(Colors.WARNING, "Ctrl-c catched") self.set_celery_test_and_simulator_modes_to(False) for p in self.subproc: proc, name = p self.printColor(Colors.BLUE, "Killing process " + str(name)) proc.kill() self.printFullTerm(Colors.WARNING, "Exiting") sys.exit(0) def addExecuted(self, src, message): if (src in self.executed): self.executed[src].append(str(message)) else: self.executed[src] = [str(message)] return 0 def addError(self, src, message): if (src in self.errors): self.errors[src].append(str(message)) else: self.errors[src] = [str(message)] return 0 def execProcess(self, command): self.printFullTerm(Colors.BLUE, "Executing command [" + command + "]") process = subprocess.Popen(command, shell=True) process.wait() if process.returncode == 0: self.printFullTerm(Colors.GREEN, "Process executed successfully") self.addExecuted(self.current_command, command) else: self.printFullTerm(Colors.WARNING, "Process execution failed") self.addError(self.current_command, command) return process.returncode def execProcessSilent(self, command): process = subprocess.Popen(command, shell=True) process.wait() return process.returncode def execProcessFromVenv(self, command): args = command.split() self.printFullTerm(Colors.BLUE, "Executing command from venv [" + str(' '.join(args[1:])) + "]") process = subprocess.Popen(args) process.wait() if process.returncode == 0: self.printFullTerm(Colors.GREEN, "Process executed successfully") self.addExecuted(self.current_command, str(' '.join(args[1:]))) else: self.printFullTerm(Colors.WARNING, "Process execution failed") self.addError(self.current_command, str(' '.join(args[1:]))) return process.returncode def execProcessAsync(self, command): self.printFullTerm(Colors.BLUE, "Executing command [" + command + "]") p = subprocess.Popen(command, shell=True) self.subproc.append((p, command)) self.printFullTerm(Colors.GREEN, "Process launched successfully") self.addExecuted(self.current_command, command) return p def execProcessFromVenvAsync(self, command: str): args = command.split() self.printFullTerm(Colors.BLUE, "Executing command from venv [" + str(' '.join(args[1:])) + "]") p = subprocess.Popen(args) self.subproc.append((p, ' '.join(args[1:]))) self.printFullTerm(Colors.GREEN, "Process launched successfully") self.addExecuted(self.current_command, str(' '.join(args[1:]))) return p def waitProcesses(self): if (self.wait): for p in self.subproc: proc, name = p proc.wait() return 0 def end(self): count = 0 self.waitProcesses() self.printFullTerm(Colors.WARNING, "Summary") self.printColor(Colors.GREEN, "Success : ") for command, valid in self.executed.items(): if not valid: self.printColor(Colors.BLUE, "\t- Command : " + command + " success !") else: self.printColor(Colors.WARNING, "\t- In commmand : " + command) for exe in valid: self.printColor(Colors.GREEN, "\t\t - Command : " + exe + " success !") self.printColor(Colors.FAIL, "Errors : ") if not self.errors: self.printColor(Colors.GREEN, "\tNone") for command, items in self.errors.items(): count += 1 if (not items): self.printColor(Colors.FAIL, "Command : " + command + " failed !") else: self.printColor(Colors.WARNING, "\t- In commmand : " + command) for exe in items: self.printColor(Colors.FAIL, "\t\t - Command : " + exe) return count def exec(self): if (not self.commands): self.commandMatcher["help"]() return 0 for command in self.commands: self.current_command = command if command in self.commandMatcher: self.commandMatcher[command]() else: self.addError(str(command), "invalid command") return self.end() def logError(self, message): self.printColor(Colors.FAIL, "Pyros : An error occurred [" + message + "]", file=sys.stderr) return 0 ''' Config file representation (able to parse and give informations) ''' class Config: __parser = argparse.ArgumentParser("Project Pyros") __content = { "path": "private", "env": "venv_py3_pyros" } __wait = True __print = True usage = "" __command_list = [] def __init__(self): self.__parser.add_argument("command", nargs='*', default="help", help="The command you want to execute (default=help)") self.__parser.add_argument("--env", help="Your environment directory name default=venv") self.__parser.add_argument("--path", help="Path to the virtual env (from the source file directory) (default=private)") self.__parser.add_argument("--nowait", action='store_true', help="Don't wait the end of a program") self.__parser.add_argument("--noprint", action='store_true', help="Won't print") self.usage = self.__parser.format_usage() def parse(self): try: res = self.__parser.parse_args(), self.__parser.format_usage() return (res) except SystemExit as e: # print(e, file=sys.stderr) sys.exit(1) def parseConf(self): res, usage = self.parse() try: if (res.env): self.__content["env"] = res.env if (res.path): self.__content["path"] = res.path if (res.nowait): self.__wait = False if (res.noprint): self.__print = False self.__command_list.append(res.command[0]) #return return True except Exception as e: print(e, file=sys.stderr) #return 1 return False def getPath(self): return self.__content["path"] def getEnv(self): return self.__content["env"] def getWait(self): return self.__wait def getPrint(self): return self.__print def setPrint(self, value): self.__print = value return 0 def setWait(self, value): self.__wait = value return 0 def getCommandList(self): return self.__command_list def printUsage(self): print(self.usage, file=sys.stderr) def addConf(self, key, value): if isinstance(key, str) and isinstance(value, str): self.__content[key] = value return 0 return 1 def setPath(self, path): if (os.path.isdir(path)): if (path == ""): path = "." self.__content["path"] = path return 0 return 1 def setEnvName(self, name): self.__content["env"] = name return 0 def getConfig(self): return self.__content ''' Color class ''' 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' ''' Pyros class ''' class Pyros(AManager): help_message = "python neo.py" init_fixture = "initial_fixture.json" def signal_handler(self, signal, frame): self.printFullTerm(Colors.WARNING, "Ctrl-c catched") for p in self.subproc: proc, name = p self.printColor(Colors.BLUE, "Killing process " + str(name)) proc.kill() if self.current_command == "simulator" or self.current_command == "simulator_development": self.changeDirectory(self.path_dir_file) self.kill_simulation() self.printFullTerm(Colors.WARNING, "Exiting") sys.exit(0) def install(self): if (self.system == "Windows"): self.execProcess("python install/install.py install") else: self.execProcess("python3 install/install.py install") return 0 def update(self): if (self.system == "Windows"): self.execProcess("python install/install.py update") else: self.execProcess("python3 install/install.py update") return 0 def server(self): self.changeDirectory("src") self.execProcessFromVenvAsync(self.venv_bin + " manage.py runserver") self.changeDirectory("..") return 0 def clean(self): return self.clean_logs() def clean_logs(self): return self.execProcess("rm logs/*.log") def test(self): ##self.singleWorker("scheduling") self.changeDirectory("src") ##self.execProcessFromVenv(self.venv_bin + " manage.py test") self.execProcessFromVenvAsync(self.venv_bin + " manage.py test") self.changeDirectory("..") ##self.stop_workers() return 0 def migrate(self): self.changeDirectory("src") self.execProcessFromVenv(self.venv_bin + " manage.py migrate") self.changeDirectory("..") return 0 def makemigrations(self): self.changeDirectory("src") self.execProcessFromVenv(self.venv_bin + " manage.py makemigrations") self.changeDirectory("..") return 0 def help(self): count = 0 self.printFullTerm(Colors.WARNING, "Help Message") for command, message in self.commandDescription.items(): count += 1 if (self.columns > 100): self.printColor(Colors.BLUE, "\t"+str(count)+(' ' if count < 10 else '')+": " + command + ": ", eol='') else: self.printColor(Colors.BLUE, "-> " + command + ": ", eol='') self.printColor(Colors.GREEN, message) return 0 def updatedb(self): self.makemigrations() self.migrate() return 0 def reset_config(self): self.changeDirectory("src") self.set_celery_test_and_simulator_modes_to(False) self.addExecuted(self.current_command, "reset configuration") self.changeDirectory("..") return 0 def unittest(self): #self.changeDirectory("src") apps = ['common', 'scheduler', 'routine_manager', 'user_manager', 'alert_manager.tests.TestStrategyChange'] for app in apps: self.loaddata() self.changeDirectory("src") self.execProcessFromVenv(self.venv_bin + ' manage.py test ' + app) self.changeDirectory("..") return 0 def test_all(self): self.unittest() return 0 #TODO: mettre la fixture en date naive (sans time zone) def loaddata(self): self.changeDirectory("src") self.execProcessFromVenv(self.venv_bin + " manage.py loaddata misc" + os.sep + "fixtures" + os.sep + self.init_fixture) self.changeDirectory("..") return 0 def celery_on(self, TOTAL=True): self.changeDirectory("src") if TOTAL: self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q alert_listener_q -n pyros@alert_listener -c 1") if TOTAL: self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q monitoring_q -n pyros@monitoring -c 1") #self.singleWorker("majordome") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q majordome_q -n pyros@majordome -c 1") #self.singleWorker("scheduling") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q scheduling_q --purge -n pyros@scheduling -c 1") #self.singleWorker("execute_plan_vis") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q execute_plan_vis_q --purge -n pyros@execute_plan_vis -c 1") if TOTAL: self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q night_calibrations_q --purge -n pyros@night_calibrations -c 1") #self.singleWorker("execute_plan_nir") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q execute_plan_nir_q --purge -n pyros@execute_plan_nir -c 1") #self.singleWorker("create_calibrations") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q create_calibrations_q --purge -n pyros@create_calibrations -c 1") #self.singleWorker("analysis") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q analysis_q --purge -n pyros@analysis -c 1") self.changeDirectory("..") return 0 # ex start() def start_workers(self): self.stop_workers() self.celery_on() return 0 # ex stop() def stop_workers(self): if (self.system == "Windows"): self.execProcessAsync("taskkill /f /im celery.exe") self.execProcessAsync("taskkill /f /im python.exe") else: self.execProcessAsync("ps aux | grep \"celery worker\" | awk '{print $2}' | xargs kill -9") return 0 def init_database(self): self.makemigrations() self.migrate() self.loaddata() return 0 # Start the PyROS software # Start only the (django) Web server (pyros website) def start_web(self): self.start("web") #self.start(3) # Start only the agents (all of them) def start_agents(self): self.start("agents") # Start only 1 agent def start_agent_monitoring(self): self.start("monitoring") def start_agent_majordome(self): self.start("majordome") def start_agent_alertmanager(self): self.start("alert_manager") # Start the PyROS software # By default (what=None), start everything : all the agents and also the web server (website, web viewing, for global monitoring) def start(self, what:str = None): agents = ("alert_manager", "majordome", "monitoring") ''' what="monitoring" what="majordome" what="alert_manager" what="all" ''' ''' OLD CODE self.stop_workers() #self.celery_on() # Start the 3 main agents (via their celery worker) : self.startAgent("monitoring") self.startAgent("majordome") self.startAgent("alert_listener") ''' # Go into src/ self.changeDirectory("src") #print("Current directory : " + str(os.getcwd())) # Start (Django) Web server (pyros website) if what=='web' or what is None: self.execProcessFromVenvAsync(self.venv_bin + " manage.py runserver") #self.changeDirectory("..") # DJANGO setup ''' (optional) import sys sys.path.append('/PROJECTS/GFT/SOFT/PYROS_SOFT/PYROS201802/src') ''' ''' os.environ.setdefault("DJANGO_SETTINGS_MODULE", "src.pyros.settings") #os.environ['SECRET_KEY'] = 'abc' #os.environ['ENVIRONMENT'] = 'production' import django django.setup() ''' # Start Agents ''' if agent=="majordome" or agent=="all": from majordome.tasks import Majordome Majordome().run() if agent=="alert_manager" or agent=="all": from alert_manager.tasks import AlertListener AlertListener().run() ''' for agent in agents: if what==agent or what=="agents" or what is None: #os.chdir('src') ''' from monitoring.tasks import Monitoring Monitoring().run() ''' #self.changeDirectory("src/monitoring") #self.changeDirectory("src") self.changeDirectory(agent) self.execProcessFromVenvAsync(self.venv_bin + ' start_agent_'+agent+'.py') # Go back to src/ self.changeDirectory('..') #os.chdir('..') # Go back to root folder (/) self.changeDirectory('..') def startAgent(self, agent_name:str): # Start Celery Worker self.singleWorker(agent_name) time.sleep(3) # Put the agent task run() into the Worker queue # Reset the database content def reset_database_sim(self): self.changeDirectory("src") self.set_celery_test_and_simulator_modes_to(True, False) ''' Supprime toutes les données de la base de données et réexécute tout gestionnaire de post-synchronisation. La table contenant les informations d’application des migrations n’est pas effacée ''' #TODO: remplacer par manage.py --noinput flush pour eviter le "echo yes"... self.execProcess( self.venv_bin + " manage.py flush --noinput") self.set_celery_test_and_simulator_modes_to(True, False) self.changeDirectory("..") # Simulation for the scheduler ONLY (and only some celery workers, not all of them) def simulator_development(self): self.simulator(False) ''' (EP) utile pour le debug avec phpmyadmin pour remettre à zéro la bd pyros_test delete from plan; delete from album; delete from schedule_has_sequences; delete from schedule; delete from sequence; delete from request; ''' # Simulation (by default, with ALL simulators and ALL celery workers) def simulator(self, TOTAL=True): self.changeDirectory("src") # Set CELERY_TEST mode ON self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", "pyros/settings.py") self.replacePatternInFile("SIMULATOR = False", "SIMULATOR = True", "pyros/settings.py") # 0) Reset the database (Empty the database from any data) #TODO: je crois qu'on n'utilise plus sqlite... donc ce code est inutile ? if self.system == "Windows" : self.execProcess("del /f testdb.sqlite3") else : self.execProcess("rm -f testdb.sqlite3") self.changeDirectory("..") if TOTAL: self.reset_database_sim() # EP added: if not TOTAL: self.reset_database_sim() # Actualise l’état de la DB en accord avec l’ensemble des modèles et des migrations actuels self.makemigrations() self.migrate() # Load fixture initial_fixture.json self.loaddata() # # 1) Launch Django web server # self.server() self.sleep(2) self.printFullTerm(Colors.WARNING, "SUMMARY") self.printColor(Colors.GREEN, "The simulator has been successfully initialised") #TODO: (EP) verifier mais je pense que cette info est obsolete, c'est MySQL qui est utilisé, pas sqlite #self.printColor(Colors.GREEN, "The simulator runs on a temp database : src/testdb.sqlite3") self.printColor(Colors.GREEN, "The simulation will be ended by the task 'simulator herself'") self.printColor(Colors.GREEN, "If you want to shutdown the simulation, please run :") self.printColor(Colors.GREEN, "CTRL-C or pyros.py kill_simulation") self.printColor(Colors.GREEN, "If the simulation isn't correctly killed, please switch the variable") self.printColor(Colors.GREEN, "CELERY_TEST in src/pyros/settings.py to False") self.printFullTerm(Colors.WARNING, "SUMMARY") # # 2) (if USE_CELERY) Start Celery workers # if USE_CELERY: self.celery_on(TOTAL) self.sleep(3) # # 3) Start simulator(s) : # self.sims_launch(TOTAL) ''' # (DEFAULT NORMAL) TOTAL RUN # - Launch ALL simulators if TOTAL: # Launch ALL simulators and WAIT until finished: #self.sims_launch(conf) self.sims_launch(TOTAL) # (DEV) PARTIAL RUN # - Launch only USER simulator else: # EP: bugfix: inutile si TOTAL, car refait dans sims_launch !!! self.changeDirectory("simulators/config") self.printColor(Colors.BOLD, "Existing simulations : ", eol='') sys.stdout.flush() if (self.system == "Windows") : self.execProcessSilent("dir /B conf*.json") else: self.execProcessSilent("ls conf*.json") self.changeDirectory("..") conf = self.askQuestion("Which simulation do you want to use", default="conf.json") self.changeDirectory("..") procs = [] self.changeDirectory("simulators") self.changeDirectory("user") # Launch only 1 simulator : UserSimulator procs.append(self.execProcessFromVenvAsync(self.venv_bin + " userSimulator.py " + conf)) self.changeDirectory("..") for p in procs: p.wait() self.changeDirectory("..") ''' ''' # # 2) (if not USE_CELERY) Start Agents # if TOTAL and not USE_CELERY : #pass # Start Environment Monitoring Agent # Start Majordome Agent # Start Alert Manager Agent self.start_agents() # Needed ? self.sleep(3) ''' # When simulators are finished: #self.kill_simulation() return 0 # Test of the Majordome agent def test_majordome(self): self.changeDirectory("src") # Set CELERY_TEST mode ON self.set_celery_test_and_simulator_modes_to(True) # 0) Reset the database (Empty the database from any data) self.changeDirectory("..") self.reset_database_sim() # Actualise l’état de la DB en accord avec l’ensemble des modèles et des migrations actuels self.migrate() # Load fixture initial_fixture.json self.loaddata() return # # 1) Launch Django web server # ''' self.server() self.sleep(2) ''' self.printFullTerm(Colors.WARNING, "SUMMARY") self.printColor(Colors.GREEN, "The simulation will be ended by the task 'simulator herself'") self.printColor(Colors.GREEN, "If you want to shutdown the simulation, please run :") self.printColor(Colors.GREEN, "CTRL-C or pyros.py kill_simulation") self.printColor(Colors.GREEN, "If the simulation isn't correctly killed, please switch the variable") self.printColor(Colors.GREEN, "CELERY_TEST in src/pyros/settings.py to False") self.printFullTerm(Colors.WARNING, "SUMMARY") # 2) (if USE_CELERY) Start Celery workers # ''' if USE_CELERY: self.celery_on(TOTAL) self.sleep(3) ''' # # 3) Start simulator(s) : # #self.sims_launch(True) agent='majordome' self.changeDirectory(agent) p = self.execProcessFromVenvAsync(self.venv_bin + ' start_agent_'+agent+'.py') os.chdir('..') time.sleep(5) # Wait for end of simulators : #p.wait() # When simulators are finished: #self.kill_simulation() #self.changeDirectory("src") self.set_celery_test_and_simulator_modes_to(False) self.changeDirectory("..") self.execProcessAsync("ps aux | grep \"start_agent_majordome.py\" | awk '{ print $2 }' | xargs kill") return 0 def kill_server(self): self.execProcessAsync("fuser -k 8000/tcp") return 0 def kill_simulation(self): self.changeDirectory("src") self.set_celery_test_and_simulator_modes_to(False) self.changeDirectory("..") if (self.system == "Windows"): self.execProcessAsync("taskkill /f /im python.exe") #self.execProcessAsync("del /f testdb.sqlite3") obsolete #self.changeDirectory("..") POURQUOI ? return 0 #else: self.execProcessAsync("rm -f testdb.sqlite3") # Kill web server (processes using TCP port 8000) : #self.execProcessAsync("fuser -k 8000/tcp") self.kill_server() # (if not using celery) Kill all agents : if not USE_CELERY: self.execProcessAsync("ps aux | grep \"start_agent_alert_manager.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \"start_agent_monitoring.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \"start_agent_majordome.py\" | awk '{ print $2 }' | xargs kill") #self.execProcessAsync("ps aux | grep \"start_agent_majordome.py\" | awk '{ print $2 }' | xargs kill") # Kill all simulators : self.execProcessAsync("ps aux | grep \" domeSimulator.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \" userSimulator.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \" alertSimulator.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \" plcSimulator.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \" telescopeSimulator.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \" cameraNIRSimulator.py\" | awk '{ print $2 }' | xargs kill") self.execProcessAsync("ps aux | grep \" cameraVISSimulator.py\" | awk '{ print $2 }' | xargs kill") self.changeDirectory("..") if USE_CELERY: self.stop_workers() self.printFullTerm(Colors.GREEN, "simulation ended") return 0 # EP 25/7/18 # Start one, some, or all agents and simulators def start_agents_and_simulators_for_majordome(self): self.start_agents_and_simulators("majordome") def start_agents_and_simulators(self, agent:str=None): simulators = ('user', 'plc', 'dome', 'alert', 'cameraVIS', 'cameraNIR', 'telescope') #simulators = ('plc', 'user') #simulators = () agents = ("alert_manager", "majordome", "monitoring") if agent=="majordome": simulators = ("plc",) agents = (agent, "monitoring") # Start simulators p_sims = [] self.changeDirectory("simulators/") for simulator in simulators: print() print("Start simulator", ' '+simulator+"Simulator.py ") self.changeDirectory(simulator) #p_sims.append( self.execProcessFromVenvAsync(self.venv_bin + ' '+simulator+"Simulator.py " + conf) ) p_sims.append( self.execProcessFromVenvAsync(self.venv_bin + ' '+simulator+"Simulator.py ") ) self.changeDirectory("../") # Start agents #self.start_agents() p_agents = [] self.changeDirectory("../src/") for agent in agents: print() print("Start agent", 'start_agent_'+agent+'.py') self.changeDirectory(agent) p_agents.append( self.execProcessFromVenvAsync(self.venv_bin + ' start_agent_'+agent+'.py') ) self.changeDirectory('..') # Simulators only def sims_launch(self, TOTAL=True): conf = SIMULATOR_CONFIG_FILE # Read simulators scenario file self.changeDirectory("simulators/config") # if (conf == ""): # self.printColor(Colors.BOLD, "Existing simulations : ", eol='') # sys.stdout.flush() # if (self.system == "Windows"): # self.execProcessSilent("dir /B conf*.json") # else: # self.execProcessSilent("ls conf*.json") # conf = self.askQuestion("Which simulation do you want to use ?", default="conf.json") if not os.path.isfile(conf): self.printColor(Colors.FAIL, "The simulation file " + conf + " does not exist") return 1 # Go back to simulators/ self.changeDirectory("..") procs = [] # Launch the User simulator: self.changeDirectory("user") procs.append(self.execProcessFromVenvAsync(self.venv_bin + " userSimulator.py " + conf)) self.changeDirectory("..") # (if TOTAL) Launch all other simulators if TOTAL: self.changeDirectory("dome") procs.append(self.execProcessFromVenvAsync(self.venv_bin + " domeSimulator.py " + conf)) self.changeDirectory("..") self.changeDirectory("alert") procs.append(self.execProcessFromVenvAsync(self.venv_bin + " alertSimulator.py " + conf)) self.changeDirectory("..") self.changeDirectory("plc") procs.append(self.execProcessFromVenvAsync(self.venv_bin + " plcSimulator.py " + conf)) self.changeDirectory("..") self.changeDirectory("camera") procs.append(self.execProcessFromVenvAsync(self.venv_bin + " cameraVISSimulator.py " + conf)) procs.append(self.execProcessFromVenvAsync(self.venv_bin + " cameraNIRSimulator.py " + conf)) self.changeDirectory("..") self.changeDirectory("telescope") procs.append(self.execProcessFromVenvAsync(self.venv_bin + " telescopeSimulator.py " + conf)) self.changeDirectory("..") # Get back to project root folder self.changeDirectory("..") # (if not celery) Launch agents (env monitor, major, alert mgr) if not USE_CELERY: self.start_agents() # Wait for end of simulators : for p in procs: p.wait() # Kill all processes self.kill_simulation() return 0 def singleWorker(self, worker): self.changeDirectory("src") self.execProcessFromVenvAsync(self.venv_cel + " worker -A pyros -Q "+ worker +"_q -n pyros@"+worker+" -c 1") self.changeDirectory("..") return 0 def mysql_on(self): self.changeDirectory("src") self.replacePatternInFile("MYSQL = False", "MYSQL = True", "pyros/settings.py") self.addExecuted(self.current_command, "Switch to mysql") self.changeDirectory("..") return 0 def mysql_off(self): self.changeDirectory("src") self.replacePatternInFile("MYSQL = True", "MYSQL = False", "pyros/settings.py") self.addExecuted(self.current_command, "Switch to sqlite") self.changeDirectory("..") return 0 def __init__(self, argv): super(Pyros, self).__init__(argv) self.commandMatcher = { "install": self.install, "update": self.update, "server": self.server, "clean": self.clean, "simulator_development": self.simulator_development, "clean_logs": self.clean_logs, "test": self.test, "migrate": self.migrate, "mysql_on": self.mysql_on, "mysql_off": self.mysql_off, "makemigrations": self.makemigrations, "updatedb": self.updatedb, "unittest": self.unittest, "reset_config": self.reset_config, "test_all": self.test_all, "celery_on": self.celery_on, "reset_database_sim": self.reset_database_sim, "init_database": self.init_database, "kill_server": self.kill_server, "loaddata": self.loaddata, "start": self.start, "start_web": self.start_web, "start_agents": self.start_agents, "start_agents_and_simulators": self.start_agents_and_simulators, "start_agents_and_simulators_for_majordome": self.start_agents_and_simulators_for_majordome, "start_agent_monitoring": self.start_agent_monitoring, "start_agent_majordome": self.start_agent_majordome, "start_agent_alertmanager": self.start_agent_alertmanager, "test_majordome": self.test_majordome, # ex start "start_workers": self.start_workers, # ex stop "stop_workers": self.stop_workers, "simulator": self.simulator, "kill_simulation": self.kill_simulation, "sims_launch": self.sims_launch, "help": self.help, } self.commandDescription = { "install": "Launch the server installation", "update": "Update the server", "server": "Launch the web server", "loaddata": "Load the initial fixture in database", "clean": "clean the repository", "clean_logs": "clean the log directory", "test": "launch the server tests", "migrate": "execute migrations", "mysql_on": "switch the database to be used to MYSQL", "mysql_off": "switch the database to be used usage to SQLITE", "makemigrations": "create new migrations", "reset_config": "Reset the configuration in settings.py", "reset_database_sim": "Reset the database content", "help": "Help message", "updatedb": "Update the database", "kill_server": "Kill the web server on port 8000", "init_database": "Create a standard context for pyros in db", "unittest": "Runs the tests that don't need celery", "test_all": "Run all the existing tests (this command needs to be updated when tests are added in the project", "celery_on": "Starts celery workers", "start_workers": "Starts the celery workers (then the web server ???)", "stop_workers": "Stops the celery workers", "simulator": "Launch a simulation", "simulator_development": "Simulation for the scheduler only", "kill_simulation": "kill the simulators / celery workers / web server", "sims_launch": "Launch only the simulators", } if __name__ == "__main__": if len(sys.argv) == 3 and sys.argv[1].startswith("simulator"): SIMULATOR_CONFIG_FILE = sys.argv[2] conf = Config() if not conf.parseConf(): sys.exit(1) pyros = Pyros(conf) sys.exit(pyros.exec())