Merged PR 609: fix instantiation of network nodes

This commit is contained in:
Marek Wolan
2025-02-18 11:05:16 +00:00
12 changed files with 33 additions and 29 deletions

View File

@@ -449,10 +449,8 @@ class IPWirelessNetworkInterface(WirelessNetworkInterface, Layer3Interface, ABC)
`default_gateway_hello` method is not defined, ignoring such errors to proceed without interruption.
"""
super().enable()
try:
if hasattr(self._connected_node, "default_gateway_hello"):
self._connected_node.default_gateway_hello()
except AttributeError:
pass
@abstractmethod
def receive_frame(self, frame: Frame) -> bool:

View File

@@ -155,7 +155,12 @@ class OfficeLANAdder(NetworkNodeAdder, discriminator="office-lan"):
# Create a core switch if more than one edge switch is needed
if num_of_switches > 1:
core_switch = Switch.from_config(
config={"type": "switch", "hostname": f"switch_core_{config.lan_name}", "start_up_duration": 0}
config={
"type": "switch",
"hostname": f"switch_core_{config.lan_name}",
"start_up_duration": 0,
"num_ports": 24,
}
)
core_switch.power_on()
network.add_node(core_switch)
@@ -183,7 +188,12 @@ class OfficeLANAdder(NetworkNodeAdder, discriminator="office-lan"):
switch_port = 0
switch_n = 1
switch = Switch.from_config(
config={"type": "switch", "hostname": f"switch_edge_{switch_n}_{config.lan_name}", "start_up_duration": 0}
config={
"type": "switch",
"hostname": f"switch_edge_{switch_n}_{config.lan_name}",
"start_up_duration": 0,
"num_ports": 24,
}
)
switch.power_on()
network.add_node(switch)
@@ -207,6 +217,7 @@ class OfficeLANAdder(NetworkNodeAdder, discriminator="office-lan"):
"type": "switch",
"hostname": f"switch_edge_{switch_n}_{config.lan_name}",
"start_up_duration": 0,
"num_ports": 24,
}
)
switch.power_on()

View File

@@ -639,10 +639,8 @@ class IPWiredNetworkInterface(WiredNetworkInterface, Layer3Interface, ABC):
`default_gateway_hello` method is not defined, ignoring such errors to proceed without interruption.
"""
super().enable()
try:
if hasattr(self._connected_node, "default_gateway_hello"):
self._connected_node.default_gateway_hello()
except AttributeError:
pass
return True
@abstractmethod

View File

@@ -333,7 +333,7 @@ class HostNode(Node, discriminator="host-node"):
class ConfigSchema(Node.ConfigSchema):
"""Configuration Schema for HostNode class."""
type: Literal["host-node"]
type: Literal["host-node"] = "host-node"
hostname: str = "HostNode"
subnet_mask: IPV4Address = "255.255.255.0"
ip_address: IPV4Address
@@ -375,7 +375,7 @@ class HostNode(Node, discriminator="host-node"):
This method is invoked to ensure the host node can communicate with its default gateway, primarily to confirm
network connectivity and populate the ARP cache with the gateway's MAC address.
"""
if self.operating_state == NodeOperatingState.ON and self.default_gateway:
if self.operating_state == NodeOperatingState.ON and self.config.default_gateway:
self.software_manager.arp.get_default_gateway_mac_address()
def receive_frame(self, frame: Frame, from_network_interface: NIC):

View File

@@ -1351,7 +1351,6 @@ class Router(NetworkNode, discriminator="router"):
:return: A dictionary representing the current state.
"""
state = super().describe_state()
state["num_ports"] = self.config.num_ports
state["acl"] = self.acl.describe_state()
return state

View File

@@ -103,8 +103,8 @@ class Switch(NetworkNode, discriminator="switch"):
type: Literal["switch"] = "switch"
hostname: str = "Switch"
num_ports: int = 24
"The number of ports on the switch. Default is 24."
num_ports: int = 8
"The number of ports on the switch."
config: ConfigSchema = Field(default_factory=lambda: Switch.ConfigSchema())
@@ -139,7 +139,6 @@ class Switch(NetworkNode, discriminator="switch"):
"""
state = super().describe_state()
state["ports"] = {port_num: port.describe_state() for port_num, port in self.network_interface.items()}
state["num_ports"] = self.config.num_ports # redundant?
state["mac_address_table"] = {mac: port.port_num for mac, port in self.mac_address_table.items()}
return state

View File

@@ -137,8 +137,8 @@ class ARP(Service, discriminator="arp"):
break
if use_default_gateway:
if self.software_manager.node.default_gateway:
target_ip_address = self.software_manager.node.default_gateway
if self.software_manager.node.config.default_gateway:
target_ip_address = self.software_manager.node.config.default_gateway
else:
return

View File

@@ -82,7 +82,7 @@ class Software(SimComponent, ABC):
"""Configurable options for all software."""
model_config = ConfigDict(extra="forbid")
starting_health_state: SoftwareHealthState = SoftwareHealthState.UNUSED
starting_health_state: SoftwareHealthState = SoftwareHealthState.GOOD
criticality: SoftwareCriticality = SoftwareCriticality.LOWEST
fixing_duration: int = 2

View File

@@ -17,4 +17,3 @@ def switch() -> Switch:
def test_describe_state(switch):
state = switch.describe_state()
assert len(state.get("ports")) is 8
assert state.get("num_ports") is 8

View File

@@ -18,7 +18,7 @@ def test_scan(application):
def test_run_application(application):
assert application.operating_state == ApplicationOperatingState.CLOSED
assert application.health_state_actual == SoftwareHealthState.UNUSED
assert application.health_state_actual == SoftwareHealthState.GOOD
application.run()
assert application.operating_state == ApplicationOperatingState.RUNNING
@@ -37,9 +37,9 @@ def test_close_application(application):
def test_application_describe_states(application):
assert application.operating_state == ApplicationOperatingState.CLOSED
assert application.health_state_actual == SoftwareHealthState.UNUSED
assert application.health_state_actual == SoftwareHealthState.GOOD
assert SoftwareHealthState.UNUSED.value == application.describe_state().get("health_state_actual")
assert SoftwareHealthState.GOOD.value == application.describe_state().get("health_state_actual")
application.run()
assert SoftwareHealthState.GOOD.value == application.describe_state().get("health_state_actual")

View File

@@ -22,7 +22,7 @@ def test_scan(service):
def test_start_service(service):
assert service.operating_state == ServiceOperatingState.STOPPED
assert service.health_state_actual == SoftwareHealthState.UNUSED
assert service.health_state_actual == SoftwareHealthState.GOOD
service.start()
assert service.operating_state == ServiceOperatingState.RUNNING
@@ -43,7 +43,7 @@ def test_pause_and_resume_service(service):
assert service.operating_state == ServiceOperatingState.STOPPED
service.resume()
assert service.operating_state == ServiceOperatingState.STOPPED
assert service.health_state_actual == SoftwareHealthState.UNUSED
assert service.health_state_actual == SoftwareHealthState.GOOD
service.start()
assert service.health_state_actual == SoftwareHealthState.GOOD
@@ -58,11 +58,11 @@ def test_pause_and_resume_service(service):
def test_restart(service):
assert service.operating_state == ServiceOperatingState.STOPPED
assert service.health_state_actual == SoftwareHealthState.UNUSED
assert service.health_state_actual == SoftwareHealthState.GOOD
service.restart()
# Service is STOPPED. Restart will only work if the service was PAUSED or RUNNING
assert service.operating_state == ServiceOperatingState.STOPPED
assert service.health_state_actual == SoftwareHealthState.UNUSED
assert service.health_state_actual == SoftwareHealthState.GOOD
service.start()
assert service.operating_state == ServiceOperatingState.RUNNING
@@ -157,11 +157,11 @@ def test_service_fixing(service):
def test_enable_disable(service):
service.disable()
assert service.operating_state == ServiceOperatingState.DISABLED
assert service.health_state_actual == SoftwareHealthState.UNUSED
assert service.health_state_actual == SoftwareHealthState.GOOD
service.enable()
assert service.operating_state == ServiceOperatingState.STOPPED
assert service.health_state_actual == SoftwareHealthState.UNUSED
assert service.health_state_actual == SoftwareHealthState.GOOD
def test_overwhelm_service(service):

View File

@@ -39,6 +39,6 @@ def test_software_creation(software):
def test_software_set_health_state(software):
assert software.health_state_actual == SoftwareHealthState.UNUSED
software.set_health_state(SoftwareHealthState.GOOD)
assert software.health_state_actual == SoftwareHealthState.GOOD
software.set_health_state(SoftwareHealthState.COMPROMISED)
assert software.health_state_actual == SoftwareHealthState.COMPROMISED