Fix quagga peering by working around the NAT 47/30347/2
authorRomanos Skiadas <rski@intracom-telecom.com>
Mon, 13 Mar 2017 13:08:54 +0000 (15:08 +0200)
committerRomanos Skiadas <rski@intracom-telecom.com>
Tue, 14 Mar 2017 07:29:58 +0000 (09:29 +0200)
Quagga peering doesn't seem to work over the NATted openstack external
network. To work around this, directly patch the quagga instance to the
external network and give it a fixed IP in that network. Then, all the
peering traffic goes over that patched interface.

Change-Id: I8d9d8fef4e86839c821f83e564d5c49cc15e43ae
JIRA: SDNVPN-114
Signed-off-by: Romanos Skiadas <rski@intracom-telecom.com>
sdnvpn/artifacts/quagga_setup.sh
sdnvpn/lib/quagga.py
sdnvpn/test/functest/testcase_3.py

index d52cbed..8a90198 100644 (file)
@@ -12,6 +12,11 @@ sleep 20
 # Variables to be filled in with python
 NEIGHBOR_IP=%s
 OWN_IP=%s
+# directly access the instance from the external net without NAT
+EXT_NET_MASK=%s
+
+ip link set ens7 up
+ip addr add $OWN_IP/$EXT_NET_MASK dev ens7
 
 ZEBRA_CONFIG_LOCATION="/etc/quagga/zebra.conf"
 DAEMONS_FILE_LOCATION="/etc/quagga/daemons"
index e2885c2..9f8a4cd 100644 (file)
@@ -29,10 +29,14 @@ def bootstrap_quagga(fip_addr, controller_ip):
     return rc == 0
 
 
-def gen_quagga_setup_script(controller_ip, instance_floating_ip):
+def gen_quagga_setup_script(controller_ip,
+                            fake_floating_ip,
+                            ext_net_mask):
     with open(COMMON_CONFIG.quagga_setup_script_path) as f:
         template = f.read()
-    script = template % (controller_ip, instance_floating_ip)
+    script = template % (controller_ip,
+                         fake_floating_ip,
+                         ext_net_mask)
     return script
 
 
index 38d0d8f..0253444 100644 (file)
@@ -53,6 +53,7 @@ def main():
 
     controllers = [node for node in openstack_nodes
                    if node.is_odl()]
+    computes = [node for node in openstack_nodes if node.is_compute()]
     msg = ("Verify that OpenDaylight can start/communicate with zrpcd/Quagga")
     results.record_action(msg)
     results.add_to_summary(0, "-")
@@ -85,7 +86,6 @@ def main():
 
         results.add_to_summary(0, "-")
 
-        # TODO here we need the external ip of the controller
         start_quagga = "odl:configure-bgp -op start-bgp-server " \
                        "--as-num 100 --router-id {0}".format(controller.ip)
         test_utils.run_odl_cmd(controller, start_quagga)
@@ -181,9 +181,27 @@ def main():
     # We also create the FIP first because it is used in the
     # cloud-init script.
     fip = os_utils.create_floating_ip(neutron_client)
-
+    # fake_fip is needed to bypass NAT
+    # see below for the reason why.
+    fake_fip = os_utils.create_floating_ip(neutron_client)
+    # pin quagga to some compute
+    compute_node = nova_client.hypervisors.list()[0]
+    quagga_compute_node = "nova:" + compute_node.hypervisor_hostname
+    # Map the hypervisor used above to a compute handle
+    # returned by releng's manager
+    for comp in computes:
+        if compute_node.host_ip in comp.run_cmd("ip a"):
+            compute = comp
+            break
+    # Get the mask of ext net of the compute where quagga is running
+    # TODO check this works on apex
+    cmd = "ip a | grep br-ex | grep inet | awk '{print $2}'"
+    ext_cidr = compute.run_cmd(cmd).split("/")
+    ext_net_mask = ext_cidr[1]
     quagga_bootstrap_script = quagga.gen_quagga_setup_script(
-        controllers[0].ip, fip['fip_addr'])
+        controllers[0].ip,
+        fake_fip['fip_addr'],
+        ext_net_mask)
     quagga_vm = test_utils.create_instance(
         nova_client,
         TESTCASE_CONFIG.quagga_instance_name,
@@ -192,7 +210,9 @@ def main():
         sg_id,
         fixed_ip=TESTCASE_CONFIG.quagga_instance_ip,
         flavor=TESTCASE_CONFIG.quagga_instance_flavor,
-        userdata=quagga_bootstrap_script)
+        userdata=quagga_bootstrap_script,
+        compute_node=quagga_compute_node)
+
     fip_added = os_utils.add_floating_ip(nova_client,
                                          quagga_vm.id,
                                          fip['fip_addr'])
@@ -211,6 +231,15 @@ def main():
         results.add_failure(testcase)
     results.add_to_summary(0, "=")
 
+    # This part works around NAT
+    # What we do is attach the instance directly to the OpenStack
+    # external network. This way is is directly accessible from the
+    # controller without NAT. We assign a floating IP for this
+    # to make sure no overlaps happen.
+    libvirt_instance_name = getattr(quagga_vm, "OS-EXT-SRV-ATTR:instance_name")
+    compute.run_cmd("virsh attach-interface %s"
+                    " bridge br-ex" % libvirt_instance_name)
+
     results.add_to_summary(0, '-')
     results.add_to_summary(1, "Peer Quagga with OpenDaylight")
     results.add_to_summary(0, '-')