From 5cb7a20804e4259e4c06716a1743ba7fbaf68740 Mon Sep 17 00:00:00 2001 From: sridhargaddam Date: Wed, 25 Feb 2015 05:42:47 +0000 Subject: [PATCH] Default route missing for IPv6 subnets in HA Router In an HA setup, keepalived would configure the default gateway (in the master HA router) by parsing the "virtual_routes" section of keepalived.conf file. The "virtual_routes" section is properly constructed for an IPv4 subnet, but requires a minor change for IPv6 subnets. Conflicts: neutron/agent/l3_ha_agent.py neutron/tests/functional/agent/test_l3_agent.py Closes-Bug: #1414937 Change-Id: I54070e048577292d98d86fcc9ca8b9d3e72b4ebe (cherry picked from commit a1318ae187f1695e2e49bbde32eb75230e96aefe) --- neutron/agent/l3_ha_agent.py | 9 +++-- .../tests/functional/agent/test_l3_agent.py | 38 +++++++++++++------ neutron/tests/unit/test_l3_agent.py | 6 +-- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/neutron/agent/l3_ha_agent.py b/neutron/agent/l3_ha_agent.py index 9a41c58a9e3..d16ccb9e5a9 100644 --- a/neutron/agent/l3_ha_agent.py +++ b/neutron/agent/l3_ha_agent.py @@ -207,13 +207,15 @@ class AgentMixin(object): def _add_default_gw_virtual_route(self, ri, ex_gw_port, interface_name): gw_ip = ex_gw_port['subnet']['gateway_ip'] if gw_ip: + default_gw = ('0.0.0.0/0' if netaddr.IPAddress(gw_ip).version == 4 + else '::/0') instance = ri.keepalived_manager.config.get_instance(ri.ha_vr_id) instance.virtual_routes = ( [route for route in instance.virtual_routes - if route.destination != '0.0.0.0/0']) + if route.destination != default_gw]) instance.virtual_routes.append( keepalived.KeepalivedVirtualRoute( - '0.0.0.0/0', gw_ip, interface_name)) + default_gw, gw_ip, interface_name)) def _ha_external_gateway_added(self, ri, ex_gw_port, interface_name): self._add_vip(ri, ex_gw_port['ip_cidr'], interface_name) @@ -263,8 +265,9 @@ class AgentMixin(object): instance = ri.keepalived_manager.config.get_instance(ri.ha_vr_id) # Filter out all of the old routes while keeping only the default route + default_gw = ('::/0', '0.0.0.0/0') instance.virtual_routes = [route for route in instance.virtual_routes - if route.destination == '0.0.0.0/0'] + if route.destination in default_gw] for route in new_routes: instance.virtual_routes.append(keepalived.KeepalivedVirtualRoute( route['destination'], diff --git a/neutron/tests/functional/agent/test_l3_agent.py b/neutron/tests/functional/agent/test_l3_agent.py index ac26b85f30e..0b92cb12d83 100644 --- a/neutron/tests/functional/agent/test_l3_agent.py +++ b/neutron/tests/functional/agent/test_l3_agent.py @@ -62,12 +62,18 @@ class L3AgentTestFramework(base.BaseOVSLinuxTestCase): mock.patch.object(self.agent, '_send_gratuitous_arp_packet').start() - def manage_router(self, enable_ha): - router = test_l3_agent.prepare_router_data(enable_snat=True, - enable_floating_ip=True, - enable_ha=enable_ha) - self.addCleanup(self._delete_router, router['id']) - ri = self._create_router(router) + def manage_router(self, enable_ha, ip_version=4, enable_fip=True, + enable_snat=True): + if ip_version == 6: + enable_snat = False + enable_fip = False + + r = test_l3_agent.prepare_router_data(ip_version=ip_version, + enable_snat=enable_snat, + enable_floating_ip=enable_fip, + enable_ha=enable_ha) + self.addCleanup(self._delete_router, r['id']) + ri = self._create_router(r) return ri def _create_router(self, router): @@ -183,6 +189,9 @@ class L3AgentTestCase(L3AgentTestFramework): def test_ha_router_lifecycle(self): self._router_lifecycle(enable_ha=True) + def test_ipv6_ha_router_lifecycle(self): + self._router_lifecycle(enable_ha=True, ip_version=6) + def test_keepalived_configuration(self): router = self.manage_router(enable_ha=True) expected = self.get_expected_keepalive_configuration(router) @@ -214,8 +223,8 @@ class L3AgentTestCase(L3AgentTestFramework): self.assertNotIn(old_external_device_ip, new_config) self.assertIn(new_external_device_ip, new_config) - def _router_lifecycle(self, enable_ha): - router = self.manage_router(enable_ha) + def _router_lifecycle(self, enable_ha, ip_version=4): + router = self.manage_router(enable_ha, ip_version) if enable_ha: port = self.agent._get_ex_gw_port(router) @@ -236,10 +245,15 @@ class L3AgentTestCase(L3AgentTestFramework): self.assertTrue(self._metadata_proxy_exists(router)) self._assert_internal_devices(router) self._assert_external_device(router) - self._assert_gateway(router) - self._assert_floating_ips(router) - self._assert_snat_chains(router) - self._assert_floating_ip_chains(router) + if ip_version == 4: + # Note(SridharG): enable the assert_gateway for IPv6 once + # keepalived on Ubuntu14.04 (i.e., check-neutron-dsvm-functional + # platform) is updated to 1.2.10 (or above). + # For more details: https://review.openstack.org/#/c/151284/ + self._assert_gateway(router) + self._assert_floating_ips(router) + self._assert_snat_chains(router) + self._assert_floating_ip_chains(router) if enable_ha: self._assert_ha_device(router) diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index 12b2cdfefdc..56cd0b9c34a 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -213,9 +213,9 @@ def router_append_interface(router, count=1, ip_version=4, ra_mode=None, cidr_pool = '35.4.%i.0/24' gw_pool = '35.4.%i.1' elif ip_version == 6: - ip_pool = 'fd01:%x::6' - cidr_pool = 'fd01:%x::/64' - gw_pool = 'fd01:%x::1' + ip_pool = 'fd01:%x:1::6' + cidr_pool = 'fd01:%x:1::/64' + gw_pool = 'fd01:%x:1::1' else: raise ValueError("Invalid ip_version: %s" % ip_version)