Commit 03814884c0f73a0e4fcc8dfe097b04d1af4835c8
1 parent
f47ec727
Exists in
dev
launch majordome agent from majordome unit tests
Showing
7 changed files
with
279 additions
and
19 deletions
Show diff stats
pyros.py
@@ -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())) |
@@ -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, |
@@ -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 | +] |