Commit 03814884c0f73a0e4fcc8dfe097b04d1af4835c8

Authored by Etienne Pallier
1 parent f47ec727
Exists in dev

launch majordome agent from majordome unit tests

pyros.py
... ... @@ -11,8 +11,8 @@ import signal
11 11  
12 12 # For USE_CELERY global variable
13 13 #from src.pyros import settings
14   -USE_CELERY = False
15   -#USE_CELERY = True
  14 +#USE_CELERY = False
  15 +USE_CELERY = True
16 16  
17 17 DEBUG = True
18 18 SIMULATOR_CONFIG_FILE = "conf.json" #default config file
... ... @@ -679,6 +679,7 @@ class Pyros(AManager):
679 679 # EP added:
680 680 if not TOTAL: self.reset_database_sim()
681 681 # Actualise l’état de la DB en accord avec l’ensemble des modèles et des migrations actuels
  682 + self.makemigrations()
682 683 self.migrate()
683 684 # Load fixture initial_fixture.json
684 685 self.loaddata()
... ... @@ -763,6 +764,79 @@ class Pyros(AManager):
763 764 return 0
764 765  
765 766  
  767 +
  768 +
  769 + # Test of the Majordome agent
  770 + def test_majordome(self):
  771 + self.changeDirectory("src")
  772 +
  773 + # Set CELERY_TEST mode ON
  774 + self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", "pyros/settings.py")
  775 + self.replacePatternInFile("SIMULATOR = False", "SIMULATOR = True", "pyros/settings.py")
  776 +
  777 + # 0) Reset the database (Empty the database from any data)
  778 + self.changeDirectory("..")
  779 + self.reset_database_sim()
  780 + # Actualise l’état de la DB en accord avec l’ensemble des modèles et des migrations actuels
  781 + self.migrate()
  782 + # Load fixture initial_fixture.json
  783 + self.loaddata()
  784 + return
  785 +
  786 + #
  787 + # 1) Launch Django web server
  788 + #
  789 + '''
  790 + self.server()
  791 + self.sleep(2)
  792 + '''
  793 +
  794 + self.printFullTerm(Colors.WARNING, "SUMMARY")
  795 + self.printColor(Colors.GREEN, "The simulation will be ended by the task 'simulator herself'")
  796 + self.printColor(Colors.GREEN, "If you want to shutdown the simulation, please run :")
  797 + self.printColor(Colors.GREEN, "CTRL-C or pyros.py kill_simulation")
  798 + self.printColor(Colors.GREEN, "If the simulation isn't correctly killed, please switch the variable")
  799 + self.printColor(Colors.GREEN, "CELERY_TEST in src/pyros/settings.py to False")
  800 + self.printFullTerm(Colors.WARNING, "SUMMARY")
  801 +
  802 + # 2) (if USE_CELERY) Start Celery workers
  803 + #
  804 + '''
  805 + if USE_CELERY:
  806 + self.celery_on(TOTAL)
  807 + self.sleep(3)
  808 + '''
  809 +
  810 + #
  811 + # 3) Start simulator(s) :
  812 + #
  813 + #self.sims_launch(True)
  814 + agent='majordome'
  815 + self.changeDirectory(agent)
  816 + p = self.execProcessFromVenvAsync(self.venv_bin + ' start_agent_'+agent+'.py')
  817 + os.chdir('..')
  818 + time.sleep(5)
  819 +
  820 +
  821 + # Wait for end of simulators :
  822 + #p.wait()
  823 +
  824 + # When simulators are finished:
  825 + #self.kill_simulation()
  826 + #self.changeDirectory("src")
  827 + self.replacePatternInFile("CELERY_TEST = True", "CELERY_TEST = False", "pyros/settings.py")
  828 + self.replacePatternInFile("SIMULATOR = True", "SIMULATOR = False", "pyros/settings.py")
  829 + self.changeDirectory("..")
  830 + self.execProcessAsync("ps aux | grep \"start_agent_majordome.py\" | awk '{ print $2 }' | xargs kill")
  831 +
  832 + return 0
  833 +
  834 +
  835 +
  836 +
  837 +
  838 +
  839 +
766 840 def kill_server(self):
767 841 self.execProcessAsync("fuser -k 8000/tcp")
768 842 return 0
... ... @@ -799,7 +873,7 @@ class Pyros(AManager):
799 873 self.execProcessAsync("ps aux | grep \" cameraNIRSimulator.py\" | awk '{ print $2 }' | xargs kill")
800 874 self.execProcessAsync("ps aux | grep \" cameraVISSimulator.py\" | awk '{ print $2 }' | xargs kill")
801 875 self.changeDirectory("..")
802   - self.stop_workers()
  876 + if USE_CELERY: self.stop_workers()
803 877  
804 878 self.printFullTerm(Colors.GREEN, "simulation ended")
805 879 return 0
... ... @@ -920,6 +994,7 @@ class Pyros(AManager):
920 994 "start_agent_monitoring": self.start_agent_monitoring,
921 995 "start_agent_majordome": self.start_agent_majordome,
922 996 "start_agent_alertmanager": self.start_agent_alertmanager,
  997 + "test_majordome": self.test_majordome,
923 998  
924 999 # ex start
925 1000 "start_workers": self.start_workers,
... ...
src/majordome/start_agent_majordome.py
1   -#!/usr/bin/env python3
  1 +#!/usr/bin/env python
2 2  
3 3 import os
4 4 import sys
... ... @@ -6,6 +6,9 @@ import sys
6 6 # DJANGO setup
7 7 #sys.path.append('/PROJECTS/GFT/SOFT/PYROS_SOFT/PYROS201802')
8 8 sys.path.append('..')
  9 +#print("file is", __file__)
  10 +mypath = os.getcwd()
  11 +
9 12 # Go into src/
10 13 os.chdir('..')
11 14 #print("Current directory : " + str(os.getcwd()))
... ...
src/majordome/start_agent_majordome_from_test.py 0 → 100755
... ... @@ -0,0 +1,26 @@
  1 +#!/usr/bin/env python
  2 +
  3 +import os
  4 +import sys
  5 +
  6 +# DJANGO setup
  7 +#sys.path.append('/PROJECTS/GFT/SOFT/PYROS_SOFT/PYROS201802')
  8 +sys.path.append('..')
  9 +#print("file is", __file__)
  10 +mypath = os.getcwd()
  11 +
  12 +# Go into src/
  13 +##os.chdir('..')
  14 +#print("Current directory : " + str(os.getcwd()))
  15 +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "src.pyros.settings")
  16 +#os.environ['SECRET_KEY'] = 'abc'
  17 +#os.environ['ENVIRONMENT'] = 'production'
  18 +import django
  19 +django.setup()
  20 +
  21 +# MONITORING AGENT setup
  22 +agent="majordome"
  23 +
  24 +if agent=="majordome":
  25 + from majordome.tasks import Majordome
  26 + Majordome().run()
... ...
src/majordome/tasks.py
... ... @@ -24,6 +24,8 @@ from majordome.MajordomeDecorators import *
24 24 from utils.JDManipulator import *
25 25 import time
26 26  
  27 +from threading import Thread
  28 +
27 29 DEBUG_FILE = False
28 30 log = L.setupLogger("MajordomeTaskLogger", "Majordome")
29 31  
... ... @@ -35,7 +37,7 @@ log = L.setupLogger("MajordomeTaskLogger", "Majordome")
35 37 check if the last schedule made has to be planned
36 38 launch schedule's sequences
37 39 '''
38   -class Majordome(Task):
  40 +class Majordome(Task, Thread):
39 41  
40 42 loop_speed = 1
41 43 julian_div = 86400
... ... @@ -94,7 +96,14 @@ class Majordome(Task):
94 96 # SETUP
95 97 try :
96 98 self.config = get_object_or_404(Config, id=1)
97   - except Config.ObjectDoesNotExist:
  99 + #self.config = Config.objects.get(pk=1)
  100 + #self.config = Config.objects.get()[0]
  101 +
  102 + #print("maj config id is", self.config.id)
  103 +
  104 + #except Config.ObjectDoesNotExist:
  105 + except Exception as e:
  106 + print("Config read exception", str(e))
98 107 return -1
99 108  
100 109 #self.config.ntc = False
... ... @@ -134,7 +143,7 @@ class Majordome(Task):
134 143 if self.current_state not in ['STARTING', 'PASSIVE_NO_PLC']:
135 144 if self.plc_is_not_auto(): self.changeState("PASSIVE")
136 145 '''
137   - self.current_state = self.do_behavior_for_state(self.current_state)
  146 + self.current_state = self.do_behavior_for_current_state()
138 147  
139 148  
140 149 '''
... ... @@ -236,7 +245,7 @@ class Majordome(Task):
236 245 print("Waiting for PLC connection")
237 246 # Wait until PCL is connected
238 247 while not self.plc_is_connected():
239   - time.sleep(2)
  248 + time.sleep(3)
240 249 '''
241 250 if self.is_restarting():
242 251 self.changeState("STARTING")
... ... @@ -273,7 +282,7 @@ class Majordome(Task):
273 282 if self.NEED_TO_CLOSE:
274 283 self.changeState("Closing")
275 284 #self.sub_behavior_closing()
276   - self.do_behavior_for_state("Closing")
  285 + self.do_behavior_for_current_state()
277 286 self.changeState("Standby")
278 287  
279 288 #elif self.plc_status.plc_mode != "AUTO" or self.is_shuttingdown_or_restarting():
... ... @@ -359,8 +368,8 @@ class Majordome(Task):
359 368 "Scheduler": behavior_scheduler,
360 369 #"Closing": sub_behavior_closing,
361 370 }
362   - def do_behavior_for_state(self, current_state:str) -> str:
363   - print("CURRENT OCS (MAJORDOME) STATE: "+current_state)
  371 + def do_behavior_for_current_state(self) -> str:
  372 + print("CURRENT OCS (MAJORDOME) STATE: " + self.current_state)
364 373 time.sleep(2)
365 374 # EXIT if PLC not connected
366 375 #if not self.plc_is_connected(): return
... ... @@ -368,11 +377,11 @@ class Majordome(Task):
368 377 #if self.is_shuttingdown_or_restarting(): return
369 378 # run behavior for this state
370 379 #self.behavior[current_state](self)
371   - if current_state == "Closing":
  380 + if self.current_state == "Closing":
372 381 self.sub_behavior_closing()
373 382 else:
374   - self.behavior[current_state](self)
375   - return self.current_state
  383 + self.behavior[self.current_state](self)
  384 + return self.current_state
376 385  
377 386  
378 387 '''
... ...
src/majordome/tests.py
1 1 from django.test import TestCase
  2 +from common.models import *
2 3 from .tasks import Majordome
  4 +#from django.contrib.auth.models import User
  5 +import threading
  6 +#from threading import Thread
  7 +from django.shortcuts import get_object_or_404
  8 +import time
  9 +#import sys
  10 +import subprocess
  11 +import os
  12 +
3 13  
4 14 # Create your tests here.
5 15  
6   -class Majordome(TestCase):
  16 +
  17 +class MajordomeTests(TestCase):
  18 +
  19 + fixtures = ['tests/majordome_test']
  20 +
  21 +
7 22  
8 23 def setUp(self):
9   - self.majordome = Majordome()
  24 + '''
  25 + self.m = Majordome()
  26 + self.m.run()
  27 + '''
  28 + #Config.objects.create()
  29 + self.path_dir_file = os.path.dirname(os.path.realpath(__file__))
  30 + #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
  31 + self.venv_bin = '../../private/venv_py3_pyros/bin/python'
  32 +
  33 +
  34 + def getConfigFromDB(self):
  35 + return get_object_or_404(Config, id=1)
  36 +
  37 + def execProcessAsync(self, command):
  38 + #self.printFullTerm(Colors.BLUE, "Executing command [" + command + "]")
  39 + p = subprocess.Popen(command, shell=True)
  40 + '''
  41 + self.subproc.append((p, command))
  42 + self.printFullTerm(Colors.GREEN, "Process launched successfully")
  43 + self.addExecuted(self.current_command, command)
  44 + '''
  45 + return p
  46 +
  47 + def execProcessFromVenvAsync(self, command: str):
  48 + args = command.split()
  49 + #self.printFullTerm(Colors.BLUE, "Executing command from venv [" + str(' '.join(args[1:])) + "]")
  50 + p = subprocess.Popen(args)
  51 + #self.subproc.append((p, ' '.join(args[1:])))
  52 + #self.printFullTerm(Colors.GREEN, "Process launched successfully")
  53 + #self.addExecuted(self.current_command, str(' '.join(args[1:])))
  54 + return p
  55 +
  56 +
  57 +
  58 + def test_all(self):
  59 + '''
  60 + self.config = get_object_or_404(Config, id=1)
  61 + print("config id is", self.config.id)
  62 + print("config latitude is", self.config.latitude)
  63 + print("config global mode is", self.config.global_mode)
  64 + print("config row_data_save_frequency is", self.config.row_data_save_frequency)
  65 + '''
  66 +
  67 + #print_lock = threading.Lock()
  68 +
  69 +
  70 + #Majordome().run()
  71 + '''
  72 + time.sleep(2)
  73 + thread_majordome = Majordome()
  74 + thread_majordome.start()
  75 + #thread_majordome.run()
  76 + '''
  77 +
  78 + #with print_lock:
  79 + print("global mode is", self.getConfigFromDB().global_mode)
  80 + #sys.stdout.write("global mode")
  81 + #sys.stdout.flush()
  82 + print("global mode is", self.getConfigFromDB().global_mode)
  83 +
  84 + time.sleep(2)
  85 + #'''
  86 +
  87 + # Launch the Majordome agent
  88 + #'''
  89 + agent="majordome"
  90 + os.chdir(agent)
  91 + #print("Current directory : " + str(os.getcwd()))
  92 + p = self.execProcessFromVenvAsync(self.venv_bin + ' start_agent_'+agent+'_from_test.py')
  93 + #p = self.execProcessFromVenvAsync('./start_agent_'+agent+'.py')
  94 + #p.wait()
  95 + print("hello1")
  96 + print("hello2")
  97 + time.sleep(7)
10 98  
11   - def test_basic(self):
12   - # TODO write some basic tests for majordome
13   - pass
14 99 \ No newline at end of file
  100 + # Kill agent Majordome
  101 + p.kill()
  102 + #self.execProcessAsync("ps aux | grep \"start_agent_majordome.py\" | awk '{ print $2 }' | xargs kill")
  103 + #self.execProcessAsync("ps aux | grep start_agent_majordome.py | awk '{ print $2 }' | xargs kill")
  104 + #'''
  105 +
  106 + print("hello")
  107 + #thread_majordome.join()
  108 + #thread_majordome.killExecutingSequence()
... ...
src/misc/fixtures/initial_fixture.json
1 1 [
  2 +
2 3 {
3 4 "model": "common.country",
4 5 "pk": 1,
... ... @@ -8,6 +9,7 @@
8 9 "quota": null
9 10 }
10 11 },
  12 +
11 13 {
12 14 "model": "common.detector",
13 15 "pk": 1,
... ... @@ -563,6 +565,7 @@
563 565 "can_del_void_req": false
564 566 }
565 567 },
  568 +
566 569 {
567 570 "model": "common.config",
568 571 "pk": 1,
... ...
src/misc/fixtures/tests/majordome_test.json 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +[
  2 +
  3 +{
  4 + "model": "common.plcdevice",
  5 + "pk": 1,
  6 + "fields": {
  7 + "name": "Plc",
  8 + "desc": "",
  9 + "created": "2018-06-18 14:32:00",
  10 + "updated": "2018-06-18 14:32:00",
  11 + "is_online": false,
  12 + "maintenance_date": null
  13 + }
  14 +},
  15 +
  16 +{
  17 + "model": "common.config",
  18 + "pk": 1,
  19 + "fields": {
  20 + "id": 1,
  21 + "latitude": 10,
  22 + "local_time_zone": 1,
  23 + "longitude": 1,
  24 + "altitude": 1,
  25 + "horizon_line": 1,
  26 + "row_data_save_frequency": 400,
  27 + "request_frequency": 300,
  28 + "analysed_data_save": 300,
  29 + "telescope_ip_address": "127.0.0.1",
  30 + "camera_ip_address": "127.0.0.1",
  31 + "plc_ip_address": "127.0.0.1",
  32 + "global_mode": true,
  33 + "ack": true,
  34 + "bypass": false,
  35 + "plc_timeout_seconds": 60
  36 + }
  37 +},
  38 +
  39 +{
  40 + "model": "common.plcdevicestatus",
  41 + "pk": 1,
  42 + "fields": {
  43 + "id": 1,
  44 + "device_id": 1,
  45 + "created": "2018-07-18 11:49:49",
  46 + "plc_mode": "AUTO"
  47 + }
  48 +}
  49 +
  50 +]
... ...