From 040d740d20f268938bbbca06b41006331f0ee889 Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Mon, 27 Jun 2016 13:30:44 -0600 Subject: [PATCH] Create segment_host mapping after new network This adds logic to add segment to host mappings for agents after a network with one or more segments is created. The previous logic was doing this only after an agent initially reported after the server started. This meant that any segmented networks created after the agent was running would not get mappings to the agent's host. Change-Id: Ie265500639b1119f0448ed272d235fb709db36f6 Partially-Implements: blueprint routed-networks --- neutron/db/segments_db.py | 14 ++++++++++--- neutron/plugins/ml2/driver_context.py | 2 +- neutron/plugins/ml2/managers.py | 19 +++++++++-------- neutron/tests/unit/extensions/test_segment.py | 21 ++++++++++++++++++- neutron/tests/unit/plugins/ml2/test_db.py | 2 +- neutron/tests/unit/plugins/ml2/test_plugin.py | 12 +++++------ 6 files changed, 49 insertions(+), 21 deletions(-) diff --git a/neutron/db/segments_db.py b/neutron/db/segments_db.py index b455c10e35b..507f4edde4f 100644 --- a/neutron/db/segments_db.py +++ b/neutron/db/segments_db.py @@ -16,6 +16,9 @@ import sqlalchemy as sa from sqlalchemy.orm import exc from neutron._i18n import _LI +from neutron.callbacks import events +from neutron.callbacks import registry +from neutron.callbacks import resources from neutron.db import model_base LOG = logging.getLogger(__name__) @@ -60,9 +63,9 @@ def _make_segment_dict(record): SEGMENTATION_ID: record.segmentation_id} -def add_network_segment(session, network_id, segment, segment_index=0, +def add_network_segment(context, network_id, segment, segment_index=0, is_dynamic=False): - with session.begin(subtransactions=True): + with context.session.begin(subtransactions=True): record = NetworkSegment( id=uuidutils.generate_uuid(), network_id=network_id, @@ -72,7 +75,12 @@ def add_network_segment(session, network_id, segment, segment_index=0, segment_index=segment_index, is_dynamic=is_dynamic ) - session.add(record) + context.session.add(record) + registry.notify(resources.SEGMENT, + events.PRECOMMIT_CREATE, + trigger=add_network_segment, + context=context, + segment=record) segment['id'] = record.id LOG.info(_LI("Added segment %(id)s of type %(network_type)s for network " "%(network_id)s"), diff --git a/neutron/plugins/ml2/driver_context.py b/neutron/plugins/ml2/driver_context.py index 5812e90d004..afc73911615 100644 --- a/neutron/plugins/ml2/driver_context.py +++ b/neutron/plugins/ml2/driver_context.py @@ -259,7 +259,7 @@ class PortContext(MechanismDriverContext, api.PortContext): network_id = self._network_context.current['id'] return self._plugin.type_manager.allocate_dynamic_segment( - self._plugin_context.session, network_id, segment) + self._plugin_context, network_id, segment) def release_dynamic_segment(self, segment_id): return self._plugin.type_manager.release_dynamic_segment( diff --git a/neutron/plugins/ml2/managers.py b/neutron/plugins/ml2/managers.py index c6fe71d1e84..6912e9de105 100644 --- a/neutron/plugins/ml2/managers.py +++ b/neutron/plugins/ml2/managers.py @@ -182,10 +182,10 @@ class TypeManager(stevedore.named.NamedExtensionManager): LOG.info(_LI("Initializing driver for type '%s'"), network_type) driver.obj.initialize() - def _add_network_segment(self, session, network_id, segment, mtu, + def _add_network_segment(self, context, network_id, segment, mtu, segment_index=0): segments_db.add_network_segment( - session, network_id, segment, segment_index) + context, network_id, segment, segment_index) if segment.get(api.MTU, 0) > 0: mtu.append(segment[api.MTU]) @@ -200,15 +200,15 @@ class TypeManager(stevedore.named.NamedExtensionManager): for segment_index, segment in enumerate(segments): segment = self.reserve_provider_segment( session, segment) - self._add_network_segment(session, network_id, segment, + self._add_network_segment(context, network_id, segment, mtu, segment_index) elif (cfg.CONF.ml2.external_network_type and self._get_attribute(network, external_net.EXTERNAL)): segment = self._allocate_ext_net_segment(session) - self._add_network_segment(session, network_id, segment, mtu) + self._add_network_segment(context, network_id, segment, mtu) else: segment = self._allocate_tenant_net_segment(session) - self._add_network_segment(session, network_id, segment, mtu) + self._add_network_segment(context, network_id, segment, mtu) network[api.MTU] = min(mtu) if mtu else 0 def is_partial_segment(self, segment): @@ -265,18 +265,19 @@ class TypeManager(stevedore.named.NamedExtensionManager): LOG.error(_LE("Failed to release segment '%s' because " "network type is not supported."), segment) - def allocate_dynamic_segment(self, session, network_id, segment): + def allocate_dynamic_segment(self, context, network_id, segment): """Allocate a dynamic segment using a partial or full segment dict.""" dynamic_segment = segments_db.get_dynamic_segment( - session, network_id, segment.get(api.PHYSICAL_NETWORK), + context.session, network_id, segment.get(api.PHYSICAL_NETWORK), segment.get(api.SEGMENTATION_ID)) if dynamic_segment: return dynamic_segment driver = self.drivers.get(segment.get(api.NETWORK_TYPE)) - dynamic_segment = driver.obj.reserve_provider_segment(session, segment) - segments_db.add_network_segment(session, network_id, dynamic_segment, + dynamic_segment = driver.obj.reserve_provider_segment(context.session, + segment) + segments_db.add_network_segment(context, network_id, dynamic_segment, is_dynamic=True) return dynamic_segment diff --git a/neutron/tests/unit/extensions/test_segment.py b/neutron/tests/unit/extensions/test_segment.py index 6d2994b3ca2..f8702862159 100644 --- a/neutron/tests/unit/extensions/test_segment.py +++ b/neutron/tests/unit/extensions/test_segment.py @@ -19,6 +19,9 @@ from oslo_utils import uuidutils import webob.exc from neutron.api.v2 import attributes +from neutron.callbacks import events +from neutron.callbacks import registry +from neutron.callbacks import resources from neutron import context from neutron.db import agents_db from neutron.db import db_base_plugin_v2 @@ -189,6 +192,22 @@ class TestSegment(SegmentTestCase): self.assertEqual(2, len(res['segments'])) +class TestSegmentML2(SegmentTestCase): + def setUp(self): + super(TestSegmentML2, self).setUp( + plugin='neutron.plugins.ml2.plugin.Ml2Plugin') + + def test_segment_notification_on_create_network(self): + with mock.patch.object(registry, 'notify') as notify: + with self.network(): + pass + notify.assert_any_call(resources.SEGMENT, + events.PRECOMMIT_CREATE, + context=mock.ANY, + segment=mock.ANY, + trigger=mock.ANY) + + class TestSegmentSubnetAssociation(SegmentTestCase): def test_basic_association(self): with self.network() as network: @@ -259,7 +278,7 @@ class TestSegmentSubnetAssociation(SegmentTestCase): segment = {segments_db.NETWORK_TYPE: 'phys_net', segments_db.PHYSICAL_NETWORK: 'net_type', segments_db.SEGMENTATION_ID: 200} - segments_db.add_network_segment(cxt.session, + segments_db.add_network_segment(cxt, network_id=net['id'], segment=segment, is_dynamic=True) diff --git a/neutron/tests/unit/plugins/ml2/test_db.py b/neutron/tests/unit/plugins/ml2/test_db.py index 32d32ccf75d..f33b89b74ba 100644 --- a/neutron/tests/unit/plugins/ml2/test_db.py +++ b/neutron/tests/unit/plugins/ml2/test_db.py @@ -66,7 +66,7 @@ class Ml2DBTestCase(testlib_api.SqlTestCase): self._setup_neutron_network(network_id) for segment in segments: segments_db.add_network_segment( - self.ctx.session, network_id, segment, + self.ctx, network_id, segment, is_dynamic=is_seg_dynamic) net_segments = segments_db.get_network_segments( diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index bb04aa19a3b..3e38d1914aa 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -1367,7 +1367,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): driver_api.PHYSICAL_NETWORK: 'physnet1'} network_id = network['network']['id'] self.driver.type_manager.allocate_dynamic_segment( - self.context.session, network_id, segment) + self.context, network_id, segment) dynamic_segment = segments_db.get_dynamic_segment( self.context.session, network_id, 'physnet1') self.assertEqual('vlan', dynamic_segment[driver_api.NETWORK_TYPE]) @@ -1378,7 +1378,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): driver_api.SEGMENTATION_ID: 1234, driver_api.PHYSICAL_NETWORK: 'physnet3'} self.driver.type_manager.allocate_dynamic_segment( - self.context.session, network_id, segment2) + self.context, network_id, segment2) dynamic_segment = segments_db.get_dynamic_segment( self.context.session, network_id, segmentation_id='1234') self.assertEqual('vlan', dynamic_segment[driver_api.NETWORK_TYPE]) @@ -1396,7 +1396,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): driver_api.PHYSICAL_NETWORK: 'physnet1'} network_id = network['network']['id'] self.driver.type_manager.allocate_dynamic_segment( - self.context.session, network_id, segment) + self.context, network_id, segment) dynamic_segment = segments_db.get_dynamic_segment( self.context.session, network_id, 'physnet1') self.assertEqual('vlan', dynamic_segment[driver_api.NETWORK_TYPE]) @@ -1411,7 +1411,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): segment2 = {driver_api.NETWORK_TYPE: 'vlan', driver_api.PHYSICAL_NETWORK: 'physnet2'} self.driver.type_manager.allocate_dynamic_segment( - self.context.session, network_id, segment2) + self.context, network_id, segment2) dynamic_segment2 = segments_db.get_dynamic_segment( self.context.session, network_id, 'physnet2') dynamic_segmentation2_id = dynamic_segment2[driver_api.SEGMENTATION_ID] @@ -1427,7 +1427,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): driver_api.PHYSICAL_NETWORK: 'physnet1'} network_id = network['network']['id'] self.driver.type_manager.allocate_dynamic_segment( - self.context.session, network_id, segment) + self.context, network_id, segment) dynamic_segment = segments_db.get_dynamic_segment( self.context.session, network_id, 'physnet1') self.assertEqual('vlan', dynamic_segment[driver_api.NETWORK_TYPE]) @@ -1564,7 +1564,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): segment = {driver_api.NETWORK_TYPE: 'vlan', driver_api.PHYSICAL_NETWORK: 'physnet2'} self.driver.type_manager.allocate_dynamic_segment( - self.context.session, network_id, segment) + self.context, network_id, segment) dynamic_segment = segments_db.get_dynamic_segment( self.context.session, network_id, 'physnet2') self.assertEqual('vlan', dynamic_segment[driver_api.NETWORK_TYPE])