summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-11-13 21:23:51 +0000
committerGerrit Code Review <review@openstack.org>2018-11-13 21:23:51 +0000
commit84e22945cea3ef9cbef61553836dc35d4e62ff13 (patch)
tree3cc6970b57a14d9ed281b95b20e0f79eb8e5c9e3
parent90dd08b15693a5629ffa8d946b25b8b4f453f5f6 (diff)
parent8c17df7138744de567d1e45cfb604a0221db90ab (diff)
Merge "Notify router_update after directly gateway IP change"HEADmaster
-rw-r--r--neutron/db/l3_db.py16
-rw-r--r--neutron/tests/fullstack/resources/client.py4
-rw-r--r--neutron/tests/fullstack/test_l3_agent.py51
-rw-r--r--neutron/tests/unit/extensions/test_l3.py82
4 files changed, 153 insertions, 0 deletions
diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py
index 008c616..40930ba 100644
--- a/neutron/db/l3_db.py
+++ b/neutron/db/l3_db.py
@@ -1908,6 +1908,22 @@ class L3RpcNotifierMixin(object):
1908 l3plugin.notify_router_updated(context, router_id) 1908 l3plugin.notify_router_updated(context, router_id)
1909 1909
1910 @staticmethod 1910 @staticmethod
1911 @registry.receives(resources.PORT, [events.AFTER_UPDATE])
1912 def _notify_gateway_port_ip_changed(resource, event, trigger, **kwargs):
1913 l3plugin = directory.get_plugin(plugin_constants.L3)
1914 if not l3plugin:
1915 return
1916 new_port = kwargs.get('port')
1917 original_port = kwargs.get('original_port')
1918
1919 if original_port['device_owner'] != constants.DEVICE_OWNER_ROUTER_GW:
1920 return
1921
1922 if utils.port_ip_changed(new_port, original_port):
1923 l3plugin.notify_router_updated(kwargs['context'],
1924 new_port['device_id'])
1925
1926 @staticmethod
1911 @registry.receives(resources.SUBNETPOOL_ADDRESS_SCOPE, 1927 @registry.receives(resources.SUBNETPOOL_ADDRESS_SCOPE,
1912 [events.AFTER_UPDATE]) 1928 [events.AFTER_UPDATE])
1913 def _notify_subnetpool_address_scope_update(resource, event, 1929 def _notify_subnetpool_address_scope_update(resource, event,
diff --git a/neutron/tests/fullstack/resources/client.py b/neutron/tests/fullstack/resources/client.py
index 07176e5..441c3e5 100644
--- a/neutron/tests/fullstack/resources/client.py
+++ b/neutron/tests/fullstack/resources/client.py
@@ -118,6 +118,10 @@ class ClientFixture(fixtures.Fixture):
118 118
119 return self._create_resource(resource_type, spec) 119 return self._create_resource(resource_type, spec)
120 120
121 def list_ports(self, retrieve_all=True, **kwargs):
122 resp = self.client.list_ports(retrieve_all=retrieve_all, **kwargs)
123 return resp['ports']
124
121 def create_port(self, tenant_id, network_id, hostname=None, 125 def create_port(self, tenant_id, network_id, hostname=None,
122 qos_policy_id=None, security_groups=None, **kwargs): 126 qos_policy_id=None, security_groups=None, **kwargs):
123 spec = { 127 spec = {
diff --git a/neutron/tests/fullstack/test_l3_agent.py b/neutron/tests/fullstack/test_l3_agent.py
index 0479065..e0cbea0 100644
--- a/neutron/tests/fullstack/test_l3_agent.py
+++ b/neutron/tests/fullstack/test_l3_agent.py
@@ -17,6 +17,7 @@ import os
17import time 17import time
18 18
19import netaddr 19import netaddr
20from neutron_lib import constants
20from oslo_utils import uuidutils 21from oslo_utils import uuidutils
21 22
22from neutron.agent.l3 import ha_router 23from neutron.agent.l3 import ha_router
@@ -76,6 +77,50 @@ class TestL3Agent(base.BaseFullStackTestCase):
76 77
77 return self._boot_fake_vm_in_network(host, tenant_id, network['id']) 78 return self._boot_fake_vm_in_network(host, tenant_id, network['id'])
78 79
80 def _test_gateway_ip_changed(self):
81 tenant_id = uuidutils.generate_uuid()
82 ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id)
83 external_vm = self.useFixture(
84 machine_fixtures.FakeMachine(
85 self.environment.central_bridge,
86 common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24)))
87
88 router = self.safe_client.create_router(tenant_id,
89 external_network=ext_net['id'])
90
91 vm = self._create_net_subnet_and_vm(
92 tenant_id, ['20.0.0.0/24', '2001:db8:aaaa::/64'],
93 self.environment.hosts[1], router)
94 # ping external vm to test snat
95 vm.block_until_ping(external_vm.ip)
96
97 fip = self.safe_client.create_floatingip(
98 tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id'])
99 # ping floating ip from external vm
100 external_vm.block_until_ping(fip['floating_ip_address'])
101
102 # ping router gateway IP
103 old_gw_ip = router['external_gateway_info'][
104 'external_fixed_ips'][0]['ip_address']
105 external_vm.block_until_ping(old_gw_ip)
106
107 gateway_port = self.safe_client.list_ports(
108 device_id=router['id'],
109 device_owner=constants.DEVICE_OWNER_ROUTER_GW)[0]
110 ip_1 = str(netaddr.IPNetwork(
111 ext_sub['gateway_ip']).next(100)).split('/')[0]
112 ip_2 = str(netaddr.IPNetwork(
113 ext_sub['gateway_ip']).next(101)).split('/')[0]
114 self.safe_client.update_port(gateway_port['id'], fixed_ips=[
115 {'ip_address': ip_1},
116 {'ip_address': ip_2}])
117 # ping router gateway new IPs
118 external_vm.block_until_ping(ip_1)
119 external_vm.block_until_ping(ip_2)
120
121 # ping router old gateway IP, should fail now
122 external_vm.block_until_no_ping(old_gw_ip)
123
79 124
80class TestLegacyL3Agent(TestL3Agent): 125class TestLegacyL3Agent(TestL3Agent):
81 126
@@ -224,6 +269,9 @@ class TestLegacyL3Agent(TestL3Agent):
224 # Verify north-south connectivity using ping6 to external_vm. 269 # Verify north-south connectivity using ping6 to external_vm.
225 vm.block_until_ping(external_vm.ipv6) 270 vm.block_until_ping(external_vm.ipv6)
226 271
272 def test_gateway_ip_changed(self):
273 self._test_gateway_ip_changed()
274
227 275
228class TestHAL3Agent(TestL3Agent): 276class TestHAL3Agent(TestL3Agent):
229 277
@@ -375,3 +423,6 @@ class TestHAL3Agent(TestL3Agent):
375 423
376 self._assert_ping_during_agents_restart( 424 self._assert_ping_during_agents_restart(
377 l3_active_agents, external_vm.namespace, [router_ip], count=60) 425 l3_active_agents, external_vm.namespace, [router_ip], count=60)
426
427 def test_gateway_ip_changed(self):
428 self._test_gateway_ip_changed()
diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py
index e98ccb5..0f6e251 100644
--- a/neutron/tests/unit/extensions/test_l3.py
+++ b/neutron/tests/unit/extensions/test_l3.py
@@ -269,6 +269,21 @@ class TestL3NatBasePlugin(db_base_plugin_v2.NeutronDbPluginV2,
269 plugin.disassociate_floatingips(context, id) 269 plugin.disassociate_floatingips(context, id)
270 return super(TestL3NatBasePlugin, self).delete_port(context, id) 270 return super(TestL3NatBasePlugin, self).delete_port(context, id)
271 271
272 def update_port(self, context, id, port):
273 original_port = self.get_port(context, id)
274 session = context.session
275 with session.begin(subtransactions=True):
276 new_port = super(TestL3NatBasePlugin, self).update_port(
277 context, id, port)
278 # Notifications must be sent after the above transaction is complete
279 kwargs = {
280 'context': context,
281 'port': new_port,
282 'original_port': original_port,
283 }
284 registry.notify(resources.PORT, events.AFTER_UPDATE, self, **kwargs)
285 return new_port
286
272 287
273# This plugin class is for tests with plugin that integrates L3. 288# This plugin class is for tests with plugin that integrates L3.
274class TestL3NatIntPlugin(TestL3NatBasePlugin, 289class TestL3NatIntPlugin(TestL3NatBasePlugin,
@@ -3434,6 +3449,73 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
3434 self.assertEqual('', body['port']['device_owner']) 3449 self.assertEqual('', body['port']['device_owner'])
3435 self.assertEqual('', body['port']['device_id']) 3450 self.assertEqual('', body['port']['device_id'])
3436 3451
3452 def _test__notify_gateway_port_ip_changed_helper(self, gw_ip_change=True):
3453 plugin = directory.get_plugin(plugin_constants.L3)
3454 if not hasattr(plugin, 'l3_rpc_notifier'):
3455 self.skipTest("Plugin does not support l3_rpc_notifier")
3456 # make sure the callback is registered.
3457 registry.subscribe(
3458 l3_db.L3RpcNotifierMixin._notify_gateway_port_ip_changed,
3459 resources.PORT,
3460 events.AFTER_UPDATE)
3461 with mock.patch.object(plugin.l3_rpc_notifier,
3462 'routers_updated') as chk_method:
3463 with self.router() as router:
3464 with self.subnet(cidr='1.1.1.0/24') as subnet:
3465 self._set_net_external(subnet['subnet']['network_id'])
3466 router_id = router['router']['id']
3467 self._add_external_gateway_to_router(
3468 router_id,
3469 subnet['subnet']['network_id'])
3470 body = self._show('routers', router_id)
3471 gateway_ips = body['router']['external_gateway_info'][
3472 'external_fixed_ips']
3473 gateway_ip_len = len(gateway_ips)
3474 self.assertEqual(1, gateway_ip_len)
3475 gw_port_id = None
3476 for p in self._list('ports')['ports']:
3477 if (p['device_owner'] ==
3478 lib_constants.DEVICE_OWNER_ROUTER_GW and
3479 p['device_id'] == router_id):
3480 gw_port_id = p['id']
3481 self.assertIsNotNone(gw_port_id)
3482 gw_ip_len = 1
3483 if gw_ip_change:
3484 gw_ip_len += 1
3485 data = {'port': {'fixed_ips': [
3486 {'ip_address': '1.1.1.101'},
3487 {'ip_address': '1.1.1.100'}]}}
3488 else:
3489 gw_ip = gateway_ips[0]['ip_address']
3490 data = {'port': {'fixed_ips': [
3491 {'ip_address': gw_ip}]}}
3492 req = self.new_update_request('ports', data,
3493 gw_port_id)
3494 res = self.deserialize(self.fmt,
3495 req.get_response(self.api))
3496 self.assertEqual(gw_ip_len, len(res['port']['fixed_ips']))
3497
3498 body = self._show('routers', router_id)
3499 gateway_ip_len = len(
3500 body['router']['external_gateway_info'][
3501 'external_fixed_ips'])
3502 self.assertEqual(gw_ip_len, gateway_ip_len)
3503 chk_method.assert_called_with(mock.ANY,
3504 [router_id], None)
3505 self.assertEqual(gw_ip_len, chk_method.call_count)
3506
3507 def test__notify_gateway_port_ip_changed(self):
3508 """Test to make sure notification to routers occurs when the gateway
3509 ip address changed.
3510 """
3511 self._test__notify_gateway_port_ip_changed_helper()
3512
3513 def test__notify_gateway_port_ip_not_changed(self):
3514 """Test to make sure no notification to routers occurs when the gateway
3515 ip address is not changed.
3516 """
3517 self._test__notify_gateway_port_ip_changed_helper(gw_ip_change=False)
3518
3437 def test_update_subnet_gateway_for_external_net(self): 3519 def test_update_subnet_gateway_for_external_net(self):
3438 """Test to make sure notification to routers occurs when the gateway 3520 """Test to make sure notification to routers occurs when the gateway
3439 ip address of a subnet of the external network is changed. 3521 ip address of a subnet of the external network is changed.