Newer
Older
""" This module generates a Vagrantfile from input device definitions. """
from modules.file_manager import load_template, generate_file, open_yaml
VAGRANT_MAPPING = open_yaml("conf/vagrant_mapping.yml")
VIRTUALBOX_MAPPING = open_yaml("conf/virtualbox_mapping.yml")
BASE_PLAYBOOK = "base_provisioning/device_configuration.yml"
USER_PLAYBOOK = "provisioning/playbook.yml"
INVENTORY_FILE = "provisioning/inventory.ini"
def _create_simple_attribute(key, value, attribute_type):
""" Creates simple vagrant attributes like string, integer or boolean. """
attribute = dict()
attribute["type"] = attribute_type
attribute["command"] = 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. """
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"))
elif attribute in VAGRANT_MAPPING["boolean"]:
commands.append(_create_simple_attribute(VAGRANT_MAPPING["boolean"][attribute], value, "boolean"))
elif attribute in VAGRANT_MAPPING["integer"]:
commands.append(_create_simple_attribute(VAGRANT_MAPPING["integer"][attribute], value, "integer"))
elif attribute in VIRTUALBOX_MAPPING["integer"]:
vb_commands.append(_create_simple_attribute(VIRTUALBOX_MAPPING["integer"][attribute], value, "integer"))
if vb_commands:
vb = dict()
vb["type"] = "provider"
vb["name"] = "virtualbox"
vb["commands"] = vb_commands
commands.append(vb)
return commands
def _create_ansible_commands(playbook_location, flags):
""" Creates commands for running a playbook from the Vagrantfile. """
commands = []
playbook = dict()
playbook["type"] = "string"
playbook["command"] = "playbook"
playbook["value"] = playbook_location
commands.append(playbook)
inventory = dict()
inventory["type"] = "string"
inventory["command"] = "inventory_path"
inventory["value"] = INVENTORY_FILE
commands.append(inventory)
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
if "verbose_ansible" in flags and flags["verbose_ansible"]:
verbosity = dict()
verbosity["type"] = "boolean"
verbosity["command"] = "verbose"
verbosity["value"] = True
commands.append(verbosity)
return commands
def _find_netmask(network_name, networks):
""" Returns 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
def _add_networks_to_device(definition, mappings, input_definitions):
""" Adds networks to the vagrant definition of one device. """
for mapping in mappings:
if mapping[definition["type"]] == definition["name"]:
network = dict()
network["type"] = "network"
network["network_type"] = "private_network"
network["name"] = mapping["network"]
network["ip"] = mapping["ip"]
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. """
for definition in vagrant_definitions:
if definition["type"] == "host":
_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)
def _call_provisioner(flags):
""" Creates entry to vagrant definitions for calling the provisioner. """
provisioner_calls = []
config_playbook = dict()
config_playbook["type"] = "provision"
if "ansible_local" in flags and flags["ansible_local"]:
config_playbook["provisioner"] = "ansible_local"
else:
config_playbook["provisioner"] = "ansible"
config_playbook["note"] = "basic configuration of devices and networks"
config_playbook["commands"] = _create_ansible_commands(
provisioner_calls.append(config_playbook)
user_playbook = dict()
user_playbook["type"] = "provision"
if "ansible_local" in flags and flags["ansible_local"]:
user_playbook["provisioner"] = "ansible_local"
else:
user_playbook["provisioner"] = "ansible"
user_playbook["note"] = "user configuration of devices"
user_playbook["commands"] = _create_ansible_commands(
provisioner_calls.append(user_playbook)
return provisioner_calls
def _build_vagrant_definitions(input_definitions, flags):
"""
Creates a definition structure that 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)
vagrant_definitions.append(device)
device = dict()
device["type"] = "host"
device["name"] = host["name"]
device["commands"] = _create_commands(host, "host", input_definitions, flags)
vagrant_definitions.append(device)
_add_all_networks(vagrant_definitions, input_definitions, flags)
vagrant_definitions.extend(_call_provisioner(flags))
return vagrant_definitions
def _build_vagrantfile(vagrant_definitions):
"""
Generates the Vagrantfile using the vagrantfile template and vagrant
definitions.
"""
template = load_template("vagrantfile")
output = template.render(defs=vagrant_definitions)
generate_file("Vagrantfile", output)
def generate_vagrantfile(input_definitions, flags):
"""
This method is responsible for Vagrantfile generation.
:param input_definitions: device definitions from the input file
:param flags: command line flags
"""
try:
vagrant_definitions = _build_vagrant_definitions(input_definitions, flags)
print("Could not create definitions for Vagrantfile.")
raise
try:
_build_vagrantfile(vagrant_definitions)
except Exception:
print("Could not generate Vagrantfile.")
raise