Commit eb6649f7d6dc7d2cdfba6affee7627471c61c406
1 parent
6a41fe96
Exists in
dev
bugfix DEFAULT_VALIDITY_DURATION in AgentCmd et ajout de ma config perso
Showing
7 changed files
with
246 additions
and
15 deletions
Show diff stats
private/plugins/README deleted
... | ... | @@ -0,0 +1,25 @@ |
1 | +# Schema file to check the syntax of this config file | |
2 | +schema: schema_computer-2.0.yml | |
3 | + | |
4 | +# Here is the description of the configuration of an isolated computer | |
5 | +COMPUTER: | |
6 | + | |
7 | + inventory_label: CPT-XCY-001 | |
8 | + manufacturer: XCY | |
9 | + model: X26A | |
10 | + description: "Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz 1.90 GHz RAM = 4 GB" | |
11 | + sn: 00331-10000-00001-AA478 | |
12 | + power: | |
13 | + voltage: 12 | |
14 | + intensity: 5 | |
15 | + socket: "IEC 60130-10 Type A: 5.5 mm OD, 2.5 mm ID" | |
16 | + | |
17 | + #hostname: macp1219 | |
18 | + hostname: c32f49397c28 | |
19 | + virtual_machine: False | |
20 | + os: Mac | |
21 | + os_version: "10" | |
22 | + network_interfaces: | |
23 | + - 00-A8-3D-68-22-87 # Gigabit 2 | |
24 | + - 00-A8-3D-68-22-86 # Gigabit 3 | |
25 | + - 16-82-FE-44-64-E8 # Wifi | ... | ... |
privatedev/config/tnc/observatory_tnc.yml
... | ... | @@ -132,7 +132,17 @@ OBSERVATORY: |
132 | 132 | network_interface_index: 0 |
133 | 133 | # IP attributed by the Router |
134 | 134 | network_ip: 192.168.1.7 |
135 | - | |
135 | + | |
136 | + - COMPUTER: | |
137 | + name: EtienneComputer | |
138 | + file: computer_XYZ_EP.yml | |
139 | + # Describe here the configuration of the computer in operation | |
140 | + role: Main | |
141 | + # Choice of the interface to connect the computer to the network (cf.network_interfaces infile) | |
142 | + network_interface_index: 0 | |
143 | + # IP attributed by the Router | |
144 | + network_ip: 192.168.0.11 | |
145 | + | |
136 | 146 | # === Assembly of devices into units |
137 | 147 | # A unit is a robotic telescope |
138 | 148 | UNITS: |
... | ... | @@ -295,11 +305,12 @@ OBSERVATORY: |
295 | 305 | computer: AKlotzPersoComputer |
296 | 306 | protocol: privatedev/plugin/agent/AgentImagesProcessor_tnc_up1.py |
297 | 307 | |
298 | - # SF11-IPC (for AKo) | |
308 | + # Basic Agent (for EP, to test the Agent base class) | |
299 | 309 | - AGENT: |
300 | - name: AgentImagesProcessor_tnc_up1_ako | |
301 | - computer: AKoralewskiPersoComputer | |
302 | - protocol: privatedev/plugin/agent/AgentImagesProcessor_tnc_up1.py | |
310 | + name: AgentBasic | |
311 | + computer: EtienneComputer | |
312 | + protocol: private/plugin/agent/AgentBasic.py | |
313 | + | |
303 | 314 | |
304 | 315 | TOPOLOGY: |
305 | 316 | ... | ... |
... | ... | @@ -0,0 +1,193 @@ |
1 | +#!/usr/bin/env python3 | |
2 | + | |
3 | +import sys | |
4 | + | |
5 | +import os | |
6 | +pwd = os.environ['PROJECT_ROOT_PATH'] | |
7 | +if pwd not in sys.path: | |
8 | + sys.path.append(pwd) | |
9 | + | |
10 | +from src.core.pyros_django.agent.Agent import Agent, build_agent | |
11 | + | |
12 | +##import utils.Logger as L | |
13 | + | |
14 | +##from .Agent import Agent | |
15 | +##log = L.setupLogger("AgentXTaskLogger", "AgentX") | |
16 | + | |
17 | + | |
18 | + | |
19 | +class AgentBasic(Agent): | |
20 | + | |
21 | + # FOR TEST ONLY | |
22 | + # Run this agent in simulator mode | |
23 | + TEST_MODE = False | |
24 | + # Run the assertion tests at the end | |
25 | + TEST_WITH_FINAL_TEST = False | |
26 | + #TEST_MAX_DURATION_SEC = None | |
27 | + TEST_MAX_DURATION_SEC = 100 | |
28 | + # Who should I send commands to ? | |
29 | + TEST_COMMANDS_DEST = "myself" | |
30 | + #TEST_COMMANDS_DEST = "AgentB" | |
31 | + # Scenario to be executed | |
32 | + | |
33 | + | |
34 | + | |
35 | + | |
36 | + """ | |
37 | + ================================================================= | |
38 | + FUNCTIONS RUN INSIDE MAIN THREAD | |
39 | + ================================================================= | |
40 | + """ | |
41 | + | |
42 | + # @override | |
43 | + ''' | |
44 | + #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True): | |
45 | + def __init__(self, config_filename=None): | |
46 | + ##if name is None: name = self.__class__.__name__ | |
47 | + #super().__init__(name, config_filename, RUN_IN_THREAD) | |
48 | + super().__init__(config_filename) | |
49 | + #self._log.print(f"init done for {name}") | |
50 | + self._log.print("init done") | |
51 | + ''' | |
52 | + def __init__(self, name:str=None): | |
53 | + if name is None: | |
54 | + name = self.__class__.__name__ | |
55 | + super().__init__() | |
56 | + #super().__init__(RUN_IN_THREAD) | |
57 | + | |
58 | + # @override | |
59 | + def init(self): | |
60 | + super().init() | |
61 | + # --- Set the mode according the startmode value | |
62 | + ##agent_alias = self.__class__.__name__ | |
63 | + ##self.set_mode_from_config(agent_alias) | |
64 | + | |
65 | + ''' | |
66 | + # @override | |
67 | + def load_config(self): | |
68 | + super().load_config() | |
69 | + ''' | |
70 | + | |
71 | + ''' | |
72 | + # @override | |
73 | + def update_survey(self): | |
74 | + super().update_survey() | |
75 | + ''' | |
76 | + | |
77 | + ''' | |
78 | + # @override | |
79 | + def get_next_command(self): | |
80 | + return super().get_next_command() | |
81 | + ''' | |
82 | + | |
83 | + # @override | |
84 | + def do_log(self): | |
85 | + super().do_log() | |
86 | + | |
87 | + | |
88 | + | |
89 | + """ | |
90 | + ================================================================= | |
91 | + FUNCTIONS RUN INSIDE A SUB-THREAD (OR A PROCESS) (thread_*()) | |
92 | + ================================================================= | |
93 | + """ | |
94 | + | |
95 | + # Define your own command step(s) here | |
96 | + def cmd_step1(self, step:int): | |
97 | + cmd = self._current_specific_cmd | |
98 | + cmd.result = f"in step #{step}/{self._thread_total_steps_number}" | |
99 | + cmd.save() | |
100 | + """ | |
101 | + if self.RUN_IN_THREAD: | |
102 | + print("(save from thread)") | |
103 | + cmd.save() | |
104 | + else: | |
105 | + #@transaction.atomic | |
106 | + print("(save from process)") | |
107 | + with transaction.atomic(): | |
108 | + cmd.save() | |
109 | + #Command.objects.select_for_update() | |
110 | + """ | |
111 | + | |
112 | + def cmd_step2(self, step:int): | |
113 | + self.cmd_step1(step) | |
114 | + def cmd_step3(self, step:int): | |
115 | + self.cmd_step1(step) | |
116 | + def cmd_step4(self, step:int): | |
117 | + self.cmd_step1(step) | |
118 | + | |
119 | + """ | |
120 | + # @override | |
121 | + def thread_exec_specific_cmd_step(self, step:int, sleep_time:float=1.0): | |
122 | + self.thread_stop_if_asked() | |
123 | + cmd = self._current_specific_cmd | |
124 | + print(f">>>>> Thread (cmd {cmd.name}): step #{step}/5") | |
125 | + self.sleep(sleep_time) | |
126 | + """ | |
127 | + | |
128 | + ''' | |
129 | + # @override | |
130 | + def exec_specific_cmd_start(self, cmd:Command, from_thread=True): | |
131 | + super().exec_specific_cmd_start(cmd, from_thread) | |
132 | + ''' | |
133 | + | |
134 | + | |
135 | + | |
136 | + # @override | |
137 | + def simulator_test_results_main(self, commands): | |
138 | + nb_asserted = 0 | |
139 | + for cmd in commands: | |
140 | + if cmd.name == "flush_commands": | |
141 | + assert cmd.is_executed() | |
142 | + nb_asserted+=1 | |
143 | + # 2 times | |
144 | + if cmd.name == "go_active": | |
145 | + assert cmd.is_executed() | |
146 | + nb_asserted+=1 | |
147 | + # 2 times | |
148 | + if cmd.name == "go_idle": | |
149 | + assert cmd.is_executed() | |
150 | + nb_asserted+=1 | |
151 | + """ | |
152 | + if cmd.name == "specific0": | |
153 | + assert cmd.is_skipped() | |
154 | + assert cmd.result == "in step #5/5" | |
155 | + nb_asserted+=1 | |
156 | + """ | |
157 | + if cmd.name == "specific1": | |
158 | + assert cmd.is_killed() | |
159 | + nb_asserted+=1 | |
160 | + if cmd.name == "specific2": | |
161 | + assert cmd.is_executed() | |
162 | + assert cmd.result == "in step #5/5" | |
163 | + nb_asserted+=1 | |
164 | + if cmd.name == "eval 4+3": | |
165 | + assert cmd.is_executed() | |
166 | + assert cmd.get_result() == "7" | |
167 | + nb_asserted+=1 | |
168 | + if cmd.name in ("abort"): | |
169 | + assert cmd.is_executed() | |
170 | + nb_asserted+=1 | |
171 | + if cmd.name in ("exit"): | |
172 | + assert cmd.is_executed() | |
173 | + nb_asserted+=1 | |
174 | + return nb_asserted | |
175 | + | |
176 | + | |
177 | +""" | |
178 | +================================================================= | |
179 | + MAIN FUNCTION | |
180 | +================================================================= | |
181 | +""" | |
182 | +if __name__ == "__main__": | |
183 | + | |
184 | + agent = build_agent(AgentBasic) | |
185 | + | |
186 | + ''' | |
187 | + TEST_MODE, configfile = extract_parameters() | |
188 | + #agent = AgentX() | |
189 | + agent = AgentA("AgentA", configfile, RUN_IN_THREAD) | |
190 | + agent.setSimulatorMode(TEST_MODE) | |
191 | + print(agent) | |
192 | + ''' | |
193 | + agent.run() | ... | ... |
pyros.py
... | ... | @@ -78,7 +78,8 @@ AGENTS = { |
78 | 78 | "majordome": "majordome", |
79 | 79 | #"scheduler": "scheduler", |
80 | 80 | "alert_manager": "alert_manager", |
81 | - "agentImagesProcessor_tnc_up1": "../../../privatedev/plugin/agent" | |
81 | + "agentImagesProcessor_tnc_up1": "../../../privatedev/plugin/agent", | |
82 | + "agentBasic": "agent", | |
82 | 83 | } |
83 | 84 | # AGENTS = ["agentX", "webserver", "monitoring", "majordome", "scheduler", "alert_manager"] |
84 | 85 | # AGENTS = ["all", "webserver", "monitoring", "majordome", "scheduler", "alert"] | ... | ... |
src/core/pyros_django/agent/Agent.py
... | ... | @@ -396,7 +396,7 @@ class Agent: |
396 | 396 | # ------------------------------- |
397 | 397 | |
398 | 398 | # Agent general command |
399 | - ("Agent set_mode ATTENTIVE", 2, "MODE = ATTENTIVE"), | |
399 | + ("self set_mode ATTENTIVE", 2, "MODE = ATTENTIVE"), | |
400 | 400 | # => should get "ATTENTIVE" |
401 | 401 | ("self get_mode", 1, "MODE = ATTENTIVE"), |
402 | 402 | |
... | ... | @@ -1593,9 +1593,9 @@ class Agent: |
1593 | 1593 | #ex: send_command(“AgentX”,”GENERIC”,”EVAL”,“3+4”) |
1594 | 1594 | ex: send_command(“AgentX”,"EVAL”,“3+4”) |
1595 | 1595 | """ |
1596 | - #return AgentCmd.send_cmd(self.name, self._get_real_agent_name_for_alias(to_agent), cmd_name, cmd_args) | |
1597 | - cmd = self.create_cmd_for(to_agent, cmd_name, cmd_args) | |
1598 | - cmd.send() | |
1596 | + #return AgentCmd.send_cmd_from_to(self.name, self._get_real_agent_name_for_alias(to_agent), cmd_name, cmd_args) | |
1597 | + cmd = self.create_cmd_for(to_agent, cmd_name, cmd_args).send() | |
1598 | + #cmd.send() | |
1599 | 1599 | return cmd |
1600 | 1600 | |
1601 | 1601 | def create_cmd_for(self, to_agent, cmd_name, cmd_args=None) -> AgentCmd: | ... | ... |
src/core/pyros_django/common/models.py
... | ... | @@ -464,7 +464,7 @@ class AgentCmd(models.Model): |
464 | 464 | "CMD_EXECUTED", |
465 | 465 | ) |
466 | 466 | |
467 | - # Command default validity duration (from sending time) in hours, before peremption (in sec) | |
467 | + # Command default validity duration (from sending time), before peremption (in sec) | |
468 | 468 | # => From the time a command was sent (cmd.s_deposit_time), it is still valid during VALIDITY_DURATION hours |
469 | 469 | # => After that, it is considered as "expired" (obsolete) and must be marked as "CMD_OUTOFDATE" and not be executed anymore (and can be purged) |
470 | 470 | # => Thus, a command is expired FROM time = s_deposit_time + VALIDITY_DURATION |
... | ... | @@ -485,7 +485,7 @@ class AgentCmd(models.Model): |
485 | 485 | ##name = models.CharField(max_length=400, help_text='command name', null=False) |
486 | 486 | full_name = models.CharField(max_length=400, help_text='command full name (with type and args)', null=False) |
487 | 487 | |
488 | - validity_duration = models.PositiveIntegerField('(in hour)', default=DEFAULT_VALIDITY_DURATION) | |
488 | + validity_duration = models.PositiveIntegerField('(in sec)', default=DEFAULT_VALIDITY_DURATION) | |
489 | 489 | exec_timeout = models.PositiveIntegerField('(in sec)', default=DEFAULT_EXEC_TIMEOUT) |
490 | 490 | |
491 | 491 | #state = models.CharField(choices = CMD_STATUS_CODES, default=CMD_STATUS_CODES.CMD_PENDING, max_length=20) |
... | ... | @@ -621,7 +621,7 @@ class AgentCmd(models.Model): |
621 | 621 | """ |
622 | 622 | |
623 | 623 | @classmethod |
624 | - def send_cmd(cls, agent_from, agent_to, cmd_name, cmd_args=None, cmd_validity:int=None, cmd_timeout:int=None): | |
624 | + def send_cmd_from_to(cls, agent_from, agent_to, cmd_name, cmd_args=None, cmd_validity:int=None, cmd_timeout:int=None): | |
625 | 625 | # def send(cls, from_agent, to_agent, cmd_name, cmd_args=None): |
626 | 626 | """ |
627 | 627 | ex: send("AgentA",“AgentB”,"EVAL”,“3+4”) |
... | ... | @@ -639,7 +639,8 @@ class AgentCmd(models.Model): |
639 | 639 | |
640 | 640 | @classmethod |
641 | 641 | def max_deposit_date_for_peremption(cls): |
642 | - return datetime.utcnow().astimezone() - timedelta(hours=cls.DEFAULT_VALIDITY_DURATION) | |
642 | + return datetime.utcnow().astimezone() - timedelta(seconds=cls.DEFAULT_VALIDITY_DURATION) | |
643 | + #return datetime.utcnow().astimezone() - timedelta(hours=cls.DEFAULT_VALIDITY_DURATION) | |
643 | 644 | |
644 | 645 | @classmethod |
645 | 646 | def delete_commands_with_running_status_for_agent(cls, agent_name): |
... | ... | @@ -733,7 +734,7 @@ class AgentCmd(models.Model): |
733 | 734 | NB: datetime.utcnow() is equivalent to datetime.now(timezone.utc) |
734 | 735 | """ |
735 | 736 | printd( |
736 | - f"(Looking for commands sent to me that are not executing and perempted - i.e. older than {cls.DEFAULT_VALIDITY_DURATION} hour(s))") | |
737 | + f"(Looking for commands sent to me that are not executing and perempted - i.e. older than {cls.DEFAULT_VALIDITY_DURATION/60} minute(s))") | |
737 | 738 | #COMMAND_PEREMPTION_DATE_FROM_NOW = datetime.utcnow() - timedelta(hours = cls.COMMANDS_PEREMPTION_HOURS) |
738 | 739 | #print("peremption date", COMMAND_PEREMPTION_DATE_FROM_NOW) |
739 | 740 | old_commands = cls.objects.filter( | ... | ... |