Verify that action tree is starting to work!

This commit is contained in:
Marek Wolan
2023-09-05 15:53:22 +01:00
parent ffe1e92664
commit 1dccceaf56
2 changed files with 35 additions and 3 deletions

View File

@@ -60,6 +60,9 @@ class Action(BaseModel):
""" """
# TODO: maybe this can be renamed to something like action selector?
# Because there are two ways it's used, to select from a list of action verbs, or to select a child object to which to
# forward the request.
class ActionManager(BaseModel): class ActionManager(BaseModel):
""" """
ActionManager is used by `SimComponent` instances to keep track of actions. ActionManager is used by `SimComponent` instances to keep track of actions.
@@ -132,14 +135,13 @@ class ActionManager(BaseModel):
self.actions.pop(name) self.actions.pop(name)
def get_action_tree(self) -> List[List[str]]: def get_action_tree(self) -> List[List[str]]:
"""Recursively generate action tree for this component.""" """Recursively generate action tree for this component."""
actions = [] actions = []
for act_name, act in self.actions.items(): for act_name, act in self.actions.items():
if isinstance(act.func, ActionManager): if isinstance(act.func, ActionManager):
sub_actions = act.func.get_action_tree() sub_actions = act.func.get_action_tree()
sub_actions = [[act_name]+a for a in sub_actions] sub_actions = [[act_name] + a for a in sub_actions]
actions.extend(sub_actions) actions.extend(sub_actions)
else: else:
actions.append([act_name]) actions.append([act_name])

View File

@@ -10,7 +10,7 @@ from prettytable import MARKDOWN, PrettyTable
from primaite import getLogger from primaite import getLogger
from primaite.exceptions import NetworkError from primaite.exceptions import NetworkError
from primaite.simulator.core import SimComponent from primaite.simulator.core import Action, ActionManager, SimComponent
from primaite.simulator.domain.account import Account from primaite.simulator.domain.account import Account
from primaite.simulator.file_system.file_system import FileSystem from primaite.simulator.file_system.file_system import FileSystem
from primaite.simulator.network.protocols.arp import ARPEntry, ARPPacket from primaite.simulator.network.protocols.arp import ARPEntry, ARPPacket
@@ -145,6 +145,14 @@ class NIC(SimComponent):
) )
return state return state
def _init_action_manager(self) -> ActionManager:
am = super()._init_action_manager()
am.add_action("enable", Action(func=lambda request, context: self.enable()))
am.add_action("disable", Action(func=lambda request, context: self.disable()))
return am
@property @property
def ip_network(self) -> IPv4Network: def ip_network(self) -> IPv4Network:
""" """
@@ -925,6 +933,24 @@ class Node(SimComponent):
super().__init__(**kwargs) super().__init__(**kwargs)
self.arp.nics = self.nics self.arp.nics = self.nics
def _init_action_manager(self) -> ActionManager:
# TODO: I see that this code is really confusing and hard to read right now... I think some of these things will
# need a better name and better documentation.
am = super()._init_action_manager()
# since there are potentially many services, create an action manager that can map service name
self._service_action_manager = ActionManager()
am.add_action("service", Action(func=self._service_action_manager))
self._process_action_manager = ActionManager()
am.add_action("process", Action(func=self._process_action_manager))
self._application_action_manager = ActionManager()
am.add_action("application", Action(func=self._application_action_manager))
self._nic_action_manager = ActionManager()
am.add_action("nic", Action(func=self._nic_action_manager))
am.add_action("file_system", Action(func=self.file_system._action_manager))
return am
def describe_state(self) -> Dict: def describe_state(self) -> Dict:
""" """
Produce a dictionary describing the current state of this object. Produce a dictionary describing the current state of this object.
@@ -1000,6 +1026,7 @@ class Node(SimComponent):
self.sys_log.info(f"Connected NIC {nic}") self.sys_log.info(f"Connected NIC {nic}")
if self.operating_state == NodeOperatingState.ON: if self.operating_state == NodeOperatingState.ON:
nic.enable() nic.enable()
self._nic_action_manager.add_action(nic.uuid, Action(func=nic._action_manager))
else: else:
msg = f"Cannot connect NIC {nic} as it is already connected" msg = f"Cannot connect NIC {nic} as it is already connected"
self.sys_log.logger.error(msg) self.sys_log.logger.error(msg)
@@ -1024,6 +1051,7 @@ class Node(SimComponent):
nic.parent = None nic.parent = None
nic.disable() nic.disable()
self.sys_log.info(f"Disconnected NIC {nic}") self.sys_log.info(f"Disconnected NIC {nic}")
self._nic_action_manager.remove_action(nic.uuid)
else: else:
msg = f"Cannot disconnect NIC {nic} as it is not connected" msg = f"Cannot disconnect NIC {nic} as it is not connected"
self.sys_log.logger.error(msg) self.sys_log.logger.error(msg)
@@ -1110,6 +1138,7 @@ class Node(SimComponent):
service.install() # Perform any additional setup, such as creating files for this service on the node. service.install() # Perform any additional setup, such as creating files for this service on the node.
self.sys_log.info(f"Installed service {service.name}") self.sys_log.info(f"Installed service {service.name}")
_LOGGER.info(f"Added service {service.uuid} to node {self.uuid}") _LOGGER.info(f"Added service {service.uuid} to node {self.uuid}")
self._service_action_manager.add_action(service.uuid, Action(func=service._action_manager))
def uninstall_service(self, service: Service) -> None: def uninstall_service(self, service: Service) -> None:
"""Uninstall and completely remove service from this node. """Uninstall and completely remove service from this node.
@@ -1125,6 +1154,7 @@ class Node(SimComponent):
service.parent = None service.parent = None
self.sys_log.info(f"Uninstalled service {service.name}") self.sys_log.info(f"Uninstalled service {service.name}")
_LOGGER.info(f"Removed service {service.uuid} from node {self.uuid}") _LOGGER.info(f"Removed service {service.uuid} from node {self.uuid}")
self._service_action_manager.remove_action(service.uuid)
def __contains__(self, item: Any) -> bool: def __contains__(self, item: Any) -> bool:
if isinstance(item, Service): if isinstance(item, Service):