From ccb50975dbc3b118a42d3756dada6e49e06511b6 Mon Sep 17 00:00:00 2001 From: Attila Farkas <x394097@fi.muni.cz> Date: Tue, 5 May 2020 19:48:33 +0200 Subject: [PATCH] fix codestyle and docstyle --- create.py | 20 +++--- modules/ansible_generator.py | 43 +++++++----- modules/ansible_vars_generator.py | 90 +++++++++++++----------- modules/border_router.py | 48 +++++++------ modules/file_manager.py | 87 ++++++++++++----------- modules/input_argument_parser.py | 30 ++++---- modules/input_file_validator.py | 9 ++- modules/preprocessing.py | 59 +++++++++++----- modules/vagrant_generator.py | 113 ++++++++++++++++-------------- 9 files changed, 280 insertions(+), 219 deletions(-) diff --git a/create.py b/create.py index ea506e7..19ba767 100644 --- a/create.py +++ b/create.py @@ -1,10 +1,9 @@ #!/usr/bin/python3 -""" -This script generates a Vagrantfile and ansible files from a YAML definition -of virtual machines and network topology. See the documentation for details. -""" +"""Generates Vagrantfile from YAML definition. -import sys +Generate a Vagrantfile and ansible files from a YAML definition of virtual +machines and network topology. See the documentation for details. +""" from modules.ansible_generator import generate_playbooks from modules.vagrant_generator import generate_vagrantfile @@ -14,15 +13,14 @@ from modules.input_file_validator import validate_device_definitions from modules.preprocessing import preprocess -flags = dict() -input_file_name = parse_input_args(sys.argv, flags) -device_definitions = open_yaml(input_file_name) +INPUT_FILE_NAME, FLAGS = parse_input_args() +device_definitions = open_yaml(INPUT_FILE_NAME) validate_device_definitions(device_definitions) -preprocess(device_definitions, flags) +preprocess(device_definitions, FLAGS) prepare_directories(device_definitions) -generate_vagrantfile(device_definitions, flags) -generate_playbooks(device_definitions, flags) +generate_vagrantfile(device_definitions, FLAGS) +generate_playbooks(device_definitions, FLAGS) print("Sandbox was successfully created.") diff --git a/modules/ansible_generator.py b/modules/ansible_generator.py index 4409f83..4bf98b7 100644 --- a/modules/ansible_generator.py +++ b/modules/ansible_generator.py @@ -1,40 +1,49 @@ +"""Contain functions for ansible file generation.""" + from modules.file_manager import generate_file, copy_template_file from modules.ansible_vars_generator import generate_ansible_vars - -def _create_config_playbooks(input_definitions, flags): - """ Generates playbooks and roles for basic device configuration. """ - copy_template_file("device_configuration", "base_provisioning/device_configuration.yml") - copy_template_file("hosts", "base_provisioning/roles/hosts/tasks/main.yml") +def _create_config_playbooks(input_definitions): + """Generate playbooks and roles for basic device configuration.""" + copy_template_file("device_configuration", + "base_provisioning/device_configuration.yml") + if input_definitions["hosts"]: + copy_template_file("hosts", + "base_provisioning/roles/hosts/tasks/main.yml") for device in input_definitions["hosts"] + input_definitions["routers"]: - copy_template_file("separate_devices", "base_provisioning/roles/" + device["name"] + "/tasks/main.yml") - - # TODO create other playbooks - return + copy_template_file("separate_devices", "base_provisioning/roles/" + + device["name"] + "/tasks/main.yml") def _create_user_playbooks(input_definitions): - """ Generates template playbooks and roles for users. """ - + """Generate template playbooks and roles for users.""" copy_template_file("playbook", "provisioning/playbook.yml") - copy_template_file("user_hosts", "provisioning/roles/hosts/tasks/main.yml") - copy_template_file("user_routers", "provisioning/roles/routers/tasks/main.yml") + if input_definitions["hosts"]: + copy_template_file("user_hosts", + "provisioning/roles/hosts/tasks/main.yml") + if input_definitions["routers"]: + copy_template_file("user_routers", + "provisioning/roles/routers/tasks/main.yml") for host in input_definitions["hosts"]: - generate_file("user_separate_hosts", "provisioning/roles/" + host["name"] + "/tasks/main.yml", host_name=host["name"]) + generate_file("user_separate_hosts", + "provisioning/roles/" + host["name"] + "/tasks/main.yml", + host_name=host["name"]) for router in input_definitions["routers"]: - generate_file("user_separate_routers", "provisioning/roles/" + router["name"] + "/tasks/main.yml", router_name=router["name"]) + generate_file("user_separate_routers", + "provisioning/roles/" + router["name"] + + "/tasks/main.yml", router_name=router["name"]) def generate_playbooks(input_definitions, flags): - """ Generates ansible vars and playbooks. + """Generate ansible vars and playbooks. :param definitions: device definitions structure :param flags: command line input flags """ generate_ansible_vars(input_definitions, flags) - _create_config_playbooks(input_definitions, flags) + _create_config_playbooks(input_definitions) _create_user_playbooks(input_definitions) diff --git a/modules/ansible_vars_generator.py b/modules/ansible_vars_generator.py index 403f6ac..b444a83 100644 --- a/modules/ansible_vars_generator.py +++ b/modules/ansible_vars_generator.py @@ -1,18 +1,18 @@ -from modules.file_manager import generate_file, dump_to_yaml +"""Contains functions for generation of ansible variables and playbooks.""" + from conf.border_router import BORDER_ROUTER_NETWORK_NAME +from modules.file_manager import generate_file, dump_to_yaml +from modules.routing_generator import add_routings def _find_networks_of_device(name, input_definitions): - """ Returns a list of network names in which the device have an - interface. - """ - + """Return a list of network names in which the device have an interface.""" networks = [] - + for net_mapping in input_definitions["net_mappings"]: if net_mapping["host"] == name: networks.append(net_mapping["network"]) - + if len(networks) == 1: return networks @@ -25,11 +25,10 @@ def _find_networks_of_device(name, input_definitions): networks.append(router_mapping["network"]) return networks - -def _add_aliases(device_name, input_definitions, flags): - """ Generates aliases for the given device. """ +def _add_aliases(device_name, input_definitions, flags): + """Generate aliases for the given device.""" home_networks = _find_networks_of_device(device_name, input_definitions) aliases = dict() @@ -46,51 +45,59 @@ def _add_aliases(device_name, input_definitions, flags): for router in input_definitions["routers"]: if router["name"] not in aliases: if "border_router" not in flags: - print("Error: " + device_name + " has no connection to " + router["name"] + " .") + print("Error: " + device_name + " has no connection to " + + router["name"] + " .") raise AttributeError for router_mapping in input_definitions["router_mappings"]: - if router_mapping["router"] == router["name"] and router_mapping["network"] == BORDER_ROUTER_NETWORK_NAME: + if router_mapping["router"] == router["name"] and \ + router_mapping["network"] == BORDER_ROUTER_NETWORK_NAME: aliases[router_mapping["router"]] = router_mapping["ip"] continue - + for router in input_definitions["routers"]: if router["name"] not in aliases: - print("Error: " + device_name + " has no connection to " + router["name"] + " .") + print("Error: " + device_name + " has no connection to " + + router["name"] + " .") raise AttributeError return aliases - -def _generate_device_vars(input_definitions, flags): - """ Generates vars files for all devices separately. """ +def _generate_device_vars(input_definitions, flags): + """Generate vars files for all devices separately.""" for target_host in input_definitions["hosts"]: variables = dict() - variables["aliases"] = _add_aliases(target_host["name"], input_definitions, flags) - dump_to_yaml(variables, "base_provisioning/roles/" + target_host["name"] + "/vars/main.yml") + variables["aliases"] = _add_aliases(target_host["name"], + input_definitions, flags) + variables["routings"] = add_routings(target_host["name"], "host", + input_definitions, flags) + dump_to_yaml(variables, "base_provisioning/roles/" + + target_host["name"] + "/vars/main.yml") for target_router in input_definitions["routers"]: variables = dict() - variables["aliases"] = _add_aliases(target_router["name"], input_definitions, flags) - dump_to_yaml(variables, "base_provisioning/roles/" + target_router["name"] + "/vars/main.yml") + variables["aliases"] = _add_aliases(target_router["name"], + input_definitions, flags) + variables["routings"] = add_routings(target_router["name"], "router", + input_definitions, flags) + dump_to_yaml(variables, "base_provisioning/roles/" + + target_router["name"] + "/vars/main.yml") def _generate_hosts_vars(input_definitions, flags): - """ Generates vars file for all hosts. """ - + """Generate vars file for all hosts.""" return def _generate_routers_vars(input_definitions, flags): - """ Generates vars file for all routers. """ - + """Generate vars file for all routers.""" return -def _find_ip(device_name, input_definitions): - """ Returns a dictionary with all network names and ips of a device. """ +def _find_ip(device_name, input_definitions): + """Return a dictionary with all network names and ips of a device.""" networks = dict() - + for host_mapping in input_definitions["net_mappings"]: if host_mapping["host"] == device_name: networks[host_mapping["network"]] = host_mapping["ip"] @@ -103,22 +110,24 @@ def _find_ip(device_name, input_definitions): def _find_default_route(device_name, input_definitions, flags): - """ Returns the ip to which the device should be routed defaultly and - None if the change of default routing is not required. - """ + """Return the ip to which the device should be routed defaultly. + None is returned if the change of default routing is not required. + """ return None -def _generate_config_vars(input_definitions, flags): # TODO check what vars needs to be in config - """ Generates vars file for all devices. """ # TODO dump to yaml without jinja - +def _generate_config_vars(input_definitions, flags): + """Generate vars file for all devices.""" +# TODO check what vars needs to be in config +# TODO dump to yaml without jinja hosts = [] for host in input_definitions["hosts"]: new_host = dict() new_host["name"] = host["name"] new_host["networks"] = _find_ip(host["name"], input_definitions) - new_host["route_to"] = _find_default_route(host["name"], input_definitions, flags) + new_host["route_to"] = _find_default_route(host["name"], + input_definitions, flags) hosts.append(new_host) routers = [] @@ -126,15 +135,16 @@ def _generate_config_vars(input_definitions, flags): # TODO check what vars need new_router = dict() new_router["name"] = router["name"] new_router["networks"] = _find_ip(router["name"], input_definitions) - new_router["route_to"] = _find_default_route(router["name"], input_definitions, flags) + new_router["route_to"] = _find_default_route(router["name"], + input_definitions, flags) routers.append(new_router) - - generate_file("config", "base_provisioning/config.yml", hosts=hosts, routers=routers) + generate_file("config", "base_provisioning/config.yml", hosts=hosts, + routers=routers) -def generate_ansible_vars(input_definitions, flags): - """ Generates files with variables for ansible. """ +def generate_ansible_vars(input_definitions, flags): + """Generate files with variables for ansible.""" _generate_config_vars(input_definitions, flags) _generate_hosts_vars(input_definitions, flags) _generate_routers_vars(input_definitions, flags) diff --git a/modules/border_router.py b/modules/border_router.py index 68cffc6..9794bb2 100644 --- a/modules/border_router.py +++ b/modules/border_router.py @@ -1,9 +1,10 @@ +"""Contains functions for border router creation.""" + from conf.border_router import * def _are_br_parameters_free(definitions): - """ Checks if border router parameters are not already taken. """ - + """Check if border router parameters are not already taken.""" for host in definitions["hosts"]: if host["name"] == BORDER_ROUTER_NAME: return False @@ -11,9 +12,10 @@ def _are_br_parameters_free(definitions): for router in definitions["routers"]: if router["name"] == BORDER_ROUTER_NAME: return False - + for network in definitions["networks"]: - if network["name"] == BORDER_ROUTER_NETWORK_NAME or network["cidr"] == BORDER_ROUTER_NETWORK_IP: + if network["name"] == BORDER_ROUTER_NETWORK_NAME or \ + network["cidr"] == BORDER_ROUTER_NETWORK_IP: return False for net_mapping in definitions["net_mappings"]: @@ -28,39 +30,39 @@ def _are_br_parameters_free(definitions): def _create_mappings_to_border_router(definitions): - """ Creates router_mapping entries from routers to border router. """ - + """Create router_mapping entries from routers to border router.""" for router in definitions["routers"]: num = definitions["routers"].index(router) + 5 if num > 255: raise IndexError("Too many routers.") - ip = BORDER_ROUTER_IP[:(0-len(str(num)))] - ip += str(num) + ip_address = BORDER_ROUTER_IP[:(0-len(str(num)))] + ip_address += str(num) + + border_router = {"router": router["name"], + "network": BORDER_ROUTER_NETWORK_NAME, + "ip": ip_address} + definitions["router_mappings"].append(border_router) - definitions["router_mappings"].append({"router":router["name"] - ,"network":BORDER_ROUTER_NETWORK_NAME - ,"ip":ip}) - def create_border_router(definitions): - """ - Adds the definition of border router to definitions. + """Add the definition of border router to definitions. :param definitions: device definition structure """ - # TODO this should be later moved to input check if not _are_br_parameters_free(definitions): - raise ValueError("A device with the same name as border router already exists.") - + raise ValueError("A device with the same name as border router " + "already exists.") + _create_mappings_to_border_router(definitions) - definitions["routers"].insert(0, {"name":BORDER_ROUTER_NAME }) - definitions["networks"].insert(0, {"name":BORDER_ROUTER_NETWORK_NAME - ,"cidr":BORDER_ROUTER_NETWORK_IP}) - definitions["router_mappings"].insert(0, {"router":BORDER_ROUTER_NAME - ,"network":BORDER_ROUTER_NETWORK_NAME - ,"ip":BORDER_ROUTER_IP} ) + definitions["routers"].insert(0, {"name": BORDER_ROUTER_NAME}) + networks = {"name": BORDER_ROUTER_NETWORK_NAME, + "cidr": BORDER_ROUTER_NETWORK_IP} + definitions["networks"].insert(0, networks) + router_mappings = {"router": BORDER_ROUTER_NAME, "ip": BORDER_ROUTER_IP, + "network": BORDER_ROUTER_NETWORK_NAME} + definitions["router_mappings"].insert(0, router_mappings) diff --git a/modules/file_manager.py b/modules/file_manager.py index 75524ea..8b4a8b5 100644 --- a/modules/file_manager.py +++ b/modules/file_manager.py @@ -1,4 +1,4 @@ -""" This module handles file imports and creations in general. """ +"""This module handles file imports and creations in general.""" import os import shutil @@ -11,8 +11,7 @@ OUTPUT_DIRECTORY = "sandbox" def open_yaml(file_name): - """ Opens and returns a file from the argument. """ - + """Open and return a file from the argument.""" try: with open(str(file_name)) as input_file: return yaml.safe_load(input_file) @@ -23,23 +22,20 @@ def open_yaml(file_name): def copy_template_file(template, destination): - """ Copies playbook templates that does not need jinja or yaml to the - destination. - """ - + """Copy playbook templates directly to the destination.""" try: shutil.copyfile("templates/" + template, "sandbox/" + destination) except IOError: - cleanup_and_exit("Could not copy template file " + str(file_name) + ".") + cleanup_and_exit("Could not copy template file " + str(template) + + ".") def dump_to_yaml(data, filename): - """ Writes a data structure to a YAML document. + """Write a data structure to a YAML document. :param data: a dict or list which should be written to file :param filename: name of the target file """ - file_path = OUTPUT_DIRECTORY + "/" + str(filename) try: @@ -50,21 +46,19 @@ def dump_to_yaml(data, filename): def generate_file(template, filename, **template_args): - """ Generates a file using a template. - + """Generate a file using a template. + :param template: name of the template file :param filename: path to the output file inside the output directory :param template_args: arbitrary number of named args for the template """ - inventory_template = _load_template(template) output = inventory_template.render(**template_args) _write_to_file(filename, output) def _write_to_file(filename, output_string): - """ Generates a file from output string. """ - + """Generate a file from output string.""" try: new_file = open(OUTPUT_DIRECTORY + "/" + filename, "w") new_file.write(output_string) @@ -73,21 +67,19 @@ def _write_to_file(filename, output_string): def _load_template(template_name): - """ Returns a loaded jinja2 template. """ - + """Return a loaded jinja2 template.""" try: template_loader = jinja2.FileSystemLoader(searchpath="templates") - template_env = jinja2.Environment(loader=template_loader, trim_blocks=True, lstrip_blocks=True) + template_env = jinja2.Environment(loader=template_loader, + trim_blocks=True, + lstrip_blocks=True) return template_env.get_template(template_name) except jinja2.TemplateNotFound: cleanup_and_exit("Could not find template " + str(template_name) + ".") def _copy_directory(source, destination): - """ Copies directory recursively form templates directory to the - destination. - """ - + """Copy directory recursively form templates dir to the destination.""" try: shutil.copytree("./templates/" + source, destination) except OSError: @@ -95,8 +87,7 @@ def _copy_directory(source, destination): def _create_provisioning_directories(directory, device_definitions): - """ Creates all subdirectories for privisioning. """ - + """Create subdirectories for privisioning.""" try: os.mkdir(OUTPUT_DIRECTORY + "/" + directory) os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles") @@ -106,18 +97,26 @@ def _create_provisioning_directories(directory, device_definitions): os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/hosts/tasks") os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/hosts/vars") for host in device_definitions["hosts"]: - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + host["name"]) - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + host["name"] + "/tasks") - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + host["name"] + "/vars") + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + + host["name"]) + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + + host["name"] + "/tasks") + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + + host["name"] + "/vars") if device_definitions["routers"]: os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/routers") - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/routers/tasks") - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/routers/vars") + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + + "/roles/routers/tasks") + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + + "/roles/routers/vars") for router in device_definitions["routers"]: - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + router["name"]) - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + router["name"] + "/tasks") - os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + router["name"] + "/vars") + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + + router["name"]) + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + + router["name"] + "/tasks") + os.mkdir(OUTPUT_DIRECTORY + "/" + directory + "/roles/" + + router["name"] + "/vars") except FileExistsError: pass @@ -126,26 +125,32 @@ def _create_provisioning_directories(directory, device_definitions): def prepare_directories(device_definitions): - """ Prepares the necessary directory structure. """ + """Prepare the necessary directory structure.""" + _remove_sandbox() - shutil.rmtree(OUTPUT_DIRECTORY, True) - try: os.mkdir(OUTPUT_DIRECTORY) except IOError: - cleanup_and_exit("Could not create directory ./" + OUTPUT_DIRECTORY + ".") + cleanup_and_exit("Could not create directory ./" + OUTPUT_DIRECTORY + + ".") _create_provisioning_directories("base_provisioning", device_definitions) _create_provisioning_directories("provisioning", device_definitions) - _copy_directory("interface", OUTPUT_DIRECTORY + "/base_provisioning/roles/interface") - _copy_directory("common", OUTPUT_DIRECTORY + "/base_provisioning/roles/common") + _copy_directory("interface", OUTPUT_DIRECTORY + + "/base_provisioning/roles/interface") + _copy_directory("common", OUTPUT_DIRECTORY + + "/base_provisioning/roles/common") -def cleanup_and_exit(error): - """ A cleanup function that is called in case of an error. """ +def _remove_sandbox(): + """Remove the existing sandbox.""" + shutil.rmtree(OUTPUT_DIRECTORY, True) - # TODO cleanup + +def cleanup_and_exit(error): + """Cleanup function that is called in case of an error.""" + _remove_sandbox() print("Sandbox creation was NOT successful:") print("Error: ", error) diff --git a/modules/input_argument_parser.py b/modules/input_argument_parser.py index 800fba0..1ccacc4 100644 --- a/modules/input_argument_parser.py +++ b/modules/input_argument_parser.py @@ -1,23 +1,29 @@ -""" This module contains functions to parse input arguments. """ +"""This module contains functions to parse input arguments.""" import argparse -def parse_input_args(argv, flags): - """ - Parses the given input arguments for input file name and flags. - :param argv: input arguments (list of strings) - :param flags: dictionary to write the parsed flags - :returns: name of the input file +def parse_input_args(): + """Parse the given input arguments for input file name and flags. + + :returns: name of the input file and flags """ input_file_name = None + flags = dict() parser = argparse.ArgumentParser() - parser.add_argument("definition_file", help="path to the input yaml definition") - parser.add_argument("--ansible_local", help="uses ansible_local for provisioning instead of ansible", action="store_true") - parser.add_argument("--verbose_ansible", help="sets verbose output for ansible (-vvvv)", action="store_true") - parser.add_argument("--border_router", help="creates a border router with connection to all routers", action="store_true") + parser.add_argument("definition_file", + help="path to the input yaml definition") + parser.add_argument("--ansible_local", + help="uses ansible_local for provisioning instead" + "of ansible", action="store_true") + parser.add_argument("--verbose_ansible", + help="sets verbose output for ansible (-vvvv)", + action="store_true") + parser.add_argument("--border_router", + help="creates a border router with connection to" + "all routers", action="store_true") args = parser.parse_args() input_file_name = args.definition_file @@ -25,4 +31,4 @@ def parse_input_args(argv, flags): flags["verbose_ansible"] = args.verbose_ansible flags["border_router"] = args.border_router - return input_file_name + return input_file_name, flags diff --git a/modules/input_file_validator.py b/modules/input_file_validator.py index bd38f6f..8faf832 100644 --- a/modules/input_file_validator.py +++ b/modules/input_file_validator.py @@ -1,11 +1,10 @@ -""" This module contains functions for input file validation. """ +"""This module contains functions for input file validation.""" + def validate_device_definitions(definitions): - """ - This function validates the device definitions structure and throws an - error if the syntax is not as expected. + """Validate the device definitions structure. + Throw an error if the syntax is not as expected. :param definitions: a device definition structure (dictionary) """ - # TODO implement validation diff --git a/modules/preprocessing.py b/modules/preprocessing.py index b28f3ac..a1c8d47 100644 --- a/modules/preprocessing.py +++ b/modules/preprocessing.py @@ -1,16 +1,20 @@ -""" This module contains functions for preprocessing. They are supposed to be -called after validating the input but before device creation. +"""This module contains functions for preprocessing. + +They are supposed to be called after validating the input but before device +creation. """ +import itertools + from modules.border_router import create_border_router -from modules.file_manager import open_yaml +from modules.file_manager import open_yaml, cleanup_and_exit FLAVORS = open_yaml("conf/flavors.yml") ROUTER_ATTRIBUTES = open_yaml("conf/router_attributes.yml") -def _add_missing_tags(definitions): - """ Adds necessary structures to the input if they are missing. """ +def _add_missing_tags(definitions): + """Add necessary structures to the input if they are missing.""" if "routers" not in definitions: definitions["routers"] = [] if "router_mappings" not in definitions: @@ -24,19 +28,28 @@ def _add_missing_tags(definitions): def _configure_routers(definitions): - """ Adds predefined parameters to all routers if they are not defined in - the source yaml. - """ + """Add predefined parameters to all routers. + Adds them if they are not defined in the source yaml. + """ for router in definitions["routers"]: for parameter, value in ROUTER_ATTRIBUTES.items(): if parameter not in router: router[parameter] = value -def _add_flavors(definitions): - """ Changes flavor attribute to cpus and memory. """ +def _add_extra_arguments(definitions, flags): + """Add extra arguments to definitions if they are not present.""" + if "border_router" in flags and flags["ansible_local"]: + for device in itertools.chain(definitions["hosts"], + definitions["routers"]): + if "synced_folder" not in device: + device["synced_folder"] = "\".\", \"/vagrant\", type: \"rsync"\ + "\", rsync__exclude: \".git/\"" + +def _add_flavors(definitions): + """Change flavor attribute to cpus and memory.""" for host in definitions["hosts"]: if "flavor" in host: if host["flavor"] not in FLAVORS: @@ -50,31 +63,39 @@ def _add_flavors(definitions): def preprocess(definitions, flags): - """ - This function handles the preprocessing, operations that need to be done - before the actual device creation. + """Run preprocessing. + Handles perations that need to be done before the actual device creation. :param definitions: device definition structure :param flags: a structure with command line flags """ - try: _add_missing_tags(definitions) except Exception: - cleanup_and_exit("Preprocessing not successful: Could not add missing tags.") + cleanup_and_exit("Preprocessing not successful: " + "Could not add missing tags.") try: if "border_router" in flags and flags["border_router"]: create_border_router(definitions) - except (ValueError, IndexError) as e: - cleanup_and_exit("Preprocessing not successful: Could not create border router (" + e + ")") + except (ValueError, IndexError) as error: + cleanup_and_exit("Preprocessing not successful: " + "Could not create border router (" + error + ")") try: _configure_routers(definitions) except Exception: - cleanup_and_exit("Preprocessing not successful: Could not add router configurations to definitions.") + cleanup_and_exit("Preprocessing not successful: " + "Could not add router configurations to definitions.") + + try: + _add_extra_arguments(definitions, flags) + except Exception: + cleanup_and_exit("Preprocessing not successful: " + "Could not add extra arguments to definitions.") try: _add_flavors(definitions) except Exception: - cleanup_and_exit("Preprocessing not successful: Could not add flavors.") + cleanup_and_exit("Preprocessing not successful: " + "Could not add flavors.") diff --git a/modules/vagrant_generator.py b/modules/vagrant_generator.py index 00801b5..f343b0e 100644 --- a/modules/vagrant_generator.py +++ b/modules/vagrant_generator.py @@ -1,6 +1,4 @@ -""" This module generates a Vagrantfile from input device definitions. """ - -import jinja2 +"""Contains functions for generating a Vagrantfile from input definitions.""" from modules.file_manager import generate_file, open_yaml @@ -11,8 +9,7 @@ USER_PLAYBOOK = "provisioning/playbook.yml" def _create_simple_attribute(key, value, attribute_type): - """ Creates simple vagrant attributes like string, integer or boolean. """ - + """Create simple vagrant attributes like string, integer or boolean.""" attribute = dict() attribute["type"] = attribute_type attribute["command"] = key @@ -22,52 +19,57 @@ def _create_simple_attribute(key, value, attribute_type): def _create_complex_attribute(key, value): - """ Creates complex vagrant attributes that are not string, integer or - boolean. - """ - - SEPARATORS = {VAGRANT_MAPPING["other"]["synced_folder"]: ""} + """Create complex vagrant attributes that are not string, int or bool.""" + separators = {VAGRANT_MAPPING["other"]["synced_folder"]: ""} attribute = dict() attribute["type"] = "other" attribute["command"] = key - attribute["separator"] = SEPARATORS[key] + attribute["separator"] = separators[key] attribute["value"] = value return attribute -def _create_commands(device_attributes, device_type, input_definitions, flags): - """ This function creates basic vagrant definition commands for a device. """ - +def _create_commands(device_attributes): + """Create basic vagrant definition commands for a device.""" commands = [] vb_commands = [] for attribute, value in device_attributes.items(): if attribute in VAGRANT_MAPPING["string"]: - commands.append(_create_simple_attribute(VAGRANT_MAPPING["string"][attribute], value, "string")) + vagrant_attribute = VAGRANT_MAPPING["string"][attribute] + commands.append(_create_simple_attribute(vagrant_attribute, value, + "string")) elif attribute in VAGRANT_MAPPING["boolean"]: - commands.append(_create_simple_attribute(VAGRANT_MAPPING["boolean"][attribute], value, "boolean")) + vagrant_attribute = VAGRANT_MAPPING["boolean"][attribute] + commands.append(_create_simple_attribute(vagrant_attribute, value, + "boolean")) elif attribute in VAGRANT_MAPPING["integer"]: - commands.append(_create_simple_attribute(VAGRANT_MAPPING["integer"][attribute], value, "integer")) + vagrant_attribute = VAGRANT_MAPPING["integer"][attribute] + commands.append(_create_simple_attribute(vagrant_attribute, value, + "integer")) elif attribute in VAGRANT_MAPPING["other"]: - commands.append(_create_complex_attribute(VAGRANT_MAPPING["other"][attribute], value)) + vagrant_attribute = VAGRANT_MAPPING["other"][attribute] + commands.append(_create_complex_attribute(vagrant_attribute, + value)) elif attribute in VIRTUALBOX_MAPPING["integer"]: - vb_commands.append(_create_simple_attribute(VIRTUALBOX_MAPPING["integer"][attribute], value, "integer")) + vagrant_attribute = VIRTUALBOX_MAPPING["integer"][attribute] + vb_commands.append(_create_simple_attribute(vagrant_attribute, + value, "integer")) if vb_commands: - vb = dict() - vb["type"] = "provider" - vb["name"] = "virtualbox" - vb["commands"] = vb_commands - commands.append(vb) + virtual_box_command = dict() + virtual_box_command["type"] = "provider" + virtual_box_command["name"] = "virtualbox" + virtual_box_command["commands"] = vb_commands + commands.append(virtual_box_command) return commands def _create_ansible_commands(playbook_location, input_definitions, flags): - """ Creates commands for running a playbook from the Vagrantfile. """ - + """Create commands for running a playbook from the Vagrantfile.""" commands = [] playbook = dict() @@ -97,28 +99,34 @@ def _create_ansible_commands(playbook_location, input_definitions, flags): commands.append(groups) if "ansible_local" in flags and flags["ansible_local"]: + install_mode = dict() + install_mode["type"] = "string" + install_mode["command"] = "install_mode" + install_mode["value"] = "pip" + commands.append(install_mode) + extravars = dict() extravars["type"] = "dictionary" extravars["command"] = "extra_vars" extravars["dictionary"] = dict() - extravars["dictionary"]["ansible_python_interpreter"] = "\"/usr/bin/python3\"" + extravars["dictionary"]["ansible_python_interpreter"] = \ + "\"/usr/bin/python3\"" commands.append(extravars) return commands def _find_netmask(network_name, networks): - """ Returns the netmask of a network address from network name. """ - + """Return the netmask of a network address from network name.""" for network in networks: if network['name'] == network_name: address, netmask = network['cidr'].split('/') return netmask + return None def _add_networks_to_device(definition, mappings, input_definitions): - """ Adds networks to the vagrant definition of one device. """ - + """Add networks to the vagrant definition of one device.""" for mapping in mappings: if mapping[definition["type"]] == definition["name"]: network = dict() @@ -126,23 +134,26 @@ def _add_networks_to_device(definition, mappings, input_definitions): network["network_type"] = "private_network" network["name"] = mapping["network"] network["ip"] = mapping["ip"] - network["netmask"] = _find_netmask(mapping["network"], input_definitions["networks"]) + network["netmask"] = _find_netmask(mapping["network"], + input_definitions["networks"]) definition["commands"].append(network) def _add_all_networks(vagrant_definitions, input_definitions, flags): - """ Adds all networks to vagrant definitions. """ - + """Add all networks to vagrant definitions.""" for definition in vagrant_definitions: if definition["type"] == "host": - _add_networks_to_device(definition, input_definitions["net_mappings"], input_definitions) + _add_networks_to_device(definition, + input_definitions["net_mappings"], + input_definitions) elif definition["type"] == "router": - _add_networks_to_device(definition, input_definitions["router_mappings"], input_definitions) + _add_networks_to_device(definition, + input_definitions["router_mappings"], + input_definitions) def _call_provisioner(input_definitions, flags): - """ Creates entry to vagrant definitions for calling the provisioner. """ - + """Create entry to vagrant definitions for calling the provisioner.""" provisioner_calls = [] config_playbook = dict() @@ -152,8 +163,9 @@ def _call_provisioner(input_definitions, flags): else: config_playbook["provisioner"] = "ansible" config_playbook["note"] = "basic configuration of devices and networks" - config_playbook["commands"] = _create_ansible_commands( - BASE_PLAYBOOK, input_definitions, flags) + config_playbook["commands"] = _create_ansible_commands(BASE_PLAYBOOK, + input_definitions, + flags) provisioner_calls.append(config_playbook) @@ -164,8 +176,9 @@ def _call_provisioner(input_definitions, flags): else: user_playbook["provisioner"] = "ansible" user_playbook["note"] = "user configuration of devices" - user_playbook["commands"] = _create_ansible_commands( - USER_PLAYBOOK, input_definitions, flags) + user_playbook["commands"] = _create_ansible_commands(USER_PLAYBOOK, + input_definitions, + flags) provisioner_calls.append(user_playbook) @@ -173,24 +186,24 @@ def _call_provisioner(input_definitions, flags): def _build_vagrant_definitions(input_definitions, flags): - """ - Creates a definition structure that is more suitable for Vagrantfile - generation than input definitions. - """ + """Create a definition structure for vagrant. + This structure is more suitable for Vagrantfile generation than input + definitions. + """ vagrant_definitions = [] for router in input_definitions["routers"]: device = dict() device["type"] = "router" device["name"] = router["name"] - device["commands"] = _create_commands(router, "router", input_definitions, flags) + device["commands"] = _create_commands(router) vagrant_definitions.append(device) for host in input_definitions["hosts"]: device = dict() device["type"] = "host" device["name"] = host["name"] - device["commands"] = _create_commands(host, "host", input_definitions, flags) + device["commands"] = _create_commands(host) vagrant_definitions.append(device) _add_all_networks(vagrant_definitions, input_definitions, flags) @@ -201,13 +214,11 @@ def _build_vagrant_definitions(input_definitions, flags): def generate_vagrantfile(input_definitions, flags): - """ - This method is responsible for Vagrantfile generation. + """Generate the Vagrantfile. :param input_definitions: device definitions from the input file :param flags: command line flags """ - vagrant_definitions = _build_vagrant_definitions(input_definitions, flags) generate_file("vagrantfile", "Vagrantfile", defs=vagrant_definitions) -- GitLab