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 | 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())) | ... | ... |
... | ... | @@ -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, | ... | ... |
... | ... | @@ -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 | +] | ... | ... |