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")
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 = []
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
playbook = dict()
playbook["type"] = "string"
playbook["command"] = "playbook"
playbook["value"] = playbook_location
commands.append(playbook)
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(
"base_provisioning/device_configuration.yml", flags)
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(
"base_provisioning/playbook.yml", flags)
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