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
(cherry picked from commit f9d0dd39e6
)
This commit is contained in:
parent
5413853b85
commit
a66af42091
|
@ -235,6 +235,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):
|
||||
|
|
|
@ -208,8 +208,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()
|
||||
|
|
|
@ -632,7 +632,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
|
||||
|
@ -940,6 +941,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[l3_constants.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
|
||||
|
||||
|
@ -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