Apply bugfix 2151

This commit is contained in:
Marek Wolan
2024-01-11 10:49:32 +00:00
parent e57c240b9b
commit d2a2472e5f
8 changed files with 40 additions and 34 deletions

View File

@@ -38,9 +38,6 @@ class Application(IOSoftware):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.health_state_visible = SoftwareHealthState.UNUSED
self.health_state_actual = SoftwareHealthState.UNUSED
def set_original_state(self): def set_original_state(self):
"""Sets the original state.""" """Sets the original state."""
super().set_original_state() super().set_original_state()
@@ -95,6 +92,7 @@ class Application(IOSoftware):
if self.operating_state == ApplicationOperatingState.CLOSED: if self.operating_state == ApplicationOperatingState.CLOSED:
self.sys_log.info(f"Running Application {self.name}") self.sys_log.info(f"Running Application {self.name}")
self.operating_state = ApplicationOperatingState.RUNNING self.operating_state = ApplicationOperatingState.RUNNING
# set software health state to GOOD if initially set to UNUSED
if self.health_state_actual == SoftwareHealthState.UNUSED: if self.health_state_actual == SoftwareHealthState.UNUSED:
self.set_health_state(SoftwareHealthState.GOOD) self.set_health_state(SoftwareHealthState.GOOD)

View File

@@ -1,7 +1,7 @@
import shutil import shutil
from abc import ABC from abc import ABC
from ipaddress import IPv4Address from ipaddress import IPv4Address
from typing import Optional from typing import Dict, Optional
from primaite.simulator.file_system.file_system import File from primaite.simulator.file_system.file_system import File
from primaite.simulator.network.protocols.ftp import FTPCommand, FTPPacket, FTPStatusCode from primaite.simulator.network.protocols.ftp import FTPCommand, FTPPacket, FTPStatusCode
@@ -16,6 +16,10 @@ class FTPServiceABC(Service, ABC):
Contains shared methods between both classes. Contains shared methods between both classes.
""" """
def describe_state(self) -> Dict:
"""Returns a Dict of the FTPService state."""
return super().describe_state()
def _process_ftp_command(self, payload: FTPPacket, session_id: Optional[str] = None, **kwargs) -> FTPPacket: def _process_ftp_command(self, payload: FTPPacket, session_id: Optional[str] = None, **kwargs) -> FTPPacket:
""" """
Process the command in the FTP Packet. Process the command in the FTP Packet.

View File

@@ -1,3 +1,4 @@
from abc import abstractmethod
from enum import Enum from enum import Enum
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
@@ -77,9 +78,6 @@ class Service(IOSoftware):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.health_state_visible = SoftwareHealthState.UNUSED
self.health_state_actual = SoftwareHealthState.UNUSED
def set_original_state(self): def set_original_state(self):
"""Sets the original state.""" """Sets the original state."""
super().set_original_state() super().set_original_state()
@@ -98,6 +96,7 @@ class Service(IOSoftware):
rm.add_request("enable", RequestType(func=lambda request, context: self.enable())) rm.add_request("enable", RequestType(func=lambda request, context: self.enable()))
return rm return rm
@abstractmethod
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.
@@ -118,7 +117,6 @@ class Service(IOSoftware):
if self.operating_state in [ServiceOperatingState.RUNNING, ServiceOperatingState.PAUSED]: if self.operating_state in [ServiceOperatingState.RUNNING, ServiceOperatingState.PAUSED]:
self.sys_log.info(f"Stopping service {self.name}") self.sys_log.info(f"Stopping service {self.name}")
self.operating_state = ServiceOperatingState.STOPPED self.operating_state = ServiceOperatingState.STOPPED
self.health_state_actual = SoftwareHealthState.UNUSED
def start(self, **kwargs) -> None: def start(self, **kwargs) -> None:
"""Start the service.""" """Start the service."""
@@ -129,42 +127,39 @@ class Service(IOSoftware):
if self.operating_state == ServiceOperatingState.STOPPED: if self.operating_state == ServiceOperatingState.STOPPED:
self.sys_log.info(f"Starting service {self.name}") self.sys_log.info(f"Starting service {self.name}")
self.operating_state = ServiceOperatingState.RUNNING self.operating_state = ServiceOperatingState.RUNNING
self.health_state_actual = SoftwareHealthState.GOOD # set software health state to GOOD if initially set to UNUSED
if self.health_state_actual == SoftwareHealthState.UNUSED:
self.set_health_state(SoftwareHealthState.GOOD)
def pause(self) -> None: def pause(self) -> None:
"""Pause the service.""" """Pause the service."""
if self.operating_state == ServiceOperatingState.RUNNING: if self.operating_state == ServiceOperatingState.RUNNING:
self.sys_log.info(f"Pausing service {self.name}") self.sys_log.info(f"Pausing service {self.name}")
self.operating_state = ServiceOperatingState.PAUSED self.operating_state = ServiceOperatingState.PAUSED
self.health_state_actual = SoftwareHealthState.OVERWHELMED
def resume(self) -> None: def resume(self) -> None:
"""Resume paused service.""" """Resume paused service."""
if self.operating_state == ServiceOperatingState.PAUSED: if self.operating_state == ServiceOperatingState.PAUSED:
self.sys_log.info(f"Resuming service {self.name}") self.sys_log.info(f"Resuming service {self.name}")
self.operating_state = ServiceOperatingState.RUNNING self.operating_state = ServiceOperatingState.RUNNING
self.health_state_actual = SoftwareHealthState.GOOD
def restart(self) -> None: def restart(self) -> None:
"""Restart running service.""" """Restart running service."""
if self.operating_state in [ServiceOperatingState.RUNNING, ServiceOperatingState.PAUSED]: if self.operating_state in [ServiceOperatingState.RUNNING, ServiceOperatingState.PAUSED]:
self.sys_log.info(f"Pausing service {self.name}") self.sys_log.info(f"Pausing service {self.name}")
self.operating_state = ServiceOperatingState.RESTARTING self.operating_state = ServiceOperatingState.RESTARTING
self.health_state_actual = SoftwareHealthState.OVERWHELMED
self.restart_countdown = self.restart_duration self.restart_countdown = self.restart_duration
def disable(self) -> None: def disable(self) -> None:
"""Disable the service.""" """Disable the service."""
self.sys_log.info(f"Disabling Application {self.name}") self.sys_log.info(f"Disabling Application {self.name}")
self.operating_state = ServiceOperatingState.DISABLED self.operating_state = ServiceOperatingState.DISABLED
self.health_state_actual = SoftwareHealthState.OVERWHELMED
def enable(self) -> None: def enable(self) -> None:
"""Enable the disabled service.""" """Enable the disabled service."""
if self.operating_state == ServiceOperatingState.DISABLED: if self.operating_state == ServiceOperatingState.DISABLED:
self.sys_log.info(f"Enabling Application {self.name}") self.sys_log.info(f"Enabling Application {self.name}")
self.operating_state = ServiceOperatingState.STOPPED self.operating_state = ServiceOperatingState.STOPPED
self.health_state_actual = SoftwareHealthState.OVERWHELMED
def apply_timestep(self, timestep: int) -> None: def apply_timestep(self, timestep: int) -> None:
""" """
@@ -181,5 +176,4 @@ class Service(IOSoftware):
if self.restart_countdown <= 0: if self.restart_countdown <= 0:
_LOGGER.debug(f"Restarting finished for service {self.name}") _LOGGER.debug(f"Restarting finished for service {self.name}")
self.operating_state = ServiceOperatingState.RUNNING self.operating_state = ServiceOperatingState.RUNNING
self.health_state_actual = SoftwareHealthState.GOOD
self.restart_countdown -= 1 self.restart_countdown -= 1

View File

@@ -69,9 +69,9 @@ class Software(SimComponent):
name: str name: str
"The name of the software." "The name of the software."
health_state_actual: SoftwareHealthState = SoftwareHealthState.GOOD health_state_actual: SoftwareHealthState = SoftwareHealthState.UNUSED
"The actual health state of the software." "The actual health state of the software."
health_state_visible: SoftwareHealthState = SoftwareHealthState.GOOD health_state_visible: SoftwareHealthState = SoftwareHealthState.UNUSED
"The health state of the software visible to the red agent." "The health state of the software visible to the red agent."
criticality: SoftwareCriticality = SoftwareCriticality.LOWEST criticality: SoftwareCriticality = SoftwareCriticality.LOWEST
"The criticality level of the software." "The criticality level of the software."
@@ -278,7 +278,7 @@ class IOSoftware(Software):
Returns true if the software can perform actions. Returns true if the software can perform actions.
""" """
if self.software_manager and self.software_manager.node.operating_state is not NodeOperatingState.ON: if self.software_manager and self.software_manager.node.operating_state != NodeOperatingState.ON:
_LOGGER.debug(f"{self.name} Error: {self.software_manager.node.hostname} is not online.") _LOGGER.debug(f"{self.name} Error: {self.software_manager.node.hostname} is not online.")
return False return False
return True return True

View File

@@ -40,6 +40,9 @@ from primaite.simulator.network.hardware.base import Link, Node
class TestService(Service): class TestService(Service):
"""Test Service class""" """Test Service class"""
def describe_state(self) -> Dict:
return super().describe_state()
def __init__(self, **kwargs): def __init__(self, **kwargs):
kwargs["name"] = "TestService" kwargs["name"] = "TestService"
kwargs["port"] = Port.HTTP kwargs["port"] = Port.HTTP
@@ -60,7 +63,7 @@ class TestApplication(Application):
super().__init__(**kwargs) super().__init__(**kwargs)
def describe_state(self) -> Dict: def describe_state(self) -> Dict:
pass return super().describe_state()
@pytest.fixture(scope="function") @pytest.fixture(scope="function")

View File

@@ -24,8 +24,8 @@ def populated_node(application_class) -> Tuple[Application, Computer]:
return app, computer return app, computer
def test_service_on_offline_node(application_class): def test_application_on_offline_node(application_class):
"""Test to check that the service cannot be interacted with when node it is on is off.""" """Test to check that the application cannot be interacted with when node it is on is off."""
computer: Computer = Computer( computer: Computer = Computer(
hostname="test_computer", hostname="test_computer",
ip_address="192.168.1.2", ip_address="192.168.1.2",
@@ -49,8 +49,8 @@ def test_service_on_offline_node(application_class):
assert app.operating_state is ApplicationOperatingState.CLOSED assert app.operating_state is ApplicationOperatingState.CLOSED
def test_server_turns_off_service(populated_node): def test_server_turns_off_application(populated_node):
"""Check that the service is turned off when the server is turned off""" """Check that the application is turned off when the server is turned off"""
app, computer = populated_node app, computer = populated_node
assert computer.operating_state is NodeOperatingState.ON assert computer.operating_state is NodeOperatingState.ON
@@ -65,8 +65,8 @@ def test_server_turns_off_service(populated_node):
assert app.operating_state is ApplicationOperatingState.CLOSED assert app.operating_state is ApplicationOperatingState.CLOSED
def test_service_cannot_be_turned_on_when_server_is_off(populated_node): def test_application_cannot_be_turned_on_when_server_is_off(populated_node):
"""Check that the service cannot be started when the server is off.""" """Check that the application cannot be started when the server is off."""
app, computer = populated_node app, computer = populated_node
assert computer.operating_state is NodeOperatingState.ON assert computer.operating_state is NodeOperatingState.ON
@@ -86,8 +86,8 @@ def test_service_cannot_be_turned_on_when_server_is_off(populated_node):
assert app.operating_state is ApplicationOperatingState.CLOSED assert app.operating_state is ApplicationOperatingState.CLOSED
def test_server_turns_on_service(populated_node): def test_server_turns_on_application(populated_node):
"""Check that turning on the server turns on service.""" """Check that turning on the server turns on application."""
app, computer = populated_node app, computer = populated_node
assert computer.operating_state is NodeOperatingState.ON assert computer.operating_state is NodeOperatingState.ON
@@ -109,13 +109,14 @@ def test_server_turns_on_service(populated_node):
assert computer.operating_state is NodeOperatingState.ON assert computer.operating_state is NodeOperatingState.ON
assert app.operating_state is ApplicationOperatingState.RUNNING assert app.operating_state is ApplicationOperatingState.RUNNING
computer.start_up_duration = 0
computer.shut_down_duration = 0
computer.power_off() computer.power_off()
for i in range(computer.start_up_duration + 1):
computer.apply_timestep(timestep=i)
assert computer.operating_state is NodeOperatingState.OFF assert computer.operating_state is NodeOperatingState.OFF
assert app.operating_state is ApplicationOperatingState.CLOSED assert app.operating_state is ApplicationOperatingState.CLOSED
computer.power_on() computer.power_on()
for i in range(computer.start_up_duration + 1):
computer.apply_timestep(timestep=i)
assert computer.operating_state is NodeOperatingState.ON assert computer.operating_state is NodeOperatingState.ON
assert app.operating_state is ApplicationOperatingState.RUNNING assert app.operating_state is ApplicationOperatingState.RUNNING

View File

@@ -117,13 +117,14 @@ def test_server_turns_on_service(populated_node):
assert server.operating_state is NodeOperatingState.ON assert server.operating_state is NodeOperatingState.ON
assert service.operating_state is ServiceOperatingState.RUNNING assert service.operating_state is ServiceOperatingState.RUNNING
server.start_up_duration = 0
server.shut_down_duration = 0
server.power_off() server.power_off()
for i in range(server.start_up_duration + 1):
server.apply_timestep(timestep=i)
assert server.operating_state is NodeOperatingState.OFF assert server.operating_state is NodeOperatingState.OFF
assert service.operating_state is ServiceOperatingState.STOPPED assert service.operating_state is ServiceOperatingState.STOPPED
server.power_on() server.power_on()
for i in range(server.start_up_duration + 1):
server.apply_timestep(timestep=i)
assert server.operating_state is NodeOperatingState.ON assert server.operating_state is NodeOperatingState.ON
assert service.operating_state is ServiceOperatingState.RUNNING assert service.operating_state is ServiceOperatingState.RUNNING

View File

@@ -1,5 +1,6 @@
import pytest import pytest
from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState
from primaite.simulator.network.hardware.nodes.server import Server from primaite.simulator.network.hardware.nodes.server import Server
from primaite.simulator.network.protocols.http import ( from primaite.simulator.network.protocols.http import (
HttpRequestMethod, HttpRequestMethod,
@@ -15,7 +16,11 @@ from primaite.simulator.system.services.web_server.web_server import WebServer
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def web_server() -> Server: def web_server() -> Server:
node = Server( node = Server(
hostname="web_server", ip_address="192.168.1.10", subnet_mask="255.255.255.0", default_gateway="192.168.1.1" hostname="web_server",
ip_address="192.168.1.10",
subnet_mask="255.255.255.0",
default_gateway="192.168.1.1",
operating_state=NodeOperatingState.ON,
) )
node.software_manager.install(software_class=WebServer) node.software_manager.install(software_class=WebServer)
node.software_manager.software.get("WebServer").start() node.software_manager.software.get("WebServer").start()