bugfix - Make node schemas stricter
This commit is contained in:
@@ -102,8 +102,7 @@ simulation:
|
|||||||
subnet_mask: 255.255.255.252
|
subnet_mask: 255.255.255.252
|
||||||
default_gateway: 8.8.8.1
|
default_gateway: 8.8.8.1
|
||||||
services:
|
services:
|
||||||
- ref: dns_server
|
- type: dns-server
|
||||||
type: dns-server
|
|
||||||
options:
|
options:
|
||||||
domain_mapping:
|
domain_mapping:
|
||||||
sometech.ai: 94.10.180.6
|
sometech.ai: 94.10.180.6
|
||||||
@@ -196,8 +195,7 @@ simulation:
|
|||||||
default_gateway: 94.10.180.5
|
default_gateway: 94.10.180.5
|
||||||
dns_server: 8.8.8.2
|
dns_server: 8.8.8.2
|
||||||
services:
|
services:
|
||||||
- ref: web_server
|
- type: web-server
|
||||||
type: web-server
|
|
||||||
applications:
|
applications:
|
||||||
- type: database-client
|
- type: database-client
|
||||||
options:
|
options:
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from primaite.simulator.network.creation import NetworkNodeAdder
|
|||||||
from primaite.simulator.network.hardware.base import NetworkInterface, Node, NodeOperatingState, UserManager
|
from primaite.simulator.network.hardware.base import NetworkInterface, Node, NodeOperatingState, UserManager
|
||||||
from primaite.simulator.network.hardware.nodes.host.host_node import NIC
|
from primaite.simulator.network.hardware.nodes.host.host_node import NIC
|
||||||
from primaite.simulator.network.hardware.nodes.network.switch import Switch
|
from primaite.simulator.network.hardware.nodes.network.switch import Switch
|
||||||
|
from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter
|
||||||
from primaite.simulator.network.nmne import NMNEConfig
|
from primaite.simulator.network.nmne import NMNEConfig
|
||||||
from primaite.simulator.sim_container import Simulation
|
from primaite.simulator.sim_container import Simulation
|
||||||
from primaite.simulator.system.applications.application import Application
|
from primaite.simulator.system.applications.application import Application
|
||||||
@@ -268,9 +269,11 @@ class PrimaiteGame:
|
|||||||
|
|
||||||
new_node = None
|
new_node = None
|
||||||
if n_type in Node._registry:
|
if n_type in Node._registry:
|
||||||
if n_type == "wireless-router":
|
n_class = Node._registry[n_type]
|
||||||
node_cfg["airspace"] = net.airspace
|
if issubclass(n_class, WirelessRouter):
|
||||||
new_node = Node._registry[n_type].from_config(config=node_cfg)
|
new_node = n_class(config=n_class.ConfigSchema(**node_cfg), airspace=net.airspace)
|
||||||
|
else:
|
||||||
|
new_node = Node._registry[n_type].from_config(config=node_cfg)
|
||||||
else:
|
else:
|
||||||
msg = f"invalid node type {n_type} in config"
|
msg = f"invalid node type {n_type} in config"
|
||||||
_LOGGER.error(msg)
|
_LOGGER.error(msg)
|
||||||
|
|||||||
@@ -1529,9 +1529,11 @@ class Node(SimComponent, ABC):
|
|||||||
class ConfigSchema(BaseModel, ABC):
|
class ConfigSchema(BaseModel, ABC):
|
||||||
"""Configuration Schema for Node based classes."""
|
"""Configuration Schema for Node based classes."""
|
||||||
|
|
||||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
|
||||||
"""Configure pydantic to allow arbitrary types, let the instance have attributes not present in the model."""
|
"""Configure pydantic to allow arbitrary types, let the instance have attributes not present in the model."""
|
||||||
|
|
||||||
|
type: str
|
||||||
|
|
||||||
hostname: str
|
hostname: str
|
||||||
"The node hostname on the network."
|
"The node hostname on the network."
|
||||||
|
|
||||||
@@ -1570,6 +1572,8 @@ class Node(SimComponent, ABC):
|
|||||||
|
|
||||||
operating_state: Any = None
|
operating_state: Any = None
|
||||||
|
|
||||||
|
users: Any = None # Temporary to appease "extra=forbid"
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: Node.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: Node.ConfigSchema())
|
||||||
"""Configuration items within Node"""
|
"""Configuration items within Node"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from typing import ClassVar, Dict
|
from typing import ClassVar, Dict, Literal
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
@@ -40,6 +40,7 @@ class Computer(HostNode, discriminator="computer"):
|
|||||||
class ConfigSchema(HostNode.ConfigSchema):
|
class ConfigSchema(HostNode.ConfigSchema):
|
||||||
"""Configuration Schema for Computer class."""
|
"""Configuration Schema for Computer class."""
|
||||||
|
|
||||||
|
type: Literal["computer"] = "computer"
|
||||||
hostname: str = "Computer"
|
hostname: str = "Computer"
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: Computer.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: Computer.ConfigSchema())
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
from typing import Any, ClassVar, Dict, Optional
|
from typing import Any, ClassVar, Dict, Literal, Optional
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
@@ -333,9 +333,14 @@ class HostNode(Node, discriminator="host-node"):
|
|||||||
class ConfigSchema(Node.ConfigSchema):
|
class ConfigSchema(Node.ConfigSchema):
|
||||||
"""Configuration Schema for HostNode class."""
|
"""Configuration Schema for HostNode class."""
|
||||||
|
|
||||||
|
type: Literal["host-node"]
|
||||||
hostname: str = "HostNode"
|
hostname: str = "HostNode"
|
||||||
subnet_mask: IPV4Address = "255.255.255.0"
|
subnet_mask: IPV4Address = "255.255.255.0"
|
||||||
ip_address: IPV4Address
|
ip_address: IPV4Address
|
||||||
|
services: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
applications: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
folders: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
network_interfaces: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: HostNode.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: HostNode.ConfigSchema())
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
|
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
from primaite.simulator.network.hardware.nodes.host.host_node import HostNode
|
from primaite.simulator.network.hardware.nodes.host.host_node import HostNode
|
||||||
@@ -36,6 +38,7 @@ class Server(HostNode, discriminator="server"):
|
|||||||
class ConfigSchema(HostNode.ConfigSchema):
|
class ConfigSchema(HostNode.ConfigSchema):
|
||||||
"""Configuration Schema for Server class."""
|
"""Configuration Schema for Server class."""
|
||||||
|
|
||||||
|
type: Literal["server"] = "server"
|
||||||
hostname: str = "server"
|
hostname: str = "server"
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: Server.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: Server.ConfigSchema())
|
||||||
@@ -49,6 +52,7 @@ class Printer(HostNode, discriminator="printer"):
|
|||||||
class ConfigSchema(HostNode.ConfigSchema):
|
class ConfigSchema(HostNode.ConfigSchema):
|
||||||
"""Configuration Schema for Printer class."""
|
"""Configuration Schema for Printer class."""
|
||||||
|
|
||||||
|
type: Literal["printer"] = "printer"
|
||||||
hostname: str = "printer"
|
hostname: str = "printer"
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: Printer.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: Printer.ConfigSchema())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
from typing import Dict, Final, Union
|
from typing import Dict, Final, Literal, Union
|
||||||
|
|
||||||
from prettytable import MARKDOWN, PrettyTable
|
from prettytable import MARKDOWN, PrettyTable
|
||||||
from pydantic import Field, validate_call
|
from pydantic import Field, validate_call
|
||||||
@@ -103,6 +103,7 @@ class Firewall(Router, discriminator="firewall"):
|
|||||||
class ConfigSchema(Router.ConfigSchema):
|
class ConfigSchema(Router.ConfigSchema):
|
||||||
"""Configuration Schema for Firewall 'Nodes' within PrimAITE."""
|
"""Configuration Schema for Firewall 'Nodes' within PrimAITE."""
|
||||||
|
|
||||||
|
type: Literal["firewall"] = "firewall"
|
||||||
hostname: str = "firewall"
|
hostname: str = "firewall"
|
||||||
num_ports: int = 0
|
num_ports: int = 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from typing import Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from primaite.simulator.network.hardware.base import NetworkInterface, Node
|
from primaite.simulator.network.hardware.base import NetworkInterface, Node
|
||||||
from primaite.simulator.network.transmission.data_link_layer import Frame
|
from primaite.simulator.network.transmission.data_link_layer import Frame
|
||||||
@@ -16,6 +16,11 @@ class NetworkNode(Node, discriminator="network-node"):
|
|||||||
provide functionality for receiving and processing frames received on their network interfaces.
|
provide functionality for receiving and processing frames received on their network interfaces.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class ConfigSchema(Node.ConfigSchema):
|
||||||
|
"""Config schema for Node baseclass."""
|
||||||
|
|
||||||
|
num_ports: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def receive_frame(self, frame: Frame, from_network_interface: NetworkInterface):
|
def receive_frame(self, frame: Frame, from_network_interface: NetworkInterface):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
import secrets
|
import secrets
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from ipaddress import IPv4Address, IPv4Network
|
from ipaddress import IPv4Address, IPv4Network
|
||||||
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
|
from typing import Any, ClassVar, Dict, List, Literal, Optional, Tuple, Union
|
||||||
|
|
||||||
from prettytable import MARKDOWN, PrettyTable
|
from prettytable import MARKDOWN, PrettyTable
|
||||||
from pydantic import Field, validate_call
|
from pydantic import Field, validate_call
|
||||||
@@ -1204,8 +1204,13 @@ class Router(NetworkNode, discriminator="router"):
|
|||||||
class ConfigSchema(NetworkNode.ConfigSchema):
|
class ConfigSchema(NetworkNode.ConfigSchema):
|
||||||
"""Configuration Schema for Routers."""
|
"""Configuration Schema for Routers."""
|
||||||
|
|
||||||
|
type: Literal["router"] = "router"
|
||||||
hostname: str = "router"
|
hostname: str = "router"
|
||||||
num_ports: int = 5
|
num_ports: int = 5
|
||||||
|
acl: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
routes: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
ports: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
default_route: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: Router.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: Router.ConfigSchema())
|
||||||
|
|
||||||
@@ -1625,16 +1630,20 @@ class Router(NetworkNode, discriminator="router"):
|
|||||||
:return: Configured router.
|
:return: Configured router.
|
||||||
:rtype: Router
|
:rtype: Router
|
||||||
"""
|
"""
|
||||||
|
ports = config.pop("ports", None)
|
||||||
|
acl = config.pop("acl", None)
|
||||||
|
routes = config.pop("routes", None)
|
||||||
|
default_route = config.pop("default_route", None)
|
||||||
router = Router(config=Router.ConfigSchema(**config))
|
router = Router(config=Router.ConfigSchema(**config))
|
||||||
if "ports" in config:
|
if ports:
|
||||||
for port_num, port_cfg in config["ports"].items():
|
for port_num, port_cfg in ports.items():
|
||||||
router.configure_port(
|
router.configure_port(
|
||||||
port=port_num,
|
port=port_num,
|
||||||
ip_address=port_cfg["ip_address"],
|
ip_address=port_cfg["ip_address"],
|
||||||
subnet_mask=IPv4Address(port_cfg.get("subnet_mask", "255.255.255.0")),
|
subnet_mask=IPv4Address(port_cfg.get("subnet_mask", "255.255.255.0")),
|
||||||
)
|
)
|
||||||
if "acl" in config:
|
if acl:
|
||||||
for r_num, r_cfg in config["acl"].items():
|
for r_num, r_cfg in acl.items():
|
||||||
router.acl.add_rule(
|
router.acl.add_rule(
|
||||||
action=ACLAction[r_cfg["action"]],
|
action=ACLAction[r_cfg["action"]],
|
||||||
src_port=None if not (p := r_cfg.get("src_port")) else PORT_LOOKUP[p],
|
src_port=None if not (p := r_cfg.get("src_port")) else PORT_LOOKUP[p],
|
||||||
@@ -1646,16 +1655,16 @@ class Router(NetworkNode, discriminator="router"):
|
|||||||
dst_wildcard_mask=r_cfg.get("dst_wildcard_mask"),
|
dst_wildcard_mask=r_cfg.get("dst_wildcard_mask"),
|
||||||
position=r_num,
|
position=r_num,
|
||||||
)
|
)
|
||||||
if "routes" in config:
|
if routes:
|
||||||
for route in config.get("routes"):
|
for route in routes:
|
||||||
router.route_table.add_route(
|
router.route_table.add_route(
|
||||||
address=IPv4Address(route.get("address")),
|
address=IPv4Address(route.get("address")),
|
||||||
subnet_mask=IPv4Address(route.get("subnet_mask", "255.255.255.0")),
|
subnet_mask=IPv4Address(route.get("subnet_mask", "255.255.255.0")),
|
||||||
next_hop_ip_address=IPv4Address(route.get("next_hop_ip_address")),
|
next_hop_ip_address=IPv4Address(route.get("next_hop_ip_address")),
|
||||||
metric=float(route.get("metric", 0)),
|
metric=float(route.get("metric", 0)),
|
||||||
)
|
)
|
||||||
if "default_route" in config:
|
if default_route:
|
||||||
next_hop_ip_address = config["default_route"].get("next_hop_ip_address", None)
|
next_hop_ip_address = default_route.get("next_hop_ip_address", None)
|
||||||
if next_hop_ip_address:
|
if next_hop_ip_address:
|
||||||
router.route_table.set_default_route_next_hop_ip_address(next_hop_ip_address)
|
router.route_table.set_default_route_next_hop_ip_address(next_hop_ip_address)
|
||||||
router.operating_state = (
|
router.operating_state = (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Literal, Optional
|
||||||
|
|
||||||
from prettytable import MARKDOWN, PrettyTable
|
from prettytable import MARKDOWN, PrettyTable
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
@@ -101,6 +101,7 @@ class Switch(NetworkNode, discriminator="switch"):
|
|||||||
class ConfigSchema(NetworkNode.ConfigSchema):
|
class ConfigSchema(NetworkNode.ConfigSchema):
|
||||||
"""Configuration Schema for Switch nodes within PrimAITE."""
|
"""Configuration Schema for Switch nodes within PrimAITE."""
|
||||||
|
|
||||||
|
type: Literal["switch"] = "switch"
|
||||||
hostname: str = "Switch"
|
hostname: str = "Switch"
|
||||||
num_ports: int = 24
|
num_ports: int = 24
|
||||||
"The number of ports on the switch. Default is 24."
|
"The number of ports on the switch. Default is 24."
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
from typing import Any, Dict, Optional, Union
|
from typing import Any, Dict, Literal, Optional, Union
|
||||||
|
|
||||||
from pydantic import Field, validate_call
|
from pydantic import Field, validate_call
|
||||||
|
|
||||||
@@ -126,10 +126,13 @@ class WirelessRouter(Router, discriminator="wireless-router"):
|
|||||||
class ConfigSchema(Router.ConfigSchema):
|
class ConfigSchema(Router.ConfigSchema):
|
||||||
"""Configuration Schema for WirelessRouter nodes within PrimAITE."""
|
"""Configuration Schema for WirelessRouter nodes within PrimAITE."""
|
||||||
|
|
||||||
|
type: Literal["wireless-router"] = "wireless-router"
|
||||||
hostname: str = "WirelessRouter"
|
hostname: str = "WirelessRouter"
|
||||||
airspace: AirSpace
|
|
||||||
num_ports: int = 0
|
num_ports: int = 0
|
||||||
|
router_interface: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
wireless_access_point: Any = None # temporarily unset to appease extra="forbid"
|
||||||
|
|
||||||
|
airspace: AirSpace
|
||||||
config: ConfigSchema = Field(default_factory=lambda: WirelessRouter.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: WirelessRouter.ConfigSchema())
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@@ -137,7 +140,7 @@ class WirelessRouter(Router, discriminator="wireless-router"):
|
|||||||
|
|
||||||
self.connect_nic(
|
self.connect_nic(
|
||||||
WirelessAccessPoint(
|
WirelessAccessPoint(
|
||||||
ip_address="127.0.0.1", subnet_mask="255.0.0.0", gateway="0.0.0.0", airspace=kwargs["config"].airspace
|
ip_address="127.0.0.1", subnet_mask="255.0.0.0", gateway="0.0.0.0", airspace=self.airspace
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -236,7 +239,7 @@ class WirelessRouter(Router, discriminator="wireless-router"):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_config(cls, config: Dict, **kwargs) -> "WirelessRouter":
|
def from_config(cls, config: Dict, airspace: AirSpace) -> "WirelessRouter":
|
||||||
"""Generate the wireless router from config.
|
"""Generate the wireless router from config.
|
||||||
|
|
||||||
Schema:
|
Schema:
|
||||||
@@ -263,7 +266,7 @@ class WirelessRouter(Router, discriminator="wireless-router"):
|
|||||||
:return: WirelessRouter instance.
|
:return: WirelessRouter instance.
|
||||||
:rtype: WirelessRouter
|
:rtype: WirelessRouter
|
||||||
"""
|
"""
|
||||||
router = cls(config=cls.ConfigSchema(**config))
|
router = cls(config=cls.ConfigSchema(**config), airspace=airspace)
|
||||||
router.operating_state = (
|
router.operating_state = (
|
||||||
NodeOperatingState.ON if not (p := config.get("operating_state")) else NodeOperatingState[p.upper()]
|
NodeOperatingState.ON if not (p := config.get("operating_state")) else NodeOperatingState[p.upper()]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from typing import Dict
|
from typing import Dict, Literal
|
||||||
|
|
||||||
from prettytable import MARKDOWN, PrettyTable
|
from prettytable import MARKDOWN, PrettyTable
|
||||||
|
|
||||||
@@ -18,6 +18,9 @@ class GigaSwitch(NetworkNode, discriminator="gigaswitch"):
|
|||||||
:ivar num_ports: The number of ports on the switch. Default is 24.
|
:ivar num_ports: The number of ports on the switch. Default is 24.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class ConfigSchema(NetworkNode.ConfigSchema):
|
||||||
|
type: Literal["gigaswitch"] = "gigaswitch"
|
||||||
|
|
||||||
num_ports: int = 24
|
num_ports: int = 24
|
||||||
"The number of ports on the switch."
|
"The number of ports on the switch."
|
||||||
network_interfaces: Dict[str, SwitchPort] = {}
|
network_interfaces: Dict[str, SwitchPort] = {}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
|
||||||
from typing import ClassVar, Dict
|
from typing import ClassVar, Dict, Literal
|
||||||
|
|
||||||
from primaite.simulator.network.hardware.nodes.host.host_node import HostNode, NIC
|
from primaite.simulator.network.hardware.nodes.host.host_node import HostNode, NIC
|
||||||
from primaite.simulator.system.services.ftp.ftp_client import FTPClient
|
from primaite.simulator.system.services.ftp.ftp_client import FTPClient
|
||||||
@@ -34,6 +34,9 @@ class SuperComputer(HostNode, discriminator="supercomputer"):
|
|||||||
* Web Browser
|
* Web Browser
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class ConfigSchema(HostNode.ConfigSchema):
|
||||||
|
type: Literal["supercomputer"] = "supercomputer"
|
||||||
|
|
||||||
SYSTEM_SOFTWARE: ClassVar[Dict] = {**HostNode.SYSTEM_SOFTWARE, "ftp-client": FTPClient}
|
SYSTEM_SOFTWARE: ClassVar[Dict] = {**HostNode.SYSTEM_SOFTWARE, "ftp-client": FTPClient}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ def test_wireless_link_loading(wireless_wan_network):
|
|||||||
# Configure Router 2 ACLs
|
# Configure Router 2 ACLs
|
||||||
router_2.acl.add_rule(action=ACLAction.PERMIT, position=1)
|
router_2.acl.add_rule(action=ACLAction.PERMIT, position=1)
|
||||||
|
|
||||||
airspace = router_1.config.airspace
|
airspace = router_1.airspace
|
||||||
|
|
||||||
client.software_manager.install(FTPClient)
|
client.software_manager.install(FTPClient)
|
||||||
ftp_client: FTPClient = client.software_manager.software.get("ftp-client")
|
ftp_client: FTPClient = client.software_manager.software.get("ftp-client")
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ def wireless_wan_network():
|
|||||||
|
|
||||||
# Configure Router 1
|
# Configure Router 1
|
||||||
router_1 = WirelessRouter.from_config(
|
router_1 = WirelessRouter.from_config(
|
||||||
config={"type": "wireless_router", "hostname": "router_1", "start_up_duration": 0, "airspace": network.airspace}
|
config={"type": "wireless-router", "hostname": "router_1", "start_up_duration": 0}, airspace=network.airspace
|
||||||
)
|
)
|
||||||
router_1.power_on()
|
router_1.power_on()
|
||||||
network.add_node(router_1)
|
network.add_node(router_1)
|
||||||
@@ -63,7 +63,7 @@ def wireless_wan_network():
|
|||||||
|
|
||||||
# Configure Router 2
|
# Configure Router 2
|
||||||
router_2: WirelessRouter = WirelessRouter.from_config(
|
router_2: WirelessRouter = WirelessRouter.from_config(
|
||||||
config={"type": "wireless_router", "hostname": "router_2", "start_up_duration": 0, "airspace": network.airspace}
|
config={"type": "wireless-router", "hostname": "router_2", "start_up_duration": 0}, airspace=network.airspace
|
||||||
)
|
)
|
||||||
router_2.power_on()
|
router_2.power_on()
|
||||||
network.add_node(router_2)
|
network.add_node(router_2)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ from primaite.utils.validation.port import PORT_LOOKUP
|
|||||||
|
|
||||||
def test_wireless_router_from_config():
|
def test_wireless_router_from_config():
|
||||||
cfg = {
|
cfg = {
|
||||||
"ref": "router_1",
|
|
||||||
"type": "router",
|
"type": "router",
|
||||||
"hostname": "router_1",
|
"hostname": "router_1",
|
||||||
"num_ports": 6,
|
"num_ports": 6,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ def wireless_wan_network():
|
|||||||
|
|
||||||
# Configure Router 1
|
# Configure Router 1
|
||||||
router_1 = WirelessRouter.from_config(
|
router_1 = WirelessRouter.from_config(
|
||||||
config={"type": "wireless_router", "hostname": "router_1", "start_up_duration": 0, "airspace": network.airspace}
|
config={"type": "wireless-router", "hostname": "router_1", "start_up_duration": 0}, airspace=network.airspace
|
||||||
)
|
)
|
||||||
router_1.power_on()
|
router_1.power_on()
|
||||||
network.add_node(router_1)
|
network.add_node(router_1)
|
||||||
|
|||||||
Reference in New Issue
Block a user