Make changes to the way actions work
This commit is contained in:
@@ -136,7 +136,7 @@ class SimComponent(BaseModel):
|
|||||||
if not kwargs.get("uuid"):
|
if not kwargs.get("uuid"):
|
||||||
kwargs["uuid"] = str(uuid4())
|
kwargs["uuid"] = str(uuid4())
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.action_manager: Optional[ActionManager] = None
|
self._action_manager: ActionManager = self._init_action_manager()
|
||||||
self._parent: Optional["SimComponent"] = None
|
self._parent: Optional["SimComponent"] = None
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -153,6 +153,28 @@ class SimComponent(BaseModel):
|
|||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
def _init_action_manager(self) -> ActionManager:
|
||||||
|
"""
|
||||||
|
Initialise the action manager for this component.
|
||||||
|
|
||||||
|
When using a hierarchy of components, the child classes should call the parent class's _init_action_manager and
|
||||||
|
add additional actions on top of the existing generic ones.
|
||||||
|
|
||||||
|
Example usage for inherited classes:
|
||||||
|
|
||||||
|
..code::python
|
||||||
|
|
||||||
|
class WebBrowser(Application):
|
||||||
|
def _init_action_manager(self) -> ActionManager:
|
||||||
|
am = super()._init_action_manager() # all actions generic to any Application get initialised
|
||||||
|
am.add_action(...) # initialise any actions specific to the web browser
|
||||||
|
return am
|
||||||
|
|
||||||
|
:return: Actiona manager object belonging to this sim component.
|
||||||
|
:rtype: ActionManager
|
||||||
|
"""
|
||||||
|
return ActionManager()
|
||||||
|
|
||||||
def apply_action(self, action: List[str], context: Dict = {}) -> None:
|
def apply_action(self, action: List[str], context: Dict = {}) -> None:
|
||||||
"""
|
"""
|
||||||
Apply an action to a simulation component. Action data is passed in as a 'namespaced' list of strings.
|
Apply an action to a simulation component. Action data is passed in as a 'namespaced' list of strings.
|
||||||
|
|||||||
@@ -85,17 +85,6 @@ class DomainController(SimComponent):
|
|||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.action_manager = ActionManager()
|
|
||||||
# Action 'account' matches requests like:
|
|
||||||
# ['account', '<account-uuid>', *account_action]
|
|
||||||
self.action_manager.add_action(
|
|
||||||
"account",
|
|
||||||
Action(
|
|
||||||
func=lambda request, context: self.accounts[request.pop(0)].apply_action(request, context),
|
|
||||||
validator=GroupMembershipValidator([AccountGroup.DOMAIN_ADMIN]),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
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.
|
||||||
@@ -109,6 +98,19 @@ class DomainController(SimComponent):
|
|||||||
state.update({"accounts": {uuid: acct.describe_state() for uuid, acct in self.accounts.items()}})
|
state.update({"accounts": {uuid: acct.describe_state() for uuid, acct in self.accounts.items()}})
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
def _init_action_manager(self) -> ActionManager:
|
||||||
|
am = super()._init_action_manager()
|
||||||
|
# Action 'account' matches requests like:
|
||||||
|
# ['account', '<account-uuid>', *account_action]
|
||||||
|
am.add_action(
|
||||||
|
"account",
|
||||||
|
Action(
|
||||||
|
func=lambda request, context: self.accounts[request.pop(0)].apply_action(request, context),
|
||||||
|
validator=GroupMembershipValidator([AccountGroup.DOMAIN_ADMIN]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return am
|
||||||
|
|
||||||
def _register_account(self, account: Account) -> None:
|
def _register_account(self, account: Account) -> None:
|
||||||
"""TODO."""
|
"""TODO."""
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -17,15 +17,6 @@ class Network(SimComponent):
|
|||||||
"""Initialise the network."""
|
"""Initialise the network."""
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.action_manager = ActionManager()
|
|
||||||
self.action_manager.add_action(
|
|
||||||
"node",
|
|
||||||
Action(
|
|
||||||
func=lambda request, context: self.nodes[request.pop(0)].apply_action(request, context),
|
|
||||||
validator=AllowAllValidator(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
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.
|
||||||
@@ -44,6 +35,18 @@ class Network(SimComponent):
|
|||||||
)
|
)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
def _init_action_manager(self) -> ActionManager:
|
||||||
|
am = super()._init_action_manager()
|
||||||
|
|
||||||
|
am.add_action(
|
||||||
|
"node",
|
||||||
|
Action(
|
||||||
|
func=lambda request, context: self.nodes[request.pop(0)].apply_action(request, context),
|
||||||
|
validator=AllowAllValidator(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return am
|
||||||
|
|
||||||
def add_node(self, node: Node) -> None:
|
def add_node(self, node: Node) -> None:
|
||||||
"""
|
"""
|
||||||
Add an existing node to the network.
|
Add an existing node to the network.
|
||||||
|
|||||||
@@ -21,22 +21,6 @@ class Simulation(SimComponent):
|
|||||||
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.action_manager = ActionManager()
|
|
||||||
# pass through network actions to the network objects
|
|
||||||
self.action_manager.add_action(
|
|
||||||
"network",
|
|
||||||
Action(
|
|
||||||
func=lambda request, context: self.network.apply_action(request, context), validator=AllowAllValidator()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
# pass through domain actions to the domain object
|
|
||||||
self.action_manager.add_action(
|
|
||||||
"domain",
|
|
||||||
Action(
|
|
||||||
func=lambda request, context: self.domain.apply_action(request, context), validator=AllowAllValidator()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
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.
|
||||||
@@ -54,3 +38,21 @@ class Simulation(SimComponent):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
def _init_action_manager(self) -> ActionManager:
|
||||||
|
am = super()._init_action_manager()
|
||||||
|
# pass through network actions to the network objects
|
||||||
|
am.add_action(
|
||||||
|
"network",
|
||||||
|
Action(
|
||||||
|
func=lambda request, context: self.network.apply_action(request, context), validator=AllowAllValidator()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
# pass through domain actions to the domain object
|
||||||
|
am.add_action(
|
||||||
|
"domain",
|
||||||
|
Action(
|
||||||
|
func=lambda request, context: self.domain.apply_action(request, context), validator=AllowAllValidator()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return am
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Dict, List, Set
|
from typing import Any, Dict, Set
|
||||||
|
|
||||||
from primaite.simulator.system.software import IOSoftware
|
from primaite.simulator.system.software import IOSoftware
|
||||||
|
|
||||||
@@ -53,14 +53,6 @@ class Application(IOSoftware):
|
|||||||
)
|
)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def apply_action(self, action: List[str]) -> None:
|
|
||||||
"""
|
|
||||||
Applies a list of actions to the Application.
|
|
||||||
|
|
||||||
:param action: A list of actions to apply.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def reset_component_for_episode(self, episode: int):
|
def reset_component_for_episode(self, episode: int):
|
||||||
"""
|
"""
|
||||||
Resets the Application component for a new episode.
|
Resets the Application component for a new episode.
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ class DatabaseService(Service):
|
|||||||
:param folder_name: Name of the folder which will be setup to hold the db files, defaults to "database"
|
:param folder_name: Name of the folder which will be setup to hold the db files, defaults to "database"
|
||||||
:type folder_name: str, optional
|
:type folder_name: str, optional
|
||||||
"""
|
"""
|
||||||
|
# note that this parent.file_system.create_folder call in the future will be authenticated by using permissions
|
||||||
|
# handler. This permission will be granted based on service account given to the database service.
|
||||||
folder = self.parent.file_system.create_folder(folder_name)
|
folder = self.parent.file_system.create_folder(folder_name)
|
||||||
self.parent.file_system.create_file("db_primary_store", db_size, FileSystemFileType.MDF, folder=folder)
|
self.parent.file_system.create_file("db_primary_store", db_size, FileSystemFileType.MDF, folder=folder)
|
||||||
self.parent.file_system.create_file("db_transaction_log", "1", FileSystemFileType.LDF, folder=folder)
|
self.parent.file_system.create_file("db_transaction_log", "1", FileSystemFileType.LDF, folder=folder)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from abc import abstractmethod
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
from primaite.simulator.network.hardware.base import Node
|
|
||||||
from primaite.simulator.system.software import IOSoftware
|
from primaite.simulator.system.software import IOSoftware
|
||||||
|
|
||||||
|
|
||||||
@@ -33,17 +32,6 @@ class Service(IOSoftware):
|
|||||||
operating_state: ServiceOperatingState
|
operating_state: ServiceOperatingState
|
||||||
"The current operating state of the Service."
|
"The current operating state of the Service."
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self, parent_node: Node, **kwargs):
|
|
||||||
"""Create the service on a node.
|
|
||||||
|
|
||||||
:param parent_node: The node on which this service runs.
|
|
||||||
:type parent_node: Node
|
|
||||||
"""
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.parent: Node = parent_node
|
|
||||||
self.parent.software_manager.add_service(self)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def describe_state(self) -> Dict:
|
def describe_state(self) -> Dict:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Dict, List, Set
|
from typing import Any, Dict, Set
|
||||||
|
|
||||||
from primaite.simulator.core import SimComponent
|
from primaite.simulator.core import SimComponent
|
||||||
from primaite.simulator.network.transmission.transport_layer import Port
|
from primaite.simulator.network.transmission.transport_layer import Port
|
||||||
@@ -98,17 +98,6 @@ class Software(SimComponent):
|
|||||||
)
|
)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def apply_action(self, action: List[str]) -> None:
|
|
||||||
"""
|
|
||||||
Applies a list of actions to the software.
|
|
||||||
|
|
||||||
The specifics of how these actions are applied should be implemented in subclasses.
|
|
||||||
|
|
||||||
:param action: A list of actions to apply.
|
|
||||||
:type action: List[str]
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def reset_component_for_episode(self, episode: int):
|
def reset_component_for_episode(self, episode: int):
|
||||||
"""
|
"""
|
||||||
Resets the software component for a new episode.
|
Resets the software component for a new episode.
|
||||||
@@ -119,6 +108,19 @@ class Software(SimComponent):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def set_health_state(self, health_state: SoftwareHealthState) -> None:
|
||||||
|
"""
|
||||||
|
Assign a new health state to this software.
|
||||||
|
|
||||||
|
Note: this should only be possible when the software is currently running, but the software base class has no
|
||||||
|
operating state, only subclasses do. So subclasses will need to implement this check. TODO: check if this should
|
||||||
|
be changed so that the base Software class has a running attr.
|
||||||
|
|
||||||
|
:param health_state: New health state to assign to the software
|
||||||
|
:type health_state: SoftwareHealthState
|
||||||
|
"""
|
||||||
|
self.health_state_actual = health_state
|
||||||
|
|
||||||
|
|
||||||
class IOSoftware(Software):
|
class IOSoftware(Software):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user