summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSwaminathan Vasudevan <swaminathan.vasudevan@hpe.com>2016-07-05 13:22:04 -0700
committerSwaminathan Vasudevan <swaminathan.vasudevan@hpe.com>2016-08-30 14:38:35 -0700
commitbce58c6410dd1f464746e81c71e045f4548bd437 (patch)
treeee50a8ef47c03dcfa7adc6eea0e5dacc933f2c38
parent9cd2dfceae43c68e17b95beec697cde12f718a21 (diff)
downloadneutron-bce58c6410dd1f464746e81c71e045f4548bd437.tar.gz
DVR: Cleanup the stale snat redirect rules in router namespace
After the stale snat namespace is deleted the snat redirect rules in router namespace should be cleaned. Here we are basically reading the ip rule from the router namespace and just cleaning up all the snat redirect rules leaving the default ones untouched. Closes-Bug: #1599287 (cherry picked from commit 34e51cad42960bdb08a92d1a60a33594bdf057ba) Conflicts: neutron/tests/functional/agent/l3/test_dvr_router.py Change-Id: Ic505a46e56d9e950bd36a1596d3f1adfb5ef5577
-rw-r--r--neutron/agent/l3/dvr_local_router.py26
-rw-r--r--neutron/agent/l3/router_info.py7
-rw-r--r--neutron/tests/functional/agent/test_l3_agent.py27
3 files changed, 60 insertions, 0 deletions
diff --git a/neutron/agent/l3/dvr_local_router.py b/neutron/agent/l3/dvr_local_router.py
index a067bb436a..f6e52c4012 100644
--- a/neutron/agent/l3/dvr_local_router.py
+++ b/neutron/agent/l3/dvr_local_router.py
@@ -292,6 +292,32 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
except exceptions.DeviceNotFoundError:
pass
+ def _stale_ip_rule_cleanup(self, ns_ipr, ns_ipd, ip_version):
+ ip_rules_list = ns_ipr.rule.list_rules(ip_version)
+ snat_table_list = []
+ for ip_rule in ip_rules_list:
+ snat_table = ip_rule['table']
+ priority = ip_rule['priority']
+ if snat_table in ['local', 'default', 'main']:
+ continue
+ if (ip_version == l3_constants.IP_VERSION_4 and
+ snat_table in range(dvr_fip_ns.FIP_PR_START,
+ dvr_fip_ns.FIP_PR_END)):
+ continue
+ gateway_cidr = ip_rule['from']
+ ns_ipr.rule.delete(ip=gateway_cidr,
+ table=snat_table,
+ priority=priority)
+ snat_table_list.append(snat_table)
+ for tb in snat_table_list:
+ ns_ipd.route.flush(ip_version, table=tb)
+
+ def gateway_redirect_cleanup(self, rtr_interface):
+ ns_ipr = ip_lib.IPRule(namespace=self.ns_name)
+ ns_ipd = ip_lib.IPDevice(rtr_interface, namespace=self.ns_name)
+ self._stale_ip_rule_cleanup(ns_ipr, ns_ipd, l3_constants.IP_VERSION_4)
+ self._stale_ip_rule_cleanup(ns_ipr, ns_ipd, l3_constants.IP_VERSION_6)
+
def _snat_redirect_modify(self, gateway, sn_port, sn_int, is_add):
"""Adds or removes rules and routes for SNAT redirection."""
try:
diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py
index e22bc93d74..60ae7a32b6 100644
--- a/neutron/agent/l3/router_info.py
+++ b/neutron/agent/l3/router_info.py
@@ -197,6 +197,9 @@ class RouterInfo(object):
def add_floating_ip(self, fip, interface_name, device):
raise NotImplementedError()
+ def gateway_redirect_cleanup(self, rtr_interface):
+ pass
+
def remove_floating_ip(self, device, ip_cidr):
device.delete_addr_and_conntrack_state(ip_cidr)
@@ -599,6 +602,10 @@ class RouterInfo(object):
elif not ex_gw_port and self.ex_gw_port:
self.external_gateway_removed(self.ex_gw_port, interface_name)
pd.remove_gw_interface(self.router['id'])
+ elif not ex_gw_port and not self.ex_gw_port:
+ for p in self.internal_ports:
+ interface_name = self.get_internal_device_name(p['id'])
+ self.gateway_redirect_cleanup(interface_name)
existing_devices = self._get_existing_devices()
stale_devs = [dev for dev in existing_devices
diff --git a/neutron/tests/functional/agent/test_l3_agent.py b/neutron/tests/functional/agent/test_l3_agent.py
index 879645fe38..e82591a425 100644
--- a/neutron/tests/functional/agent/test_l3_agent.py
+++ b/neutron/tests/functional/agent/test_l3_agent.py
@@ -1700,6 +1700,33 @@ class TestDvrRouter(L3AgentTestFramework):
self.assertFalse(sg_device)
self.assertTrue(qg_device)
+ def test_dvr_router_gateway_redirect_cleanup_on_agent_restart(self):
+ """Test to validate the router namespace gateway redirect rule cleanup.
+
+ This test checks for the non existence of the gateway redirect
+ rules in the router namespace after the agent restarts while the
+ gateway is removed for the router.
+ """
+ self.agent.conf.agent_mode = 'dvr_snat'
+ router_info = self.generate_dvr_router_info()
+ router1 = self.manage_router(self.agent, router_info)
+ self._assert_snat_namespace_exists(router1)
+ self.assertTrue(self._namespace_exists(router1.ns_name))
+ restarted_agent = neutron_l3_agent.L3NATAgentWithStateReport(
+ self.agent.host, self.agent.conf)
+ router1.router['gw_port'] = ""
+ router1.router['gw_port_host'] = ""
+ router1.router['external_gateway_info'] = ""
+ restarted_router = self.manage_router(restarted_agent, router1.router)
+ self.assertTrue(self._namespace_exists(restarted_router.ns_name))
+ ns_ipr = ip_lib.IPRule(namespace=router1.ns_name)
+ ip4_rules_list = ns_ipr.rule.list_rules(l3_constants.IP_VERSION_4)
+ ip6_rules_list = ns_ipr.rule.list_rules(l3_constants.IP_VERSION_6)
+ # Just make sure the basic set of rules are there in the router
+ # namespace
+ self.assertEqual(3, len(ip4_rules_list))
+ self.assertEqual(2, len(ip6_rules_list))
+
def _assert_fip_namespace_deleted(self, ext_gateway_port):
ext_net_id = ext_gateway_port['network_id']
self.agent.fipnamespace_delete_on_ext_net(