Something went wrong on our end
-
Attila Farkas authoredccb50975
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
vagrant_generator.py 8.30 KiB
"""Contains functions for generating a Vagrantfile from input 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):
"""Create simple vagrant attributes like string, integer or boolean."""
attribute = dict()
attribute["type"] = attribute_type
attribute["command"] = key
attribute["value"] = value
return attribute
def _create_complex_attribute(key, value):
"""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["value"] = value
return attribute
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"]:
vagrant_attribute = VAGRANT_MAPPING["string"][attribute]
commands.append(_create_simple_attribute(vagrant_attribute, value,
"string"))
elif attribute in VAGRANT_MAPPING["boolean"]:
vagrant_attribute = VAGRANT_MAPPING["boolean"][attribute]
commands.append(_create_simple_attribute(vagrant_attribute, value,
"boolean"))
elif attribute in VAGRANT_MAPPING["integer"]:
vagrant_attribute = VAGRANT_MAPPING["integer"][attribute]
commands.append(_create_simple_attribute(vagrant_attribute, value,
"integer"))
elif attribute in VAGRANT_MAPPING["other"]:
vagrant_attribute = VAGRANT_MAPPING["other"][attribute]
commands.append(_create_complex_attribute(vagrant_attribute,
value))
elif attribute in VIRTUALBOX_MAPPING["integer"]:
vagrant_attribute = VIRTUALBOX_MAPPING["integer"][attribute]
vb_commands.append(_create_simple_attribute(vagrant_attribute,
value, "integer"))
if vb_commands:
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):
"""Create 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"] = "string"
verbosity["command"] = "verbose"
verbosity["value"] = "vvvv"
commands.append(verbosity)
groups = dict()
groups["type"] = "groups"
groups["groups"] = dict()
host_names = []
for host in input_definitions["hosts"]:
host_names.append(host["name"])
groups["groups"]["hosts"] = host_names
router_names = []
for router in input_definitions["routers"]:
router_names.append(router["name"])
groups["groups"]["routers"] = router_names
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\""
commands.append(extravars)
return commands
def _find_netmask(network_name, networks):
"""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):
"""Add 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):
"""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)
elif definition["type"] == "router":
_add_networks_to_device(definition,
input_definitions["router_mappings"],
input_definitions)
def _call_provisioner(input_definitions, flags):
"""Create 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):
"""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)
vagrant_definitions.append(device)
for host in input_definitions["hosts"]:
device = dict()
device["type"] = "host"
device["name"] = host["name"]
device["commands"] = _create_commands(host)
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):
"""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)