Delete default route if no gateway in external net

Currently, when the default route is added to device, there is no
way to delete it. Even if user clear the gateway ip of external
net, there is still a default route present in router namespace.

This patch will check the default route in namespace first. If its
gateway ip is not one of the gateway ips in external net. This
default route will be deleted.

Change-Id: If2ab88b392f3935306d73e3c2de0a35548567464
Closes-Bug: #1520775
This commit is contained in:
root 2016-07-07 13:32:44 +00:00 committed by Hong Hui Xiao
parent 77cdddb055
commit f9d0dd39e6
6 changed files with 64 additions and 3 deletions

View File

@ -228,6 +228,10 @@ class FipNamespace(namespaces.Namespace):
if is_gateway_not_in_subnet:
ipd.route.add_route(gw_ip, scope='link')
ipd.route.add_gateway(gw_ip)
else:
current_gateway = ipd.route.get_gateway()
if current_gateway and current_gateway.get('gateway'):
ipd.route.delete_gateway(current_gateway.get('gateway'))
def _add_cidr_to_device(self, device, ip_cidr):
if not device.addr.list(to=ip_cidr):

View File

@ -189,8 +189,6 @@ class HaRouter(router.RouterInfo):
def _add_default_gw_virtual_route(self, ex_gw_port, interface_name):
gateway_ips = self._get_external_gw_ips(ex_gw_port)
if not gateway_ips:
return
default_gw_rts = []
instance = self._get_keepalived_instance()

View File

@ -615,7 +615,15 @@ class RouterInfo(object):
clean_connections=True)
device = ip_lib.IPDevice(interface_name, namespace=ns_name)
for ip in gateway_ips or []:
current_gateways = set()
for ip_version in (l3_constants.IP_VERSION_4,
l3_constants.IP_VERSION_6):
gateway = device.route.get_gateway(ip_version=ip_version)
if gateway and gateway.get('gateway'):
current_gateways.add(gateway.get('gateway'))
for ip in current_gateways - set(gateway_ips):
device.route.delete_gateway(ip)
for ip in gateway_ips:
device.route.add_gateway(ip)
if enable_ra_on_gw:

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import functools
import mock
@ -778,6 +779,34 @@ class TestDvrRouter(framework.L3AgentTestFramework):
self._assert_extra_routes(router_updated, namespace=snat_ns_name)
self._assert_extra_routes(router_updated)
def test_dvr_router_gateway_update_to_none(self):
self.agent.conf.agent_mode = 'dvr_snat'
router_info = self.generate_dvr_router_info(enable_snat=True)
router = self.manage_router(self.agent, router_info)
gw_port = router.get_ex_gw_port()
ex_gw_port_name = router.get_external_device_name(gw_port['id'])
ex_gw_device = ip_lib.IPDevice(ex_gw_port_name,
namespace=router.snat_namespace.name)
fg_port = router.fip_ns.agent_gateway_port
fg_port_name = router.fip_ns.get_ext_device_name(fg_port['id'])
fg_device = ip_lib.IPDevice(fg_port_name,
namespace=router.fip_ns.name)
self.assertIn('gateway', ex_gw_device.route.get_gateway())
self.assertIn('gateway', fg_device.route.get_gateway())
# Make this copy to make agent think gw_port changed.
router.ex_gw_port = copy.deepcopy(router.ex_gw_port)
for subnet in gw_port['subnets']:
subnet['gateway_ip'] = None
new_fg_port = copy.deepcopy(fg_port)
for subnet in new_fg_port['subnets']:
subnet['gateway_ip'] = None
router.router[n_const.FLOATINGIP_AGENT_INTF_KEY] = [new_fg_port]
router.process(self.agent)
self.assertIsNone(ex_gw_device.route.get_gateway())
self.assertIsNone(fg_device.route.get_gateway())
def _assert_fip_namespace_deleted(self, ext_gateway_port):
ext_net_id = ext_gateway_port['network_id']
fip_ns = self.agent.get_fip_ns(ext_net_id)

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import mock
from neutron_lib import constants as l3_constants
@ -78,6 +79,23 @@ class L3AgentTestCase(framework.L3AgentTestFramework):
self._router_lifecycle(enable_ha=False, dual_stack=True,
v6_ext_gw_with_sub=False)
def test_legacy_router_gateway_update_to_none(self):
router_info = self.generate_router_info(False)
router = self.manage_router(self.agent, router_info)
gw_port = router.get_ex_gw_port()
interface_name = router.get_external_device_name(gw_port['id'])
device = ip_lib.IPDevice(interface_name, namespace=router.ns_name)
self.assertIn('gateway', device.route.get_gateway())
# Make this copy, so that the agent will think there is change in
# external gateway port.
router.ex_gw_port = copy.deepcopy(router.ex_gw_port)
for subnet in gw_port['subnets']:
subnet['gateway_ip'] = None
router.process(self.agent)
self.assertIsNone(device.route.get_gateway())
def test_legacy_router_ns_rebuild(self):
router_info = self.generate_router_info(False)
router = self.manage_router(self.agent, router_info)

View File

@ -68,3 +68,7 @@ class TestBasicRouterOperations(base.BaseTestCase):
'gateway_ip': '30.0.0.1'})
ri._add_default_gw_virtual_route(ex_gw_port, 'qg-abc')
self.assertEqual(1, len(mock_instance.virtual_routes.gateway_routes))
subnets[1]['gateway_ip'] = None
ri._add_default_gw_virtual_route(ex_gw_port, 'qg-abc')
self.assertEqual(0, len(mock_instance.virtual_routes.gateway_routes))