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:
parent
77cdddb055
commit
f9d0dd39e6
|
@ -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):
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue