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 34e51cad42)

Conflicts:
	neutron/tests/functional/agent/l3/test_dvr_router.py

Change-Id: Ic505a46e56d9e950bd36a1596d3f1adfb5ef5577
This commit is contained in:
Swaminathan Vasudevan 2016-07-05 13:22:04 -07:00
parent 9cd2dfceae
commit bce58c6410
3 changed files with 60 additions and 0 deletions

View File

@ -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:

View File

@ -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

View File

@ -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(