Skip to content
Snippets Groups Projects
creator.py 5.56 KiB
Newer Older
Attila Farkas's avatar
Attila Farkas committed
from pathlib import Path
from typing import Union, Optional

from cyber_sandbox_creator.input_parser.sandbox import Sandbox
from cyber_sandbox_creator.vagrant_generator.vagrantfile import Vagrantfile
Attila Farkas's avatar
Attila Farkas committed
from cyber_sandbox_creator.ansible_generator.preconfig import Preconfig
from cyber_sandbox_creator.ansible_generator.provisioning import Provision
Attila Farkas's avatar
Attila Farkas committed

CSC_PATH: Path = Path(__file__).parent.resolve()
CONFIGURATION_PATH: Path = CSC_PATH / "conf/configuration.yml"
FLAVORS_PATH: Path = CSC_PATH / "conf/flavors.yml"


def create(topology: Union[str, Path],
           output_dir: Optional[Union[str, Path]] = None,
Attila Farkas's avatar
Attila Farkas committed
           ansible_installed: bool = False, border_router: bool = False,
           provisioning_dir: Optional[Union[str, Path]] = None,
           extra_vars: Optional[Union[str, Path]] = None,
           generate_provisioning: bool = False,
           verbose_ansible: bool = False) -> None:
Attila Farkas's avatar
Attila Farkas committed
    """Generates intermediate definition from a topology definition.

    :param topology: path to the topology definition file
    :param output_dir: path to an output directory
    :param ansible_installed: whether the host machine have ansible installed
    :param border_router: whether border router should be created
    :param provisioning_dir: path to directory with user provisioning files
    :param extra_vars: path to YAML file with additional values for Ansible
    :param generate_provisioning: whether provisioning should be regenerated
    :param verbose_ansible: whether Ansible output should be set to verbose
Attila Farkas's avatar
Attila Farkas committed
    """

    try:
        if isinstance(topology, str):
Attila Farkas's avatar
Attila Farkas committed
            topology_path: Path = Path(topology).resolve()
        elif isinstance(topology, Path):
Attila Farkas's avatar
Attila Farkas committed
            topology_path: Path = topology.resolve()
        else:
            raise TypeError("Topology definition file path has invalid type "
Attila Farkas's avatar
Attila Farkas committed
                            f"\"{type(topology)}\"")
        if not topology_path.is_file():
            raise IOError(f"File \"{topology_path}\" does not exist")
    except OSError:
        raise ValueError(f"Invalid path to topology file \"{topology}\"")

    try:
        if output_dir is None or not output_dir:
            sandbox_path: Path = topology_path.parent / "sandbox"
        elif isinstance(output_dir, str):
Attila Farkas's avatar
Attila Farkas committed
            sandbox_path: Path = Path(output_dir).resolve()
        elif isinstance(output_dir, Path):
Attila Farkas's avatar
Attila Farkas committed
            sandbox_path: Path = output_dir.resolve()
        else:
            raise TypeError("Output directory path has invalid type "
                            f"\"{type(output_dir)}\"")
    except OSError:
        raise ValueError(f"Invalid output directory \"{output_dir}\"")

    try:
        user_provisioning_path: Optional[Path] = None
        if provisioning_dir:
            if isinstance(provisioning_dir, str):
Attila Farkas's avatar
Attila Farkas committed
                user_provisioning_path = Path(provisioning_dir).resolve()
            elif isinstance(provisioning_dir, Path):
Attila Farkas's avatar
Attila Farkas committed
                user_provisioning_path = provisioning_dir.resolve()
            else:
                raise TypeError("Provisioning directory path has invalid type "
                                f"\"{type(output_dir)}\"")
            if not user_provisioning_path.is_dir():
                raise IOError(f"Directory \"{user_provisioning_path}\" "
                              "does not exist")
            playbook: Path = user_provisioning_path / "playbook.yml"
            if not playbook.is_file():
                raise IOError("Provisioning directory should contain "
                              "\"playbook.yml\"")
    except OSError:
        raise ValueError("Invalid path to provisioning directory "
                         f"\"{provisioning_dir}\"")

    try:
        extra_vars_path: Optional[Path] = None
        if extra_vars:
            if isinstance(extra_vars, str):
Attila Farkas's avatar
Attila Farkas committed
                extra_vars_path = Path(extra_vars).resolve()
            elif isinstance(extra_vars, Path):
Attila Farkas's avatar
Attila Farkas committed
                extra_vars_path = extra_vars.resolve()
            else:
                raise TypeError("Extra vars file path has invalid type "
                                f"\"{type(output_dir)}\"")
            if not extra_vars_path.is_file():
                raise IOError(f"File \"{extra_vars_path}\" does not exist")
    except OSError:
        raise ValueError("Invalid path to extra variables file "
                         f"\"{extra_vars}\"")

    try:
        sandbox_definition: Sandbox = Sandbox(topology_path, CONFIGURATION_PATH,
                                              FLAVORS_PATH, sandbox_path,
                                              border_router, ansible_installed,
                                              user_provisioning_path,
                                              extra_vars_path,
                                              generate_provisioning,
                                              verbose_ansible)
Attila Farkas's avatar
Attila Farkas committed
    except (IOError, ValueError) as e:
        raise RuntimeError(f"Definition parsing has failed:\n{e}")

    try:
        vagrant_definition: Vagrantfile = Vagrantfile(sandbox_definition)
        vagrant_definition.generate(sandbox_definition.sandbox_dir /
                                    "Vagrantfile", "vagrantfile.j2")
    except IOError as e:
        raise RuntimeError(f"Vagrantfile could not be generated:\n{e}")
Attila Farkas's avatar
Attila Farkas committed

    try:
        Preconfig.generate_preconfig(sandbox_definition)
    except IOError as e:
        raise RuntimeError(f"Provisioning files could not be generated:\n{e}")

    try:
        Provision.generate_user_provisioning(sandbox_definition)
    except IOError as e:
        raise RuntimeError("User provisioning files could not be generated:"
                           f"\n{e}")