Merge "Update related router when subnetpool change scope"
This commit is contained in:
commit
8627fad607
neutron
callbacks
common
db
tests/unit
@ -21,3 +21,4 @@ SECURITY_GROUP = 'security_group'
|
||||
SECURITY_GROUP_RULE = 'security_group_rule'
|
||||
SUBNET = 'subnet'
|
||||
SUBNET_GATEWAY = 'subnet_gateway'
|
||||
SUBNETPOOL_ADDRESS_SCOPE = 'subnetpool_address_scope'
|
||||
|
@ -59,6 +59,8 @@ ROUTER_INTERFACE_OWNERS = (DEVICE_OWNER_ROUTER_INTF,
|
||||
ROUTER_INTERFACE_OWNERS_SNAT = (DEVICE_OWNER_ROUTER_INTF,
|
||||
DEVICE_OWNER_DVR_INTERFACE,
|
||||
DEVICE_OWNER_ROUTER_SNAT)
|
||||
ROUTER_PORT_OWNERS = ROUTER_INTERFACE_OWNERS_SNAT + (DEVICE_OWNER_ROUTER_GW,)
|
||||
|
||||
L3_AGENT_MODE_DVR = 'dvr'
|
||||
L3_AGENT_MODE_DVR_SNAT = 'dvr_snat'
|
||||
L3_AGENT_MODE_LEGACY = 'legacy'
|
||||
|
@ -1034,12 +1034,24 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
|
||||
self._validate_address_scope_id(context, reader.address_scope_id,
|
||||
id, reader.prefixes,
|
||||
reader.ip_version)
|
||||
address_scope_changed = (orig_sp.address_scope_id !=
|
||||
reader.address_scope_id)
|
||||
|
||||
orig_sp.update(self._filter_non_model_columns(
|
||||
reader.subnetpool,
|
||||
models_v2.SubnetPool))
|
||||
self._update_subnetpool_prefixes(context,
|
||||
reader.prefixes,
|
||||
id)
|
||||
|
||||
if address_scope_changed:
|
||||
# Notify about the update of subnetpool's address scope
|
||||
kwargs = {'context': context, 'subnetpool_id': id}
|
||||
registry.notify(resources.SUBNETPOOL_ADDRESS_SCOPE,
|
||||
events.AFTER_UPDATE,
|
||||
self.update_subnetpool,
|
||||
**kwargs)
|
||||
|
||||
for key in ['min_prefixlen', 'max_prefixlen', 'default_prefixlen']:
|
||||
updated['key'] = str(updated[key])
|
||||
|
||||
|
@ -1654,6 +1654,27 @@ def _notify_subnet_gateway_ip_update(resource, event, trigger, **kwargs):
|
||||
l3plugin.notify_router_updated(context, router_id)
|
||||
|
||||
|
||||
def _notify_subnetpool_address_scope_update(resource, event,
|
||||
trigger, **kwargs):
|
||||
context = kwargs['context']
|
||||
subnetpool_id = kwargs['subnetpool_id']
|
||||
|
||||
query = context.session.query(RouterPort.router_id)
|
||||
query = query.join(models_v2.Port)
|
||||
query = query.join(
|
||||
models_v2.Subnet,
|
||||
models_v2.Subnet.network_id == models_v2.Port.network_id)
|
||||
query = query.filter(
|
||||
models_v2.Subnet.subnetpool_id == subnetpool_id,
|
||||
RouterPort.port_type.in_(l3_constants.ROUTER_PORT_OWNERS))
|
||||
query = query.distinct()
|
||||
|
||||
router_ids = [r[0] for r in query]
|
||||
l3plugin = manager.NeutronManager.get_service_plugins().get(
|
||||
constants.L3_ROUTER_NAT)
|
||||
l3plugin.notify_routers_updated(context, router_ids)
|
||||
|
||||
|
||||
def subscribe():
|
||||
registry.subscribe(
|
||||
_prevent_l3_port_delete_callback, resources.PORT, events.BEFORE_DELETE)
|
||||
@ -1662,6 +1683,10 @@ def subscribe():
|
||||
registry.subscribe(
|
||||
_notify_subnet_gateway_ip_update, resources.SUBNET_GATEWAY,
|
||||
events.AFTER_UPDATE)
|
||||
registry.subscribe(
|
||||
_notify_subnetpool_address_scope_update,
|
||||
resources.SUBNETPOOL_ADDRESS_SCOPE,
|
||||
events.AFTER_UPDATE)
|
||||
|
||||
# NOTE(armax): multiple l3 service plugins (potentially out of tree) inherit
|
||||
# from l3_db and may need the callbacks to be processed. Having an implicit
|
||||
|
@ -16,6 +16,9 @@
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.db import l3_db
|
||||
from neutron.extensions import l3
|
||||
@ -185,3 +188,14 @@ class TestL3_NAT_dbonly_mixin(base.BaseTestCase):
|
||||
self.db.get_floatingip = mock.Mock()
|
||||
with testtools.ExpectedException(n_exc.ServicePortInUse):
|
||||
self.db.prevent_l3_port_deletion(mock.Mock(), None)
|
||||
|
||||
@mock.patch.object(l3_db, '_notify_subnetpool_address_scope_update')
|
||||
def test_subscribe_address_scope_of_subnetpool(self, notify):
|
||||
l3_db.subscribe()
|
||||
registry.notify(resources.SUBNETPOOL_ADDRESS_SCOPE,
|
||||
events.AFTER_UPDATE, mock.ANY, context=mock.ANY,
|
||||
subnetpool_id='fake_id')
|
||||
notify.assert_called_once_with(resources.SUBNETPOOL_ADDRESS_SCOPE,
|
||||
events.AFTER_UPDATE, mock.ANY,
|
||||
context=mock.ANY,
|
||||
subnetpool_id='fake_id')
|
||||
|
@ -14,10 +14,14 @@
|
||||
|
||||
import contextlib
|
||||
|
||||
import mock
|
||||
import netaddr
|
||||
import webob.exc
|
||||
|
||||
from neutron.api.v2 import attributes as attr
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants
|
||||
from neutron import context
|
||||
from neutron.db import address_scope_db
|
||||
@ -370,6 +374,62 @@ class TestSubnetPoolsWithAddressScopes(AddressScopeTestCase):
|
||||
self._compare_resource(res, update_data['subnetpool'],
|
||||
'subnetpool')
|
||||
|
||||
def _test_update_subnetpool_address_scope_notify(self, as_change=True):
|
||||
with self.address_scope(name='foo-address-scope') as addr_scope:
|
||||
foo_as_id = addr_scope['address_scope']['id']
|
||||
subnet = netaddr.IPNetwork('10.10.10.0/24')
|
||||
initial_subnetpool = self._test_create_subnetpool(
|
||||
[subnet.cidr], name='foo-sp',
|
||||
min_prefixlen='21', address_scope_id=foo_as_id)
|
||||
subnetpool_id = initial_subnetpool['subnetpool']['id']
|
||||
with self.address_scope(name='bar-address-scope') as other_as, \
|
||||
self.network() as network:
|
||||
data = {'subnet': {
|
||||
'network_id': network['network']['id'],
|
||||
'subnetpool_id': subnetpool_id,
|
||||
'prefixlen': 24,
|
||||
'ip_version': 4,
|
||||
'tenant_id': network['network']['tenant_id']}}
|
||||
req = self.new_create_request('subnets', data)
|
||||
subnet = self.deserialize(self.fmt,
|
||||
req.get_response(self.api))
|
||||
|
||||
with mock.patch.object(registry, 'notify') as notify:
|
||||
plugin = db_base_plugin_v2.NeutronDbPluginV2()
|
||||
plugin.is_address_scope_owned_by_tenant = mock.Mock(
|
||||
return_value=True)
|
||||
plugin._validate_address_scope_id = mock.Mock()
|
||||
ctx = context.get_admin_context()
|
||||
|
||||
bar_as_id = other_as['address_scope']['id']
|
||||
data = {'subnetpool': {
|
||||
'name': 'bar-sp'}}
|
||||
if as_change:
|
||||
data['subnetpool']['address_scope_id'] = bar_as_id
|
||||
|
||||
updated_sp = plugin.update_subnetpool(
|
||||
ctx, subnetpool_id, data)
|
||||
|
||||
self.assertEqual('bar-sp', updated_sp['name'])
|
||||
if as_change:
|
||||
self.assertEqual(bar_as_id,
|
||||
updated_sp['address_scope_id'])
|
||||
notify.assert_called_once_with(
|
||||
resources.SUBNETPOOL_ADDRESS_SCOPE,
|
||||
events.AFTER_UPDATE,
|
||||
plugin.update_subnetpool, context=ctx,
|
||||
subnetpool_id=subnetpool_id)
|
||||
else:
|
||||
self.assertEqual(foo_as_id,
|
||||
updated_sp['address_scope_id'])
|
||||
self.assertFalse(notify.called)
|
||||
|
||||
def test_update_subnetpool_address_scope_notify(self):
|
||||
self._test_update_subnetpool_address_scope_notify()
|
||||
|
||||
def test_not_update_subnetpool_address_scope_not_notify(self):
|
||||
self._test_update_subnetpool_address_scope_notify(False)
|
||||
|
||||
def test_delete_address_scope_in_use(self):
|
||||
with self.address_scope(name='foo-address-scope') as addr_scope:
|
||||
address_scope_id = addr_scope['address_scope']['id']
|
||||
|
@ -2692,6 +2692,37 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
||||
chk_method.assert_called_with(mock.ANY,
|
||||
['fake_device'], None)
|
||||
|
||||
def test__notify_subnetpool_address_scope_update(self):
|
||||
plugin = manager.NeutronManager.get_service_plugins()[
|
||||
service_constants.L3_ROUTER_NAT]
|
||||
|
||||
tenant_id = _uuid()
|
||||
with mock.patch.object(
|
||||
plugin, 'notify_routers_updated') as chk_method, \
|
||||
self.subnetpool(prefixes=['10.0.0.0/24'],
|
||||
admin=True, name='sp',
|
||||
tenant_id=tenant_id) as subnetpool, \
|
||||
self.router(tenant_id=tenant_id) as router, \
|
||||
self.network(tenant_id=tenant_id) as network:
|
||||
subnetpool_id = subnetpool['subnetpool']['id']
|
||||
data = {'subnet': {
|
||||
'network_id': network['network']['id'],
|
||||
'subnetpool_id': subnetpool_id,
|
||||
'prefixlen': 24,
|
||||
'ip_version': 4,
|
||||
'tenant_id': tenant_id}}
|
||||
req = self.new_create_request('subnets', data)
|
||||
subnet = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
|
||||
admin_ctx = context.get_admin_context()
|
||||
plugin.add_router_interface(
|
||||
admin_ctx,
|
||||
router['router']['id'], {'subnet_id': subnet['subnet']['id']})
|
||||
l3_db._notify_subnetpool_address_scope_update(
|
||||
mock.ANY, mock.ANY, mock.ANY,
|
||||
context=admin_ctx, subnetpool_id=subnetpool_id)
|
||||
chk_method.assert_called_with(admin_ctx, [router['router']['id']])
|
||||
|
||||
|
||||
class L3AgentDbTestCaseBase(L3NatTestCaseMixin):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user