Merge "Notify router_update after directly gateway IP change"
This commit is contained in:
commit
84e22945ce
@ -1907,6 +1907,22 @@ class L3RpcNotifierMixin(object):
|
||||
for router_id in router_ids:
|
||||
l3plugin.notify_router_updated(context, router_id)
|
||||
|
||||
@staticmethod
|
||||
@registry.receives(resources.PORT, [events.AFTER_UPDATE])
|
||||
def _notify_gateway_port_ip_changed(resource, event, trigger, **kwargs):
|
||||
l3plugin = directory.get_plugin(plugin_constants.L3)
|
||||
if not l3plugin:
|
||||
return
|
||||
new_port = kwargs.get('port')
|
||||
original_port = kwargs.get('original_port')
|
||||
|
||||
if original_port['device_owner'] != constants.DEVICE_OWNER_ROUTER_GW:
|
||||
return
|
||||
|
||||
if utils.port_ip_changed(new_port, original_port):
|
||||
l3plugin.notify_router_updated(kwargs['context'],
|
||||
new_port['device_id'])
|
||||
|
||||
@staticmethod
|
||||
@registry.receives(resources.SUBNETPOOL_ADDRESS_SCOPE,
|
||||
[events.AFTER_UPDATE])
|
||||
|
@ -118,6 +118,10 @@ class ClientFixture(fixtures.Fixture):
|
||||
|
||||
return self._create_resource(resource_type, spec)
|
||||
|
||||
def list_ports(self, retrieve_all=True, **kwargs):
|
||||
resp = self.client.list_ports(retrieve_all=retrieve_all, **kwargs)
|
||||
return resp['ports']
|
||||
|
||||
def create_port(self, tenant_id, network_id, hostname=None,
|
||||
qos_policy_id=None, security_groups=None, **kwargs):
|
||||
spec = {
|
||||
|
@ -17,6 +17,7 @@ import os
|
||||
import time
|
||||
|
||||
import netaddr
|
||||
from neutron_lib import constants
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.agent.l3 import ha_router
|
||||
@ -76,6 +77,50 @@ class TestL3Agent(base.BaseFullStackTestCase):
|
||||
|
||||
return self._boot_fake_vm_in_network(host, tenant_id, network['id'])
|
||||
|
||||
def _test_gateway_ip_changed(self):
|
||||
tenant_id = uuidutils.generate_uuid()
|
||||
ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id)
|
||||
external_vm = self.useFixture(
|
||||
machine_fixtures.FakeMachine(
|
||||
self.environment.central_bridge,
|
||||
common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24)))
|
||||
|
||||
router = self.safe_client.create_router(tenant_id,
|
||||
external_network=ext_net['id'])
|
||||
|
||||
vm = self._create_net_subnet_and_vm(
|
||||
tenant_id, ['20.0.0.0/24', '2001:db8:aaaa::/64'],
|
||||
self.environment.hosts[1], router)
|
||||
# ping external vm to test snat
|
||||
vm.block_until_ping(external_vm.ip)
|
||||
|
||||
fip = self.safe_client.create_floatingip(
|
||||
tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id'])
|
||||
# ping floating ip from external vm
|
||||
external_vm.block_until_ping(fip['floating_ip_address'])
|
||||
|
||||
# ping router gateway IP
|
||||
old_gw_ip = router['external_gateway_info'][
|
||||
'external_fixed_ips'][0]['ip_address']
|
||||
external_vm.block_until_ping(old_gw_ip)
|
||||
|
||||
gateway_port = self.safe_client.list_ports(
|
||||
device_id=router['id'],
|
||||
device_owner=constants.DEVICE_OWNER_ROUTER_GW)[0]
|
||||
ip_1 = str(netaddr.IPNetwork(
|
||||
ext_sub['gateway_ip']).next(100)).split('/')[0]
|
||||
ip_2 = str(netaddr.IPNetwork(
|
||||
ext_sub['gateway_ip']).next(101)).split('/')[0]
|
||||
self.safe_client.update_port(gateway_port['id'], fixed_ips=[
|
||||
{'ip_address': ip_1},
|
||||
{'ip_address': ip_2}])
|
||||
# ping router gateway new IPs
|
||||
external_vm.block_until_ping(ip_1)
|
||||
external_vm.block_until_ping(ip_2)
|
||||
|
||||
# ping router old gateway IP, should fail now
|
||||
external_vm.block_until_no_ping(old_gw_ip)
|
||||
|
||||
|
||||
class TestLegacyL3Agent(TestL3Agent):
|
||||
|
||||
@ -224,6 +269,9 @@ class TestLegacyL3Agent(TestL3Agent):
|
||||
# Verify north-south connectivity using ping6 to external_vm.
|
||||
vm.block_until_ping(external_vm.ipv6)
|
||||
|
||||
def test_gateway_ip_changed(self):
|
||||
self._test_gateway_ip_changed()
|
||||
|
||||
|
||||
class TestHAL3Agent(TestL3Agent):
|
||||
|
||||
@ -375,3 +423,6 @@ class TestHAL3Agent(TestL3Agent):
|
||||
|
||||
self._assert_ping_during_agents_restart(
|
||||
l3_active_agents, external_vm.namespace, [router_ip], count=60)
|
||||
|
||||
def test_gateway_ip_changed(self):
|
||||
self._test_gateway_ip_changed()
|
||||
|
@ -269,6 +269,21 @@ class TestL3NatBasePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
plugin.disassociate_floatingips(context, id)
|
||||
return super(TestL3NatBasePlugin, self).delete_port(context, id)
|
||||
|
||||
def update_port(self, context, id, port):
|
||||
original_port = self.get_port(context, id)
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
new_port = super(TestL3NatBasePlugin, self).update_port(
|
||||
context, id, port)
|
||||
# Notifications must be sent after the above transaction is complete
|
||||
kwargs = {
|
||||
'context': context,
|
||||
'port': new_port,
|
||||
'original_port': original_port,
|
||||
}
|
||||
registry.notify(resources.PORT, events.AFTER_UPDATE, self, **kwargs)
|
||||
return new_port
|
||||
|
||||
|
||||
# This plugin class is for tests with plugin that integrates L3.
|
||||
class TestL3NatIntPlugin(TestL3NatBasePlugin,
|
||||
@ -3434,6 +3449,73 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
||||
self.assertEqual('', body['port']['device_owner'])
|
||||
self.assertEqual('', body['port']['device_id'])
|
||||
|
||||
def _test__notify_gateway_port_ip_changed_helper(self, gw_ip_change=True):
|
||||
plugin = directory.get_plugin(plugin_constants.L3)
|
||||
if not hasattr(plugin, 'l3_rpc_notifier'):
|
||||
self.skipTest("Plugin does not support l3_rpc_notifier")
|
||||
# make sure the callback is registered.
|
||||
registry.subscribe(
|
||||
l3_db.L3RpcNotifierMixin._notify_gateway_port_ip_changed,
|
||||
resources.PORT,
|
||||
events.AFTER_UPDATE)
|
||||
with mock.patch.object(plugin.l3_rpc_notifier,
|
||||
'routers_updated') as chk_method:
|
||||
with self.router() as router:
|
||||
with self.subnet(cidr='1.1.1.0/24') as subnet:
|
||||
self._set_net_external(subnet['subnet']['network_id'])
|
||||
router_id = router['router']['id']
|
||||
self._add_external_gateway_to_router(
|
||||
router_id,
|
||||
subnet['subnet']['network_id'])
|
||||
body = self._show('routers', router_id)
|
||||
gateway_ips = body['router']['external_gateway_info'][
|
||||
'external_fixed_ips']
|
||||
gateway_ip_len = len(gateway_ips)
|
||||
self.assertEqual(1, gateway_ip_len)
|
||||
gw_port_id = None
|
||||
for p in self._list('ports')['ports']:
|
||||
if (p['device_owner'] ==
|
||||
lib_constants.DEVICE_OWNER_ROUTER_GW and
|
||||
p['device_id'] == router_id):
|
||||
gw_port_id = p['id']
|
||||
self.assertIsNotNone(gw_port_id)
|
||||
gw_ip_len = 1
|
||||
if gw_ip_change:
|
||||
gw_ip_len += 1
|
||||
data = {'port': {'fixed_ips': [
|
||||
{'ip_address': '1.1.1.101'},
|
||||
{'ip_address': '1.1.1.100'}]}}
|
||||
else:
|
||||
gw_ip = gateway_ips[0]['ip_address']
|
||||
data = {'port': {'fixed_ips': [
|
||||
{'ip_address': gw_ip}]}}
|
||||
req = self.new_update_request('ports', data,
|
||||
gw_port_id)
|
||||
res = self.deserialize(self.fmt,
|
||||
req.get_response(self.api))
|
||||
self.assertEqual(gw_ip_len, len(res['port']['fixed_ips']))
|
||||
|
||||
body = self._show('routers', router_id)
|
||||
gateway_ip_len = len(
|
||||
body['router']['external_gateway_info'][
|
||||
'external_fixed_ips'])
|
||||
self.assertEqual(gw_ip_len, gateway_ip_len)
|
||||
chk_method.assert_called_with(mock.ANY,
|
||||
[router_id], None)
|
||||
self.assertEqual(gw_ip_len, chk_method.call_count)
|
||||
|
||||
def test__notify_gateway_port_ip_changed(self):
|
||||
"""Test to make sure notification to routers occurs when the gateway
|
||||
ip address changed.
|
||||
"""
|
||||
self._test__notify_gateway_port_ip_changed_helper()
|
||||
|
||||
def test__notify_gateway_port_ip_not_changed(self):
|
||||
"""Test to make sure no notification to routers occurs when the gateway
|
||||
ip address is not changed.
|
||||
"""
|
||||
self._test__notify_gateway_port_ip_changed_helper(gw_ip_change=False)
|
||||
|
||||
def test_update_subnet_gateway_for_external_net(self):
|
||||
"""Test to make sure notification to routers occurs when the gateway
|
||||
ip address of a subnet of the external network is changed.
|
||||
|
Loading…
Reference in New Issue
Block a user