From 63bb421b3d6e966937a3e9e1ae8f55ae343070c5 Mon Sep 17 00:00:00 2001
From: Attila Farkas <ati@mail.muni.cz>
Date: Fri, 29 May 2020 09:49:10 +0200
Subject: [PATCH] change routes so that only one default route can be defined
 on a device

---
 modules/ansible_vars_generator.py | 20 ++-------
 modules/routing_generator.py      | 75 ++++++++++++++++---------------
 templates/br                      | 12 +++--
 templates/separate_devices        | 10 ++---
 4 files changed, 52 insertions(+), 65 deletions(-)

diff --git a/modules/ansible_vars_generator.py b/modules/ansible_vars_generator.py
index b444a83..3726662 100644
--- a/modules/ansible_vars_generator.py
+++ b/modules/ansible_vars_generator.py
@@ -69,8 +69,8 @@ def _generate_device_vars(input_definitions, flags):
         variables = dict()
         variables["aliases"] = _add_aliases(target_host["name"],
                                             input_definitions, flags)
-        variables["routings"] = add_routings(target_host["name"], "host",
-                                             input_definitions, flags)
+        variables["routes"] = add_routings(target_host["name"], "host",
+                                           input_definitions, flags)
         dump_to_yaml(variables, "base_provisioning/roles/" +
                      target_host["name"] + "/vars/main.yml")
 
@@ -78,8 +78,8 @@ def _generate_device_vars(input_definitions, flags):
         variables = dict()
         variables["aliases"] = _add_aliases(target_router["name"],
                                             input_definitions, flags)
-        variables["routings"] = add_routings(target_router["name"], "router",
-                                             input_definitions, flags)
+        variables["routes"] = add_routings(target_router["name"], "router",
+                                           input_definitions, flags)
         dump_to_yaml(variables, "base_provisioning/roles/" +
                      target_router["name"] + "/vars/main.yml")
 
@@ -109,14 +109,6 @@ def _find_ip(device_name, input_definitions):
     return networks
 
 
-def _find_default_route(device_name, input_definitions, flags):
-    """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):
     """Generate vars file for all devices."""
 # TODO check what vars needs to be in config
@@ -126,8 +118,6 @@ def _generate_config_vars(input_definitions, flags):
         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)
         hosts.append(new_host)
 
     routers = []
@@ -135,8 +125,6 @@ def _generate_config_vars(input_definitions, flags):
         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)
         routers.append(new_router)
 
     generate_file("config", "base_provisioning/config.yml", hosts=hosts,
diff --git a/modules/routing_generator.py b/modules/routing_generator.py
index 0c19a37..3f1ac39 100644
--- a/modules/routing_generator.py
+++ b/modules/routing_generator.py
@@ -62,23 +62,27 @@ def _find_router_ip_in_br_network(other_network, input_definitions):
            router_mapping["network"] == BORDER_ROUTER_NETWORK_NAME:
             return router_mapping["ip"]
 
+
 def _create_host_routing(target_host_name, input_definitions, flags):
-    """Generate routings for the given host."""
-    simple_routings = []
-    default_routings = []
+    """Generate routes for the given host."""
+    simple_routes = []
+    default_route = None
+    mapping = None
 
     for host_mapping in input_definitions["net_mappings"]:
         if host_mapping["host"] == target_host_name:
             mapping = host_mapping
             break
 
+    if not mapping:
+        raise ValueError("Host was not found: " + target_host_name)
+
     if flags["border_router"]:
-        routing_to_router = dict()
-        routing_to_router["interface_ip"] = mapping["ip"]
+        default_route = dict()
+        default_route["interface_ip"] = mapping["ip"]
         gateway = _find_router_in_network(mapping["network"],
                                           input_definitions)
-        routing_to_router["gateway"] = gateway
-        default_routings.append(routing_to_router)
+        default_route["gateway"] = gateway
     else:
         for network in input_definitions["networks"]:
             if network["name"] == mapping["network"]:
@@ -91,32 +95,31 @@ def _create_host_routing(target_host_name, input_definitions, flags):
             net_ip, mask = network["cidr"].split('/')
             routing_to_other_hosts["network"] = net_ip
             routing_to_other_hosts["netmask"] = mask
-            simple_routings.append(routing_to_other_hosts)
+            simple_routes.append(routing_to_other_hosts)
 
-    return simple_routings, default_routings
+    return simple_routes, default_route
 
 
 def _create_router_routing(router_name, input_definitions, flags):
-    """Generate routings for the given router."""
-    simple_routings = []
-    default_routings = []
+    """Generate routes for the given router."""
+    simple_routes = []
+    default_route = None
 
     if flags["border_router"]:
-        routing_to_br = dict()
+        default_route = dict()
         interface_ip = _find_iface_ip_in_network(router_name,
                                                  BORDER_ROUTER_NETWORK_NAME,
                                                  input_definitions)
-        routing_to_br["interface_ip"] = interface_ip
-        routing_to_br["gateway"] = BORDER_ROUTER_IP
-        default_routings.append(routing_to_br)
+        default_route["interface_ip"] = interface_ip
+        default_route["gateway"] = BORDER_ROUTER_IP
 
-    return simple_routings, default_routings
+    return simple_routes, default_route
 
 
-def _create_border_router_routing(input_definitions, flags):
-    """Generate routings for the border router."""
-    simple_routings = []
-    default_routings = []
+def _create_border_router_routing(input_definitions):
+    """Generate routes for the border router."""
+    simple_routes = []
+    default_route = None
 
     for network in input_definitions["networks"]:
         if network["name"] == BORDER_ROUTER_NETWORK_NAME:
@@ -129,13 +132,13 @@ def _create_border_router_routing(input_definitions, flags):
         gateway = _find_router_ip_in_br_network(network["name"],
                                                 input_definitions)
         routing_to_hosts["gateway"] = gateway
-        simple_routings.append(routing_to_hosts)
+        simple_routes.append(routing_to_hosts)
 
-    return simple_routings, default_routings
+    return simple_routes, default_route
 
 
 def add_routings(device_name, device_type, input_definitions, flags):
-    """Generate simple and default routings for the given device.
+    """Generate simple and default routes for the given device.
 
     Returns a list of dicts with the syntax:
     - gateway: ip of the target device
@@ -146,22 +149,22 @@ def add_routings(device_name, device_type, input_definitions, flags):
     if not input_definitions["routers"]:
         return dict()
 
-    routings = {"simple": [], "default": []}
+    routes = {"simple": [], "default": dict()}
 
     if device_type == "host":
         simple, default = _create_host_routing(device_name, input_definitions,
                                                flags)
-        routings["simple"].extend(simple)
-        routings["default"].extend(default)
     elif device_type == "router":
         if device_name != BORDER_ROUTER_NAME:
-            simple, default =  _create_router_routing(device_name,
-                                                      input_definitions, flags)
-            routings["simple"].extend(simple)
-            routings["default"].extend(default)
+            simple, default = _create_router_routing(device_name,
+                                                     input_definitions, flags)
         else:
-            simple, default = _create_border_router_routing(input_definitions,
-                                                        flags)
-            routings["simple"].extend(simple)
-            routings["default"].extend(default)
-    return routings
+            simple, default = _create_border_router_routing(input_definitions)
+    else:
+        raise KeyError("Unsupported device type: " + str(device_type))
+
+    routes["simple"] = simple
+    if default:
+        routes["default"] = default
+
+    return routes
diff --git a/templates/br b/templates/br
index 4bb1ca7..7bbe793 100644
--- a/templates/br
+++ b/templates/br
@@ -16,19 +16,17 @@
       - gateway: "{{ route.gateway }}"
         network: "{{ route.network }}"
         mask: "{{ route.netmask }}"
-  loop: "{{ routings.simple }}"
+  loop: "{{ routes.simple }}"
   loop_control:
     loop_var: route
 
-- name: Set up default route
+- name: Configuring default routes
   include_role:
     name: interface
   vars:
-    interface_ip: "{{ route.interface_ip }}"
-    interface_default_gateway: "{{ route.gateway }}"
-  loop: "{{ routings.default }}"
-  loop_control:
-    loop_var: route
+    interface_ip: "{{ routes.default.interface_ip }}"
+    interface_default_gateway: "{{ routes.default.gateway }}"
+  when: routes.default
 
 - name: Set up postrouting
   iptables:
diff --git a/templates/separate_devices b/templates/separate_devices
index 83f5b70..909c85c 100644
--- a/templates/separate_devices
+++ b/templates/separate_devices
@@ -13,7 +13,7 @@
       - gateway: "{{ route.gateway }}"
         network: "{{ route.network }}"
         mask: "{{ route.netmask }}"
-  loop: "{{ routings.simple }}"
+  loop: "{{ routes.simple }}"
   loop_control:
     loop_var: route
 
@@ -21,8 +21,6 @@
   include_role:
     name: interface
   vars:
-    interface_ip: "{{ route.interface_ip }}"
-    interface_default_gateway: "{{ route.gateway }}"
-  loop: "{{ routings.default }}"
-  loop_control:
-    loop_var: route
+    interface_ip: "{{ routes.default.interface_ip }}"
+    interface_default_gateway: "{{ routes.default.gateway }}"
+  when: routes.default
\ No newline at end of file
-- 
GitLab