From 76c9a9f23859a2296541f71d3743a5049d7633cd Mon Sep 17 00:00:00 2001
From: Attila Farkas <ati@mail.muni.cz>
Date: Tue, 2 Jun 2020 10:47:41 +0200
Subject: [PATCH] fix ansible role not adding second route

---
 modules/ansible_vars_generator.py | 10 ++--
 modules/routing_generator.py      | 91 +++++++++++++++++--------------
 templates/br                      | 24 ++------
 templates/separate_devices        | 24 +++-----
 4 files changed, 69 insertions(+), 80 deletions(-)

diff --git a/modules/ansible_vars_generator.py b/modules/ansible_vars_generator.py
index 3726662..1495731 100644
--- a/modules/ansible_vars_generator.py
+++ b/modules/ansible_vars_generator.py
@@ -2,7 +2,7 @@
 
 from conf.border_router import BORDER_ROUTER_NETWORK_NAME
 from modules.file_manager import generate_file, dump_to_yaml
-from modules.routing_generator import add_routings
+from modules.routing_generator import add_routes
 
 
 def _find_networks_of_device(name, input_definitions):
@@ -69,8 +69,8 @@ def _generate_device_vars(input_definitions, flags):
         variables = dict()
         variables["aliases"] = _add_aliases(target_host["name"],
                                             input_definitions, flags)
-        variables["routes"] = add_routings(target_host["name"], "host",
-                                           input_definitions, flags)
+        variables["routes"] = add_routes(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["routes"] = add_routings(target_router["name"], "router",
-                                           input_definitions, flags)
+        variables["routes"] = add_routes(target_router["name"], "router",
+                                         input_definitions, flags)
         dump_to_yaml(variables, "base_provisioning/roles/" +
                      target_router["name"] + "/vars/main.yml")
 
diff --git a/modules/routing_generator.py b/modules/routing_generator.py
index 3f1ac39..1bc6892 100644
--- a/modules/routing_generator.py
+++ b/modules/routing_generator.py
@@ -63,10 +63,38 @@ def _find_router_ip_in_br_network(other_network, input_definitions):
             return router_mapping["ip"]
 
 
+def _add_interface_route(route, target_interface_ip, target_routes_list):
+    """Add route to list of routes with the given interface."""
+    for interface in target_routes_list:
+        if interface["interface_ip"] == target_interface_ip:
+            interface["interface_routes"].append(route)
+            return
+
+    new_interface = dict()
+    new_interface["interface_ip"] = target_interface_ip
+    new_interface["interface_default_gateway"] = ""
+    new_interface["interface_routes"] = [route]
+    target_routes_list.append(new_interface)
+
+
+def _add_default_route(default_gateway, target_interface_ip,
+                       target_routes_list):
+    """Add default route to the given interface."""
+    for interface in target_routes_list:
+        if interface["interface_ip"] == target_interface_ip:
+            interface["interface_default_gateway"] = default_gateway
+            return
+
+    new_interface = dict()
+    new_interface["interface_ip"] = target_interface_ip
+    new_interface["interface_default_gateway"] = default_gateway
+    new_interface["interface_routes"] = []
+    target_routes_list.append(new_interface)
+
+
 def _create_host_routing(target_host_name, input_definitions, flags):
-    """Generate routes for the given host."""
-    simple_routes = []
-    default_route = None
+    """Generate list of routes for the given host."""
+    routes = []
     mapping = None
 
     for host_mapping in input_definitions["net_mappings"]:
@@ -78,93 +106,74 @@ def _create_host_routing(target_host_name, input_definitions, flags):
         raise ValueError("Host was not found: " + target_host_name)
 
     if flags["border_router"]:
-        default_route = dict()
-        default_route["interface_ip"] = mapping["ip"]
-        gateway = _find_router_in_network(mapping["network"],
-                                          input_definitions)
-        default_route["gateway"] = gateway
+        gateway = _find_router_in_network(mapping["network"], input_definitions)
+        _add_default_route(gateway, mapping["ip"], routes)
     else:
         for network in input_definitions["networks"]:
             if network["name"] == mapping["network"]:
                 continue
             routing_to_other_hosts = dict()
-            routing_to_other_hosts["interface_ip"] = mapping["ip"]
             gateway = _find_router_in_network(mapping["network"],
                                               input_definitions)
             routing_to_other_hosts["gateway"] = gateway
             net_ip, mask = network["cidr"].split('/')
             routing_to_other_hosts["network"] = net_ip
-            routing_to_other_hosts["netmask"] = mask
-            simple_routes.append(routing_to_other_hosts)
+            routing_to_other_hosts["mask"] = mask
+            _add_interface_route(routing_to_other_hosts, mapping["ip"], routes)
 
-    return simple_routes, default_route
+    return routes
 
 
 def _create_router_routing(router_name, input_definitions, flags):
-    """Generate routes for the given router."""
-    simple_routes = []
-    default_route = None
+    """Generate list of routes for the given router."""
+    routes = []
 
     if flags["border_router"]:
-        default_route = dict()
         interface_ip = _find_iface_ip_in_network(router_name,
                                                  BORDER_ROUTER_NETWORK_NAME,
                                                  input_definitions)
-        default_route["interface_ip"] = interface_ip
-        default_route["gateway"] = BORDER_ROUTER_IP
+        _add_default_route(BORDER_ROUTER_IP, interface_ip, routes)
 
-    return simple_routes, default_route
+    return routes
 
 
 def _create_border_router_routing(input_definitions):
     """Generate routes for the border router."""
-    simple_routes = []
-    default_route = None
+    routes = []
 
     for network in input_definitions["networks"]:
         if network["name"] == BORDER_ROUTER_NETWORK_NAME:
             continue
         routing_to_hosts = dict()
-        routing_to_hosts["interface_ip"] = BORDER_ROUTER_IP
         net_ip, mask = network["cidr"].split('/')
         routing_to_hosts["network"] = net_ip
-        routing_to_hosts["netmask"] = mask
+        routing_to_hosts["mask"] = mask
         gateway = _find_router_ip_in_br_network(network["name"],
                                                 input_definitions)
         routing_to_hosts["gateway"] = gateway
-        simple_routes.append(routing_to_hosts)
+        _add_interface_route(routing_to_hosts, BORDER_ROUTER_IP, routes)
 
-    return simple_routes, default_route
+    return routes
 
 
-def add_routings(device_name, device_type, input_definitions, flags):
+def add_routes(device_name, device_type, input_definitions, flags):
     """Generate simple and default routes for the given device.
 
     Returns a list of dicts with the syntax:
     - gateway: ip of the target device
       interface_ip: ip of the device on the given interface
       network: ip of the network (if default is False)
-      netmask: mask of the network (if default is False)
+      mask: mask of the network (if default is False)
     """
     if not input_definitions["routers"]:
-        return dict()
-
-    routes = {"simple": [], "default": dict()}
+        return []
 
     if device_type == "host":
-        simple, default = _create_host_routing(device_name, input_definitions,
-                                               flags)
+        return _create_host_routing(device_name, input_definitions, flags)
     elif device_type == "router":
         if device_name != BORDER_ROUTER_NAME:
-            simple, default = _create_router_routing(device_name,
-                                                     input_definitions, flags)
+            return _create_router_routing(device_name, input_definitions, flags)
         else:
-            simple, default = _create_border_router_routing(input_definitions)
+            return _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 7bbe793..e9201f9 100644
--- a/templates/br
+++ b/templates/br
@@ -1,32 +1,20 @@
 ---
-# Configuration of the border router
-
 - name: Adding aliases
   loop: "{{ aliases | dict2items }}"
   lineinfile:
     path: /etc/hosts
     line: "{{ item.value }} {{ item.key }}"
 
-- name: Set up nondefault routes
+- name: Configuring routes
   include_role:
     name: interface
   vars:
-    interface_ip: "{{ route.interface_ip }}"
-    interface_routes:
-      - gateway: "{{ route.gateway }}"
-        network: "{{ route.network }}"
-        mask: "{{ route.netmask }}"
-  loop: "{{ routes.simple }}"
+    interface_ip: "{{ interface.interface_ip }}"
+    interface_default_gateway: "{{ interface.interface_default_gateway }}"
+    interface_routes: "{{ interface.interface_routes }}"
+  loop: "{{ routes }}"
   loop_control:
-    loop_var: route
-
-- name: Configuring default routes
-  include_role:
-    name: interface
-  vars:
-    interface_ip: "{{ routes.default.interface_ip }}"
-    interface_default_gateway: "{{ routes.default.gateway }}"
-  when: routes.default
+    loop_var: interface
 
 - name: Set up postrouting
   iptables:
diff --git a/templates/separate_devices b/templates/separate_devices
index 909c85c..4181f0a 100644
--- a/templates/separate_devices
+++ b/templates/separate_devices
@@ -1,26 +1,18 @@
+---
 - name: Adding aliases
   loop: "{{ aliases | dict2items }}"
   lineinfile:
     path: /etc/hosts
     line: "{{ item.value }} {{ item.key }}"
 
-- name: Configuring nondefault routes
+- name: Configuring routes
   include_role:
     name: interface
   vars:
-    interface_ip: "{{ route.interface_ip }}"
-    interface_routes:
-      - gateway: "{{ route.gateway }}"
-        network: "{{ route.network }}"
-        mask: "{{ route.netmask }}"
-  loop: "{{ routes.simple }}"
+    interface_ip: "{{ interface.interface_ip }}"
+    interface_default_gateway: "{{ interface.interface_default_gateway }}"
+    interface_routes: "{{ interface.interface_routes }}"
+  loop: "{{ routes }}"
   loop_control:
-    loop_var: route
-
-- name: Configuring default routes
-  include_role:
-    name: interface
-  vars:
-    interface_ip: "{{ routes.default.interface_ip }}"
-    interface_default_gateway: "{{ routes.default.gateway }}"
-  when: routes.default
\ No newline at end of file
+    loop_var: interface
+...
\ No newline at end of file
-- 
GitLab