Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
file_generator.py 7.75 KiB
import jinja2
import os

from modules.device_creator import create_devices
from modules.ansible_data_generator import create_network_map, create_host_map, create_network_ips
from modules.routing import BORDER_ROUTER_IP, BORDER_ROUTER_NAME, BORDER_ROUTER_NETWORK_NAME, BORDER_ROUTER_PUBLIC_IP

def _load_template(template_name):
    """ Returns a loaded jinja2 template. """

    template_loader = jinja2.FileSystemLoader(searchpath="templates")
    template_env = jinja2.Environment(loader=template_loader, trim_blocks=True)
    return template_env.get_template(template_name)


def _generate_file(filename, output_string):
    """ Generates a file from output string. """

    try:
        new_file = open(filename, "w")
        new_file.write(output_string)
    except IOError:
        print("Error: cannot write to this location.")


def _create_role_directory(role_name, provisioning_dir):
    """ Creates directory structure for a role. """

    try:
        os.mkdir(provisioning_dir)
    except FileExistsError:
        pass
    try:
        os.mkdir(provisioning_dir + "/roles")
    except FileExistsError:
        pass
    try:
        os.mkdir(provisioning_dir + "/roles/" + role_name)
    except FileExistsError:
        pass
    try:
        os.mkdir(provisioning_dir + "/roles/" + role_name +"/tasks")
    except FileExistsError:
        pass


def _find_user_ansible_files(definitions):
    """ Finds the user ansible files and returns a list of host names. """
    host_names = []

    for host in definitions["hosts"]:
        if os.path.isfile("provisioning/" + host["name"] + ".yml" ):
            host_names.append(host["name"])

    return host_names

def generate_vagrantfile(definitions, ansible_local):
    """ Writes the prepared output to a Vagrantfile. """
   
    device_definitions = create_devices(definitions, ansible_local)
    user_ansible_files = _find_user_ansible_files(definitions)
    template = _load_template("vagrantfile")
    output = template.render(devices=device_definitions, user_files=user_ansible_files, ansible_local=ansible_local)
    _generate_file("Vagrantfile", output)
    
    print("Info: Vagrantfile successfully created.")


def _generate_playbook(definitions):
    """ Generates the main playbook. """

    host_map = create_host_map(definitions["net_mappings"], definitions["router_mappings"], definitions["hosts"])
    network = create_network_map(definitions)
    
    template = _load_template("playbook")
    output = template.render(hosts=host_map, routers=network)

    try:
        os.mkdir("provisioning")
    except FileExistsError:
        pass

    _generate_file("./provisioning/playbook.yml", output)


def _generate_device_configuration(definitions):
    """ Generates a playbook with basic device configutarion. """

    host_map = create_host_map(definitions["net_mappings"], definitions["router_mappings"], definitions["hosts"])
    network = create_network_map(definitions) 
    network_ips = create_network_ips(definitions["networks"])

    template = _load_template("device_configuration")
    output = template.render(hosts=host_map, routers=network, network_ips=network_ips, border_router_name = BORDER_ROUTER_NAME)

    try:
        os.mkdir("base_provisioning")
    except FileExistsError:
        pass

    _generate_file("./base_provisioning/device_configuration.yml", output)


def _generate_hosts_role(definitions):
    """ Generates hosts role. """

    host_map = create_host_map(definitions["net_mappings"], definitions["router_mappings"], definitions["hosts"])

    network = create_network_map(definitions)

    template = _load_template("hosts")
    output = template.render(hosts=host_map, routers=network)

    _create_role_directory("hosts", "base_provisioning")
    _generate_file("./base_provisioning/roles/hosts/tasks/main.yml", output)
    
    user_template = _load_template("user_hosts")
    user_output = template.render()

    _create_role_directory("hosts", "provisioning")
    _generate_file("./provisioning/roles/hosts/tasks/main.yml", output)


def _generate_separate_hosts_role(definitions):
    """ Generate roles for separate host devices. """
    
    host_map = create_host_map(definitions["net_mappings"], definitions["router_mappings"], definitions["hosts"])

    for host in definitions["hosts"]:

        for host_attributes in host_map:
            if host_attributes["host_name"] == host["name"]:
                host_name = host_attributes["host_name"]
                router_ip = host_attributes["router_ip"]
                interface = host_attributes["interface"]

        template = _load_template("separate_hosts")
        output = template.render(host_name=host_name, router_ip=router_ip, interface=interface)

        _create_role_directory(host["name"], "base_provisioning")
        _generate_file("./base_provisioning/roles/" + host["name"]  + "/tasks/main.yml", output)


        template = _load_template("user_separate_hosts")
        output = template.render(host_name=host_name)

        _create_role_directory(host["name"], "provisioning")
        _generate_file("./provisioning/roles/" + host["name"]  + "/tasks/main.yml", output)

def _generate_routers_role(definitions):
    """ Generates routers role. """

    if not definitions['routers'] or not definitions['router_mappings']:
        print("Info: No router definition was found. Skipping router creation.")
        return

    host_map = create_host_map(definitions["net_mappings"], definitions["router_mappings"], definitions["hosts"])

    network = create_network_map(definitions) 

    template = _load_template("routers")
    output = template.render(hosts=host_map, routers=network, border_router_ip=BORDER_ROUTER_IP)

    _create_role_directory("routers", "base_provisioning")
    _generate_file("./base_provisioning/roles/routers/tasks/main.yml", output)


def _find_cidr(network_name, definitions):
    """ Finds cidr of a network from name. """

    for network in definitions["networks"]:
        if network["name"] == network_name:
            return network["cidr"]

def _get_br_routers(definitions):
    """ Returns a list of router ips that are in the border router network. """

    br_mappings = dict()
    for router_mapping in definitions["router_mappings"]:
        if router_mapping["network"] == BORDER_ROUTER_NETWORK_NAME:
            for router_mapping2 in definitions["router_mappings"]:
                if router_mapping["router"] == router_mapping2["router"] and router_mapping["network"] != router_mapping2["network"]:
                    br_mappings[_find_cidr(router_mapping2["network"], definitions)] = router_mapping["ip"]

    return br_mappings

def _generate_br_role(definitions):
    """ Generates br role. """

    if not definitions['routers'] or not definitions['router_mappings']:
        print("Info: No router definition was found. Skipping border router creation.")
        return

    network = create_network_map(definitions) 
    
    host_map = create_host_map(definitions["net_mappings"], definitions["router_mappings"], definitions["hosts"])

    routers_in_br_network = _get_br_routers(definitions)

    template = _load_template("br")
    output = template.render(hosts = host_map, routers=network, br_routes=routers_in_br_network, border_router_name=BORDER_ROUTER_NAME, border_router_public_ip=BORDER_ROUTER_PUBLIC_IP)

    _create_role_directory("br", "base_provisioning")
    _generate_file("./base_provisioning/roles/br/tasks/main.yml", output)


def generate_ansible_files(device_definitions):
    """ Generates files for ansible. """
    
    _generate_playbook(device_definitions)
    _generate_device_configuration(device_definitions)
    _generate_hosts_role(device_definitions)
    _generate_separate_hosts_role(device_definitions)
    _generate_routers_role(device_definitions)
    _generate_br_role(device_definitions)

    print("Info: Ansible files successfully created.")