Commit eb6649f7d6dc7d2cdfba6affee7627471c61c406

Authored by Etienne Pallier
1 parent 6a41fe96
Exists in dev

bugfix DEFAULT_VALIDITY_DURATION in AgentCmd et ajout de ma config perso

private/plugins/README deleted
privatedev/config/tnc/computer_XYZ_EP.yml 0 → 100644
... ... @@ -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  
... ...
privatedev/plugin/agent/AgentBasic.py 0 → 100755
... ... @@ -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(
... ...