diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5996f98..adf24fdc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+### Changed
+- Removed the install/uninstall methods in the node class and made the software manager install/uninstall handle all of their functionality.
+
## [3.2.0] - 2024-07-18
@@ -27,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Frame `size` attribute now includes both core size and payload size in bytes
- The `speed` attribute of `NetworkInterface` has been changed from `int` to `float`
- Tidied up CHANGELOG
+- Enhanced `AirSpace` logic to block transmissions that would exceed the available capacity.
+- Updated `_can_transmit` function in `Link` to account for current load and total bandwidth capacity, ensuring transmissions do not exceed limits.
### Fixed
- Links and airspaces can no longer transmit data if this would exceed their bandwidth
diff --git a/benchmark/report.py b/benchmark/report.py
index 5eaaab9f..e1ff46b9 100644
--- a/benchmark/report.py
+++ b/benchmark/report.py
@@ -234,10 +234,7 @@ def _plot_av_s_per_100_steps_10_nodes(
"""
major_v = primaite.__version__.split(".")[0]
title = f"Performance of Minor and Bugfix Releases for Major Version {major_v}"
- subtitle = (
- f"Average Training Time per 100 Steps on 10 Nodes "
- f"(target: <= {PLOT_CONFIG['av_s_per_100_steps_10_nodes_benchmark_threshold']} seconds)"
- )
+ subtitle = "Average Training Time per 100 Steps on 10 Nodes "
title = f"{title}
{subtitle}"
layout = go.Layout(
@@ -250,10 +247,6 @@ def _plot_av_s_per_100_steps_10_nodes(
versions = sorted(list(version_times_dict.keys()))
times = [version_times_dict[version] for version in versions]
- av_s_per_100_steps_10_nodes_benchmark_threshold = PLOT_CONFIG["av_s_per_100_steps_10_nodes_benchmark_threshold"]
-
- # Calculate the appropriate maximum y-axis value
- max_y_axis_value = max(max(times), av_s_per_100_steps_10_nodes_benchmark_threshold) + 1
fig.add_trace(
go.Bar(
@@ -267,7 +260,6 @@ def _plot_av_s_per_100_steps_10_nodes(
fig.update_layout(
xaxis_title="PrimAITE Version",
yaxis_title="Avg Time per 100 Steps on 10 Nodes (seconds)",
- yaxis=dict(range=[0, max_y_axis_value]),
title=title,
)
diff --git a/benchmark/results/v3/PrimAITE Versions Learning Benchmark.png b/benchmark/results/v3/PrimAITE Versions Learning Benchmark.png
new file mode 100644
index 00000000..9884e2ec
Binary files /dev/null and b/benchmark/results/v3/PrimAITE Versions Learning Benchmark.png differ
diff --git a/benchmark/results/v3/v3.0.0/PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png b/benchmark/results/v3/v3.0.0/PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png
deleted file mode 100644
index 542f8f56..00000000
Binary files a/benchmark/results/v3/v3.0.0/PrimAITE Learning Benchmark of Minor and Bugfix Releases for Major Version 3.png and /dev/null differ
diff --git a/benchmark/results/v3/v3.0.0/PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png b/benchmark/results/v3/v3.0.0/PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png
deleted file mode 100644
index 05fa4f15..00000000
Binary files a/benchmark/results/v3/v3.0.0/PrimAITE Performance of Minor and Bugfix Releases for Major Version 3.png and /dev/null differ
diff --git a/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Benchmark Report.md b/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Benchmark Report.md
deleted file mode 100644
index c2cd6e78..00000000
--- a/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Benchmark Report.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# PrimAITE v3.0.0 Learning Benchmark
-## PrimAITE Dev Team
-### 2024-07-20
-
----
-## 1 Introduction
-PrimAITE v3.0.0 was benchmarked automatically upon release. Learning rate metrics were captured to be referenced during system-level testing and user acceptance testing (UAT).
-The benchmarking process consists of running 5 training session using the same config file. Each session trains an agent for 1000 episodes, with each episode consisting of 128 steps.
-The total reward per episode from each session is captured. This is then used to calculate an caverage total reward per episode from the 5 individual sessions for smoothing. Finally, a 25-widow rolling average of the average total reward per session is calculated for further smoothing.
-## 2 System Information
-### 2.1 Python
-**Version:** 3.10.14 (main, Apr 6 2024, 18:45:05) [GCC 9.4.0]
-### 2.2 System
-- **OS:** Linux
-- **OS Version:** #76~20.04.1-Ubuntu SMP Thu Jun 13 18:00:23 UTC 2024
-- **Machine:** x86_64
-- **Processor:** x86_64
-### 2.3 CPU
-- **Physical Cores:** 2
-- **Total Cores:** 4
-- **Max Frequency:** 0.00Mhz
-### 2.4 Memory
-- **Total:** 15.62GB
-- **Swap Total:** 0.00B
-## 3 Stats
-- **Total Sessions:** 5
-- **Total Episodes:** 5005
-- **Total Steps:** 640000
-- **Av Session Duration (s):** 1452.5910
-- **Av Step Duration (s):** 0.0454
-- **Av Duration per 100 Steps per 10 Nodes (s):** 4.5393
-## 4 Graphs
-### 4.1 v3.0.0 Learning Benchmark Plot
-
-### 4.2 Learning Benchmark of Minor and Bugfix Releases for Major Version 3
-
-### 4.3 Performance of Minor and Bugfix Releases for Major Version 3
-
diff --git a/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.pdf b/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.pdf
new file mode 100644
index 00000000..fceba624
Binary files /dev/null and b/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.pdf differ
diff --git a/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.png b/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.png
index b61c706a..c54dc354 100644
Binary files a/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.png and b/benchmark/results/v3/v3.0.0/PrimAITE v3.0.0 Learning Benchmark.png differ
diff --git a/benchmark/results/v3/v3.2.0/session_metadata/1.json b/benchmark/results/v3/v3.2.0/session_metadata/1.json
index 794f03e3..bfccfcdc 100644
--- a/benchmark/results/v3/v3.2.0/session_metadata/1.json
+++ b/benchmark/results/v3/v3.2.0/session_metadata/1.json
@@ -1006,4 +1006,4 @@
"999": 78.49999999999996,
"1000": 84.69999999999993
}
-}
\ No newline at end of file
+}
diff --git a/benchmark/results/v3/v3.2.0/session_metadata/2.json b/benchmark/results/v3/v3.2.0/session_metadata/2.json
index e48c34b9..c35b5ae6 100644
--- a/benchmark/results/v3/v3.2.0/session_metadata/2.json
+++ b/benchmark/results/v3/v3.2.0/session_metadata/2.json
@@ -1006,4 +1006,4 @@
"999": 97.59999999999975,
"1000": 103.34999999999978
}
-}
\ No newline at end of file
+}
diff --git a/benchmark/results/v3/v3.2.0/session_metadata/3.json b/benchmark/results/v3/v3.2.0/session_metadata/3.json
index 4e2d845c..342e0f7d 100644
--- a/benchmark/results/v3/v3.2.0/session_metadata/3.json
+++ b/benchmark/results/v3/v3.2.0/session_metadata/3.json
@@ -1006,4 +1006,4 @@
"999": 101.14999999999978,
"1000": 80.94999999999976
}
-}
\ No newline at end of file
+}
diff --git a/benchmark/results/v3/v3.2.0/session_metadata/4.json b/benchmark/results/v3/v3.2.0/session_metadata/4.json
index 6e03a18f..6aaf9ab8 100644
--- a/benchmark/results/v3/v3.2.0/session_metadata/4.json
+++ b/benchmark/results/v3/v3.2.0/session_metadata/4.json
@@ -1006,4 +1006,4 @@
"999": 118.0500000000001,
"1000": 77.95000000000005
}
-}
\ No newline at end of file
+}
diff --git a/benchmark/results/v3/v3.2.0/session_metadata/5.json b/benchmark/results/v3/v3.2.0/session_metadata/5.json
index ca7ad1e9..05cf76ed 100644
--- a/benchmark/results/v3/v3.2.0/session_metadata/5.json
+++ b/benchmark/results/v3/v3.2.0/session_metadata/5.json
@@ -1006,4 +1006,4 @@
"999": 55.849999999999916,
"1000": 96.95000000000007
}
-}
\ No newline at end of file
+}
diff --git a/benchmark/results/v3/v3.2.0/v3.2.0_benchmark_metadata.json b/benchmark/results/v3/v3.2.0/v3.2.0_benchmark_metadata.json
index 830e980e..111ae25f 100644
--- a/benchmark/results/v3/v3.2.0/v3.2.0_benchmark_metadata.json
+++ b/benchmark/results/v3/v3.2.0/v3.2.0_benchmark_metadata.json
@@ -7442,4 +7442,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/pyproject.toml b/pyproject.toml
index e29fd504..c9b7c062 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -52,7 +52,7 @@ license-files = ["LICENSE"]
[project.optional-dependencies]
rl = [
- "ray[rllib] >= 2.20.0, < 2.33",
+ "ray[rllib] >= 2.20.0, <2.33",
"tensorflow==2.12.0",
"stable-baselines3[extra]==2.1.0",
"sb3-contrib==2.1.0",
diff --git a/src/primaite/VERSION b/src/primaite/VERSION
index 944880fa..6d0e8e51 100644
--- a/src/primaite/VERSION
+++ b/src/primaite/VERSION
@@ -1 +1 @@
-3.2.0
+3.3.0-dev0
diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py
index 7a127601..2fd9f945 100644
--- a/src/primaite/simulator/network/hardware/base.py
+++ b/src/primaite/simulator/network/hardware/base.py
@@ -1455,74 +1455,6 @@ class Node(SimComponent):
else:
return
- def install_service(self, service: Service) -> None:
- """
- Install a service on this node.
-
- :param service: Service instance that has not been installed on any node yet.
- :type service: Service
- """
- if service in self:
- _LOGGER.warning(f"Can't add service {service.name} to node {self.hostname}. It's already installed.")
- return
- self.services[service.uuid] = service
- service.parent = self
- 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}")
- _LOGGER.debug(f"Added service {service.name} to node {self.hostname}")
- self._service_request_manager.add_request(service.name, RequestType(func=service._request_manager))
-
- def uninstall_service(self, service: Service) -> None:
- """
- Uninstall and completely remove service from this node.
-
- :param service: Service object that is currently associated with this node.
- :type service: Service
- """
- if service not in self:
- _LOGGER.warning(f"Can't remove service {service.name} from node {self.hostname}. It's not installed.")
- return
- service.uninstall() # Perform additional teardown, such as removing files or restarting the machine.
- self.services.pop(service.uuid)
- service.parent = None
- self.sys_log.info(f"Uninstalled service {service.name}")
- self._service_request_manager.remove_request(service.name)
-
- def install_application(self, application: Application) -> None:
- """
- Install an application on this node.
-
- :param application: Application instance that has not been installed on any node yet.
- :type application: Application
- """
- if application in self:
- _LOGGER.warning(
- f"Can't add application {application.name} to node {self.hostname}. It's already installed."
- )
- return
- self.applications[application.uuid] = application
- application.parent = self
- self.sys_log.info(f"Installed application {application.name}")
- _LOGGER.debug(f"Added application {application.name} to node {self.hostname}")
- self._application_request_manager.add_request(application.name, RequestType(func=application._request_manager))
-
- def uninstall_application(self, application: Application) -> None:
- """
- Uninstall and completely remove application from this node.
-
- :param application: Application object that is currently associated with this node.
- :type application: Application
- """
- if application not in self:
- _LOGGER.warning(
- f"Can't remove application {application.name} from node {self.hostname}. It's not installed."
- )
- return
- self.applications.pop(application.uuid)
- application.parent = None
- self.sys_log.info(f"Uninstalled application {application.name}")
- self._application_request_manager.remove_request(application.name)
-
def _shut_down_actions(self):
"""Actions to perform when the node is shut down."""
# Turn off all the services in the node
diff --git a/src/primaite/simulator/system/core/software_manager.py b/src/primaite/simulator/system/core/software_manager.py
index e2266c2d..9c4d7cf6 100644
--- a/src/primaite/simulator/system/core/software_manager.py
+++ b/src/primaite/simulator/system/core/software_manager.py
@@ -4,6 +4,7 @@ from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING, Union
from prettytable import MARKDOWN, PrettyTable
+from primaite.simulator.core import RequestType
from primaite.simulator.file_system.file_system import FileSystem
from primaite.simulator.network.transmission.data_link_layer import Frame
from primaite.simulator.network.transmission.network_layer import IPProtocol
@@ -20,9 +21,7 @@ if TYPE_CHECKING:
from primaite.simulator.system.services.arp.arp import ARP
from primaite.simulator.system.services.icmp.icmp import ICMP
-from typing import Type, TypeVar
-
-IOSoftwareClass = TypeVar("IOSoftwareClass", bound=IOSoftware)
+from typing import Type
class SoftwareManager:
@@ -51,7 +50,7 @@ class SoftwareManager:
self.node = parent_node
self.session_manager = session_manager
self.software: Dict[str, Union[Service, Application]] = {}
- self._software_class_to_name_map: Dict[Type[IOSoftwareClass], str] = {}
+ self._software_class_to_name_map: Dict[Type[IOSoftware], str] = {}
self.port_protocol_mapping: Dict[Tuple[Port, IPProtocol], Union[Service, Application]] = {}
self.sys_log: SysLog = sys_log
self.file_system: FileSystem = file_system
@@ -104,33 +103,34 @@ class SoftwareManager:
return True
return False
- def install(self, software_class: Type[IOSoftwareClass]):
+ def install(self, software_class: Type[IOSoftware]):
"""
Install an Application or Service.
:param software_class: The software class.
"""
- # TODO: Software manager and node itself both have an install method. Need to refactor to have more logical
- # separation of concerns.
if software_class in self._software_class_to_name_map:
self.sys_log.warning(f"Cannot install {software_class} as it is already installed")
return
software = software_class(
software_manager=self, sys_log=self.sys_log, file_system=self.file_system, dns_server=self.dns_server
)
+ software.parent = self.node
if isinstance(software, Application):
- software.install()
+ self.node.applications[software.uuid] = software
+ self.node._application_request_manager.add_request(
+ software.name, RequestType(func=software._request_manager)
+ )
+ elif isinstance(software, Service):
+ self.node.services[software.uuid] = software
+ self.node._service_request_manager.add_request(software.name, RequestType(func=software._request_manager))
+ software.install()
software.software_manager = self
self.software[software.name] = software
self.port_protocol_mapping[(software.port, software.protocol)] = software
if isinstance(software, Application):
software.operating_state = ApplicationOperatingState.CLOSED
-
- # add the software to the node's registry after it has been fully initialized
- if isinstance(software, Service):
- self.node.install_service(software)
- elif isinstance(software, Application):
- self.node.install_application(software)
+ self.node.sys_log.info(f"Installed {software.name}")
def uninstall(self, software_name: str):
"""
@@ -138,25 +138,31 @@ class SoftwareManager:
:param software_name: The software name.
"""
- if software_name in self.software:
- self.software[software_name].uninstall()
- software = self.software.pop(software_name) # noqa
- if isinstance(software, Application):
- self.node.uninstall_application(software)
- elif isinstance(software, Service):
- self.node.uninstall_service(software)
- for key, value in self.port_protocol_mapping.items():
- if value.name == software_name:
- self.port_protocol_mapping.pop(key)
- break
- for key, value in self._software_class_to_name_map.items():
- if value == software_name:
- self._software_class_to_name_map.pop(key)
- break
- del software
- self.sys_log.info(f"Uninstalled {software_name}")
+ if software_name not in self.software:
+ self.sys_log.error(f"Cannot uninstall {software_name} as it is not installed")
return
- self.sys_log.error(f"Cannot uninstall {software_name} as it is not installed")
+
+ self.software[software_name].uninstall()
+ software = self.software.pop(software_name) # noqa
+ if isinstance(software, Application):
+ self.node.applications.pop(software.uuid)
+ self.node._application_request_manager.remove_request(software.name)
+ elif isinstance(software, Service):
+ self.node.services.pop(software.uuid)
+ software.uninstall()
+ self.node._service_request_manager.remove_request(software.name)
+ software.parent = None
+ for key, value in self.port_protocol_mapping.items():
+ if value.name == software_name:
+ self.port_protocol_mapping.pop(key)
+ break
+ for key, value in self._software_class_to_name_map.items():
+ if value == software_name:
+ self._software_class_to_name_map.pop(key)
+ break
+ del software
+ self.sys_log.info(f"Uninstalled {software_name}")
+ return
def send_internal_payload(self, target_software: str, payload: Any):
"""
diff --git a/tests/conftest.py b/tests/conftest.py
index 54519e2b..ca704461 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -37,14 +37,14 @@ ACTION_SPACE_NODE_ACTION_VALUES = 1
_LOGGER = getLogger(__name__)
-class TestService(Service):
+class DummyService(Service):
"""Test Service class"""
def describe_state(self) -> Dict:
return super().describe_state()
def __init__(self, **kwargs):
- kwargs["name"] = "TestService"
+ kwargs["name"] = "DummyService"
kwargs["port"] = Port.HTTP
kwargs["protocol"] = IPProtocol.TCP
super().__init__(**kwargs)
@@ -75,15 +75,15 @@ def uc2_network() -> Network:
@pytest.fixture(scope="function")
-def service(file_system) -> TestService:
- return TestService(
- name="TestService", port=Port.ARP, file_system=file_system, sys_log=SysLog(hostname="test_service")
+def service(file_system) -> DummyService:
+ return DummyService(
+ name="DummyService", port=Port.ARP, file_system=file_system, sys_log=SysLog(hostname="dummy_service")
)
@pytest.fixture(scope="function")
def service_class():
- return TestService
+ return DummyService
@pytest.fixture(scope="function")
diff --git a/tests/integration_tests/component_creation/test_action_integration.py b/tests/integration_tests/component_creation/test_action_integration.py
index a6f09436..7bdc80fc 100644
--- a/tests/integration_tests/component_creation/test_action_integration.py
+++ b/tests/integration_tests/component_creation/test_action_integration.py
@@ -22,8 +22,7 @@ def test_passing_actions_down(monkeypatch) -> None:
for n in [pc1, pc2, srv, s1]:
sim.network.add_node(n)
- database_service = DatabaseService(file_system=srv.file_system)
- srv.install_service(database_service)
+ srv.software_manager.install(DatabaseService)
downloads_folder = pc1.file_system.create_folder("downloads")
pc1.file_system.create_file("bermuda_triangle.png", folder_name="downloads")
diff --git a/tests/integration_tests/system/test_service_on_node.py b/tests/integration_tests/system/test_service_on_node.py
index 15dbaf1d..cf9728ce 100644
--- a/tests/integration_tests/system/test_service_on_node.py
+++ b/tests/integration_tests/system/test_service_on_node.py
@@ -23,7 +23,7 @@ def populated_node(
server.power_on()
server.software_manager.install(service_class)
- service = server.software_manager.software.get("TestService")
+ service = server.software_manager.software.get("DummyService")
service.start()
return server, service
@@ -42,7 +42,7 @@ def test_service_on_offline_node(service_class):
computer.power_on()
computer.software_manager.install(service_class)
- service: Service = computer.software_manager.software.get("TestService")
+ service: Service = computer.software_manager.software.get("DummyService")
computer.power_off()
diff --git a/tests/integration_tests/test_simulation/test_request_response.py b/tests/integration_tests/test_simulation/test_request_response.py
index a9f0b58d..95634cf1 100644
--- a/tests/integration_tests/test_simulation/test_request_response.py
+++ b/tests/integration_tests/test_simulation/test_request_response.py
@@ -13,7 +13,7 @@ from primaite.simulator.network.hardware.node_operating_state import NodeOperati
from primaite.simulator.network.hardware.nodes.host.host_node import HostNode
from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router
from primaite.simulator.network.transmission.transport_layer import Port
-from tests.conftest import DummyApplication, TestService
+from tests.conftest import DummyApplication, DummyService
def test_successful_node_file_system_creation_request(example_network):
@@ -61,7 +61,7 @@ def test_successful_application_requests(example_network):
def test_successful_service_requests(example_network):
net = example_network
server_1 = net.get_node_by_hostname("server_1")
- server_1.software_manager.install(TestService)
+ server_1.software_manager.install(DummyService)
# Careful: the order here is important, for example we cannot run "stop" unless we run "start" first
for verb in [
@@ -77,7 +77,7 @@ def test_successful_service_requests(example_network):
"scan",
"fix",
]:
- resp_1 = net.apply_request(["node", "server_1", "service", "TestService", verb])
+ resp_1 = net.apply_request(["node", "server_1", "service", "DummyService", verb])
assert resp_1 == RequestResponse(status="success", data={})
server_1.apply_timestep(timestep=1)
server_1.apply_timestep(timestep=1)
diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py
index 9b37ac80..44c5c781 100644
--- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py
+++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py
@@ -7,6 +7,7 @@ from primaite.simulator.file_system.folder import Folder
from primaite.simulator.network.hardware.base import Node, NodeOperatingState
from primaite.simulator.network.hardware.nodes.host.computer import Computer
from primaite.simulator.system.software import SoftwareHealthState
+from tests.conftest import DummyApplication, DummyService
@pytest.fixture
@@ -47,7 +48,7 @@ def test_node_shutdown(node):
assert node.operating_state == NodeOperatingState.OFF
-def test_node_os_scan(node, service, application):
+def test_node_os_scan(node):
"""Test OS Scanning."""
node.operating_state = NodeOperatingState.ON
@@ -55,13 +56,15 @@ def test_node_os_scan(node, service, application):
# TODO implement processes
# add services to node
+ node.software_manager.install(DummyService)
+ service = node.software_manager.software.get("DummyService")
service.set_health_state(SoftwareHealthState.COMPROMISED)
- node.install_service(service=service)
assert service.health_state_visible == SoftwareHealthState.UNUSED
# add application to node
+ node.software_manager.install(DummyApplication)
+ application = node.software_manager.software.get("DummyApplication")
application.set_health_state(SoftwareHealthState.COMPROMISED)
- node.install_application(application=application)
assert application.health_state_visible == SoftwareHealthState.UNUSED
# add folder and file to node
@@ -91,7 +94,7 @@ def test_node_os_scan(node, service, application):
assert file2.visible_health_status == FileSystemItemHealthStatus.CORRUPT
-def test_node_red_scan(node, service, application):
+def test_node_red_scan(node):
"""Test revealing to red"""
node.operating_state = NodeOperatingState.ON
@@ -99,12 +102,14 @@ def test_node_red_scan(node, service, application):
# TODO implement processes
# add services to node
- node.install_service(service=service)
+ node.software_manager.install(DummyService)
+ service = node.software_manager.software.get("DummyService")
assert service.revealed_to_red is False
# add application to node
+ node.software_manager.install(DummyApplication)
+ application = node.software_manager.software.get("DummyApplication")
application.set_health_state(SoftwareHealthState.COMPROMISED)
- node.install_application(application=application)
assert application.revealed_to_red is False
# add folder and file to node