From 9ff79d003be853db0236affec9d5018825f0bac2 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Tue, 6 Dec 2016 15:59:29 +0200 Subject: [PATCH] NSX|V update router edge when gateway subnet changes When a subnet gateway changes, and this subnet is the gateway of a router we need to update the next hop on the router edge Change-Id: If232ac89c880e8a501466abbfaae7b954609aa0d --- .../nsx_v/drivers/abstract_router_driver.py | 4 ++++ .../drivers/distributed_router_driver.py | 6 +++++ vmware_nsx/plugins/nsx_v/plugin.py | 16 +++++++++++++ vmware_nsx/tests/unit/nsx_v/test_plugin.py | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py b/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py index b9c1db5659..2d21f3ec0f 100644 --- a/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py +++ b/vmware_nsx/plugins/nsx_v/drivers/abstract_router_driver.py @@ -127,3 +127,7 @@ class RouterBaseDriver(RouterAbstractDriver): def get_router_az_by_id(self, context, router_id): lrouter = self.plugin.get_router(context, router_id) return self.get_router_az(lrouter) + + def _update_nexthop(self, context, router_id, newnexthop): + """Update the router edge on gateway subnet default gateway change.""" + self.plugin._update_routes(context, router_id, newnexthop) diff --git a/vmware_nsx/plugins/nsx_v/drivers/distributed_router_driver.py b/vmware_nsx/plugins/nsx_v/drivers/distributed_router_driver.py index 36a94767f9..2314794c85 100644 --- a/vmware_nsx/plugins/nsx_v/drivers/distributed_router_driver.py +++ b/vmware_nsx/plugins/nsx_v/drivers/distributed_router_driver.py @@ -147,6 +147,12 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver): self._update_routes_on_tlr(context, router_id, newnexthop=None, metadata_gateway=metadata_gateway) + def _update_nexthop(self, context, router_id, newnexthop): + plr_id = self.edge_manager.get_plr_by_tlr_id(context, router_id) + if plr_id: + self._update_routes_on_plr(context, router_id, plr_id, + newnexthop) + def _update_router_gw_info(self, context, router_id, info, is_routes_update=False, force_update=False): diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 555b22a205..bd67d96366 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -2030,6 +2030,18 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, update_dhcp_config = True return update_dhcp_config + def _update_routers_on_gateway_change(self, context, subnet_id, + new_gateway): + """Update all relevant router edges that the nexthop changed.""" + port_filters = {'device_owner': [l3_db.DEVICE_OWNER_ROUTER_GW], + 'fixed_ips': {'subnet_id': [subnet_id]}} + intf_ports = self.get_ports(context.elevated(), + filters=port_filters) + router_ids = [port['device_id'] for port in intf_ports] + for router_id in router_ids: + router_driver = self._find_router_driver(context, router_id) + router_driver._update_nexthop(context, router_id, new_gateway) + def update_subnet(self, context, id, subnet): s = subnet['subnet'] orig = self._get_subnet(context, id) @@ -2053,6 +2065,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, # Update the edge network_id = subnet['network_id'] self.edge_manager.update_dhcp_edge_bindings(context, network_id) + # also update routers that use this subnet as their gateway + if gateway_ip != subnet['gateway_ip']: + self._update_routers_on_gateway_change(context, id, + subnet['gateway_ip']) if enable_dhcp != subnet['enable_dhcp']: self._update_subnet_dhcp_status(subnet, context) return subnet diff --git a/vmware_nsx/tests/unit/nsx_v/test_plugin.py b/vmware_nsx/tests/unit/nsx_v/test_plugin.py index d817b7a97a..cf9d92a075 100644 --- a/vmware_nsx/tests/unit/nsx_v/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v/test_plugin.py @@ -64,6 +64,8 @@ from vmware_nsx.extensions import routertype as router_type from vmware_nsx.extensions import securitygrouplogging from vmware_nsx.extensions import vnicindex as ext_vnic_idx from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az +from vmware_nsx.plugins.nsx_v.drivers import ( + distributed_router_driver as dist_router_driver) from vmware_nsx.plugins.nsx_v.drivers import ( exclusive_router_driver as ex_router_driver) from vmware_nsx.plugins.nsx_v.drivers import ( @@ -3144,6 +3146,17 @@ class TestExclusiveRouterTestCase(L3NatTest, L3NatTestCaseBase, def test_router_add_gateway_multiple_subnets_ipv6(self): self.skipTest('not supported') + def test_update_subnet_gateway_for_external_net(self): + plugin = directory.get_plugin() + router_obj = ex_router_driver.RouterExclusiveDriver(plugin) + with mock.patch.object(plugin, '_find_router_driver', + return_value=router_obj): + with mock.patch.object(router_obj, + '_update_nexthop') as update_nexthop: + super(TestExclusiveRouterTestCase, + self).test_update_subnet_gateway_for_external_net() + self.assertTrue(update_nexthop.called) + class ExtGwModeTestCase(NsxVPluginV2TestCase, test_ext_gw_mode.ExtGwModeIntTestCase): @@ -3671,6 +3684,17 @@ class TestVdrTestCase(L3NatTest, L3NatTestCaseBase, def test_floatingip_update_to_same_port_id_twice(self): self.skipTest('Plugin changes floating port status') + def test_update_subnet_gateway_for_external_net(self): + plugin = directory.get_plugin() + router_obj = dist_router_driver.RouterDistributedDriver(plugin) + with mock.patch.object(plugin, '_find_router_driver', + return_value=router_obj): + with mock.patch.object(router_obj, + '_update_nexthop') as update_nexthop: + super(TestVdrTestCase, + self).test_update_subnet_gateway_for_external_net() + self.assertTrue(update_nexthop.called) + class TestNSXvAllowedAddressPairs(NsxVPluginV2TestCase, test_addr_pair.TestAllowedAddressPairs):