Newer
Older
""" This module generates a Vagrantfile from input device definitions. """
from modules.file_manager import 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"
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)
def _create_ansible_commands(playbook_location, input_definitions, 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)
if "verbose_ansible" in flags and flags["verbose_ansible"]:
verbosity = dict()
verbosity["type"] = "boolean"
verbosity["command"] = "verbose"
verbosity["value"] = True
commands.append(verbosity)
groups = dict()
groups["type"] = "dictionary"
groups["command"] = "groups"
groups["dictionary"] = dict()
host_names = []
for host in input_definitions["hosts"]:
host_names.append(host["name"])
groups["dictionary"]["hosts"] = host_names
router_names = []
for router in input_definitions["routers"]:
router_names.append(router["name"])
groups["dictionary"]["routers"] = router_names
commands.append(groups)
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
107
108
109
110
111
112
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(input_definitions, 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_PLAYBOOK, input_definitions, 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(
USER_PLAYBOOK, input_definitions, 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(input_definitions, flags))
return vagrant_definitions
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
"""
vagrant_definitions = _build_vagrant_definitions(input_definitions, flags)
generate_file("vagrantfile", "Vagrantfile", defs=vagrant_definitions)