Commit 03814884c0f73a0e4fcc8dfe097b04d1af4835c8

Authored by Etienne Pallier
1 parent f47ec727
Exists in dev

launch majordome agent from majordome unit tests

@@ -11,8 +11,8 @@ import signal @@ -11,8 +11,8 @@ import signal
11 11
12 # For USE_CELERY global variable 12 # For USE_CELERY global variable
13 #from src.pyros import settings 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 DEBUG = True 17 DEBUG = True
18 SIMULATOR_CONFIG_FILE = "conf.json" #default config file 18 SIMULATOR_CONFIG_FILE = "conf.json" #default config file
@@ -679,6 +679,7 @@ class Pyros(AManager): @@ -679,6 +679,7 @@ class Pyros(AManager):
679 # EP added: 679 # EP added:
680 if not TOTAL: self.reset_database_sim() 680 if not TOTAL: self.reset_database_sim()
681 # Actualise l’état de la DB en accord avec l’ensemble des modèles et des migrations actuels 681 # Actualise l’état de la DB en accord avec l’ensemble des modèles et des migrations actuels
  682 + self.makemigrations()
682 self.migrate() 683 self.migrate()
683 # Load fixture initial_fixture.json 684 # Load fixture initial_fixture.json
684 self.loaddata() 685 self.loaddata()
@@ -763,6 +764,79 @@ class Pyros(AManager): @@ -763,6 +764,79 @@ class Pyros(AManager):
763 return 0 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 def kill_server(self): 840 def kill_server(self):
767 self.execProcessAsync("fuser -k 8000/tcp") 841 self.execProcessAsync("fuser -k 8000/tcp")
768 return 0 842 return 0
@@ -799,7 +873,7 @@ class Pyros(AManager): @@ -799,7 +873,7 @@ class Pyros(AManager):
799 self.execProcessAsync("ps aux | grep \" cameraNIRSimulator.py\" | awk '{ print $2 }' | xargs kill") 873 self.execProcessAsync("ps aux | grep \" cameraNIRSimulator.py\" | awk '{ print $2 }' | xargs kill")
800 self.execProcessAsync("ps aux | grep \" cameraVISSimulator.py\" | awk '{ print $2 }' | xargs kill") 874 self.execProcessAsync("ps aux | grep \" cameraVISSimulator.py\" | awk '{ print $2 }' | xargs kill")
801 self.changeDirectory("..") 875 self.changeDirectory("..")
802 - self.stop_workers() 876 + if USE_CELERY: self.stop_workers()
803 877
804 self.printFullTerm(Colors.GREEN, "simulation ended") 878 self.printFullTerm(Colors.GREEN, "simulation ended")
805 return 0 879 return 0
@@ -920,6 +994,7 @@ class Pyros(AManager): @@ -920,6 +994,7 @@ class Pyros(AManager):
920 "start_agent_monitoring": self.start_agent_monitoring, 994 "start_agent_monitoring": self.start_agent_monitoring,
921 "start_agent_majordome": self.start_agent_majordome, 995 "start_agent_majordome": self.start_agent_majordome,
922 "start_agent_alertmanager": self.start_agent_alertmanager, 996 "start_agent_alertmanager": self.start_agent_alertmanager,
  997 + "test_majordome": self.test_majordome,
923 998
924 # ex start 999 # ex start
925 "start_workers": self.start_workers, 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 import os 3 import os
4 import sys 4 import sys
@@ -6,6 +6,9 @@ import sys @@ -6,6 +6,9 @@ import sys
6 # DJANGO setup 6 # DJANGO setup
7 #sys.path.append('/PROJECTS/GFT/SOFT/PYROS_SOFT/PYROS201802') 7 #sys.path.append('/PROJECTS/GFT/SOFT/PYROS_SOFT/PYROS201802')
8 sys.path.append('..') 8 sys.path.append('..')
  9 +#print("file is", __file__)
  10 +mypath = os.getcwd()
  11 +
9 # Go into src/ 12 # Go into src/
10 os.chdir('..') 13 os.chdir('..')
11 #print("Current directory : " + str(os.getcwd())) 14 #print("Current directory : " + str(os.getcwd()))
src/majordome/start_agent_majordome_from_test.py 0 → 100755
@@ -0,0 +1,26 @@ @@ -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,6 +24,8 @@ from majordome.MajordomeDecorators import *
24 from utils.JDManipulator import * 24 from utils.JDManipulator import *
25 import time 25 import time
26 26
  27 +from threading import Thread
  28 +
27 DEBUG_FILE = False 29 DEBUG_FILE = False
28 log = L.setupLogger("MajordomeTaskLogger", "Majordome") 30 log = L.setupLogger("MajordomeTaskLogger", "Majordome")
29 31
@@ -35,7 +37,7 @@ log = L.setupLogger("MajordomeTaskLogger", "Majordome") @@ -35,7 +37,7 @@ log = L.setupLogger("MajordomeTaskLogger", "Majordome")
35 check if the last schedule made has to be planned 37 check if the last schedule made has to be planned
36 launch schedule's sequences 38 launch schedule's sequences
37 ''' 39 '''
38 -class Majordome(Task): 40 +class Majordome(Task, Thread):
39 41
40 loop_speed = 1 42 loop_speed = 1
41 julian_div = 86400 43 julian_div = 86400
@@ -94,7 +96,14 @@ class Majordome(Task): @@ -94,7 +96,14 @@ class Majordome(Task):
94 # SETUP 96 # SETUP
95 try : 97 try :
96 self.config = get_object_or_404(Config, id=1) 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 return -1 107 return -1
99 108
100 #self.config.ntc = False 109 #self.config.ntc = False
@@ -134,7 +143,7 @@ class Majordome(Task): @@ -134,7 +143,7 @@ class Majordome(Task):
134 if self.current_state not in ['STARTING', 'PASSIVE_NO_PLC']: 143 if self.current_state not in ['STARTING', 'PASSIVE_NO_PLC']:
135 if self.plc_is_not_auto(): self.changeState("PASSIVE") 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,7 +245,7 @@ class Majordome(Task):
236 print("Waiting for PLC connection") 245 print("Waiting for PLC connection")
237 # Wait until PCL is connected 246 # Wait until PCL is connected
238 while not self.plc_is_connected(): 247 while not self.plc_is_connected():
239 - time.sleep(2) 248 + time.sleep(3)
240 ''' 249 '''
241 if self.is_restarting(): 250 if self.is_restarting():
242 self.changeState("STARTING") 251 self.changeState("STARTING")
@@ -273,7 +282,7 @@ class Majordome(Task): @@ -273,7 +282,7 @@ class Majordome(Task):
273 if self.NEED_TO_CLOSE: 282 if self.NEED_TO_CLOSE:
274 self.changeState("Closing") 283 self.changeState("Closing")
275 #self.sub_behavior_closing() 284 #self.sub_behavior_closing()
276 - self.do_behavior_for_state("Closing") 285 + self.do_behavior_for_current_state()
277 self.changeState("Standby") 286 self.changeState("Standby")
278 287
279 #elif self.plc_status.plc_mode != "AUTO" or self.is_shuttingdown_or_restarting(): 288 #elif self.plc_status.plc_mode != "AUTO" or self.is_shuttingdown_or_restarting():
@@ -359,8 +368,8 @@ class Majordome(Task): @@ -359,8 +368,8 @@ class Majordome(Task):
359 "Scheduler": behavior_scheduler, 368 "Scheduler": behavior_scheduler,
360 #"Closing": sub_behavior_closing, 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 time.sleep(2) 373 time.sleep(2)
365 # EXIT if PLC not connected 374 # EXIT if PLC not connected
366 #if not self.plc_is_connected(): return 375 #if not self.plc_is_connected(): return
@@ -368,11 +377,11 @@ class Majordome(Task): @@ -368,11 +377,11 @@ class Majordome(Task):
368 #if self.is_shuttingdown_or_restarting(): return 377 #if self.is_shuttingdown_or_restarting(): return
369 # run behavior for this state 378 # run behavior for this state
370 #self.behavior[current_state](self) 379 #self.behavior[current_state](self)
371 - if current_state == "Closing": 380 + if self.current_state == "Closing":
372 self.sub_behavior_closing() 381 self.sub_behavior_closing()
373 else: 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 from django.test import TestCase 1 from django.test import TestCase
  2 +from common.models import *
2 from .tasks import Majordome 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 # Create your tests here. 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 def setUp(self): 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 \ No newline at end of file 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 "model": "common.country", 4 "model": "common.country",
4 "pk": 1, 5 "pk": 1,
@@ -8,6 +9,7 @@ @@ -8,6 +9,7 @@
8 "quota": null 9 "quota": null
9 } 10 }
10 }, 11 },
  12 +
11 { 13 {
12 "model": "common.detector", 14 "model": "common.detector",
13 "pk": 1, 15 "pk": 1,
@@ -563,6 +565,7 @@ @@ -563,6 +565,7 @@
563 "can_del_void_req": false 565 "can_del_void_req": false
564 } 566 }
565 }, 567 },
  568 +
566 { 569 {
567 "model": "common.config", 570 "model": "common.config",
568 "pk": 1, 571 "pk": 1,
src/misc/fixtures/tests/majordome_test.json 0 → 100644
@@ -0,0 +1,50 @@ @@ -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 +]