diff --git a/cyber_sandbox_creator/input_parser/__init__.py b/cyber_sandbox_creator/input_parser/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/cyber_sandbox_creator/input_parser/sandbox.py b/cyber_sandbox_creator/input_parser/sandbox.py new file mode 100644 index 0000000000000000000000000000000000000000..2c5a2b12ef194da685fe83fbb76ac22fc3bc86be --- /dev/null +++ b/cyber_sandbox_creator/input_parser/sandbox.py @@ -0,0 +1,140 @@ +from enum import Enum +from pathlib import Path +from cyber_sandbox_creator.input_parser.topology_parser import Topology +from typing import List, Dict, Optional +from cyber_sandbox_creator.io.reader import Reader + + +class Protocol(Enum): + """VM communication protocol""" + SSH = 1 + WINRM = 2 + + def __str__(self): + return self.name + + +class DeviceType(Enum): + """Type of device""" + ROUTER = 1 + HOST = 2 + + def __str__(self): + return self.name.lower() + + +class DevicePurpose(Enum): + """Function of a device - also determines building order""" + BORDER_ROUTER = 1 + ROUTER = 2 + HOST = 3 + CONTROLLER = 4 + + def __str__(self): + return self.name.lower() + + +class Flavor: + """Representation of a flavor""" + + def __init__(self, name: str, memory: int, cpus: int): + self.name: str = name + self.memory: int = memory + self.cpus: int = cpus + + def __str__(self): + return f"Flavor(name: {self.name}, memory: {self.memory} GB," \ + f"CPUs: {self.cpus})" + + +class Device: + """A device of the sandbox""" + + def __init__(self, name: str, device_purpose: DevicePurpose, box: str): + self.name: str = name + self.device_purpose: DevicePurpose = device_purpose + if (device_purpose is DevicePurpose.ROUTER or + device_purpose == DevicePurpose.BORDER_ROUTER): + self.device_type = DeviceType.ROUTER + elif (device_purpose is DevicePurpose.HOST or + device_purpose == DevicePurpose.CONTROLLER): + self.device_type = DeviceType.HOST + else: + raise ValueError("Invalid device purpose") + self.box: str = box + # TODO add other attributes + + def __lt__(self, other): + return self.device_purpose.value < other.device_purpose.value + + def __str__(self): + return f"Device(name: {self.name}, type: {self.device_type}, purpose: " \ + f"{self.device_purpose}, box: {self.box})" + + +class Sandbox: + """Structure that holds all information about the sandbox""" + + def __init__(self, topology_path: Path, configuration_path: Path, + flavors_path: Path, sandbox_dir: Path, border_router: bool, + ansible_installed: bool, user_provisioning_dir: Optional[Path], + extra_vars_file: Optional[Path]): + self.border_router_present: bool = border_router + self.sandbox_dir: Path = sandbox_dir + self.ansible_installed: bool = ansible_installed + self.user_provisioning_dir: Optional[Path] = user_provisioning_dir + self.extra_vars: Optional[Dict] = self._load_extra_vars(extra_vars_file) + self.config: Dict = Reader.open_yaml(configuration_path) + self.flavors: List[Flavor] = self._load_flavors(flavors_path) + self.devices: List[Device] = self._create_device_list(topology_path, + self.flavors, + self.config, + border_router) + + @classmethod + def _load_extra_vars(cls, extra_vars_path: Optional[Path]) -> Optional[Dict]: + """Load extra vars for ansible from YAML file to a Dict""" + + extra_vars: Optional[Dict] = None + if extra_vars_path: + extra_vars = Reader.open_yaml(extra_vars_path) + if not isinstance(extra_vars, Dict): + raise TypeError("The content of extra_vars file is invalid") + + return extra_vars + + @classmethod + def _load_flavors(cls, flavors_path: Path) -> List[Flavor]: + """Load list of possible flavors from configuration file""" + + flavors: List[Flavor] = [] + flavors_file_content: Dict = Reader.open_yaml(flavors_path) + + for flavor_name, attributes in flavors_file_content.items(): + memory: int = int(attributes["memory"]) + cpus: int = int(attributes["cores"]) + flavors.append(Flavor(flavor_name, memory, cpus)) + + return flavors + + @staticmethod + def _create_device_list(topology_path: Path, flavors: List[Flavor], + config: Dict, border_router: bool) -> List[Device]: + """Creates list of devices with all attributes""" + + topology: Topology = Topology.from_file(topology_path) + devices: List[Device] = [] + + if border_router: + devices.append(Device(config["border_router_name"], + DevicePurpose.BORDER_ROUTER, + config["border_router_box"])) + + # TODO add controller + + # for host in topology.hosts: + # TODO add hosts + # for router in topology.routers: + # TODO add routers + + return devices.sort() # sorted by priority based on device purpose diff --git a/cyber_sandbox_creator/input_parser/topology_parser.py b/cyber_sandbox_creator/input_parser/topology_parser.py new file mode 100644 index 0000000000000000000000000000000000000000..38651d6a79228fc43a7e83aadfd6aafb92bdf91e --- /dev/null +++ b/cyber_sandbox_creator/input_parser/topology_parser.py @@ -0,0 +1,5 @@ +import kypo.topology_definition.models as kypo_topology + + +class Topology(kypo_topology.TopologyDefinition): + pass