Apply bugfix 2151
This commit is contained in:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user