diff --git a/neutron/services/segments/db.py b/neutron/services/segments/db.py index 8c844fbcc04..af8f1489276 100644 --- a/neutron/services/segments/db.py +++ b/neutron/services/segments/db.py @@ -23,6 +23,7 @@ from neutron_lib.db import utils as db_utils from neutron_lib import exceptions as n_exc from neutron_lib.plugins import directory from oslo_concurrency import lockutils +from oslo_config import cfg from oslo_db import exception as db_exc from oslo_log import helpers as log_helpers from oslo_utils import uuidutils @@ -37,6 +38,26 @@ from neutron.objects import network from neutron.services.segments import exceptions +_USER_CONFIGURED_SEGMENT_PLUGIN = None + + +def check_user_configured_segment_plugin(): + global _USER_CONFIGURED_SEGMENT_PLUGIN + # _USER_CONFIGURED_SEGMENT_PLUGIN will contain 3 possible values: + # 1. None, this just happens during neutron-server startup. + # 2. True, this means that users configure the 'segments' + # service plugin in neutron config file. + # 3. False, this means that can not find 'segments' service + # plugin in neutron config file. + # This function just load once to store the result + # into _USER_CONFIGURED_SEGMENT_PLUGIN during neutron-server startup. + if _USER_CONFIGURED_SEGMENT_PLUGIN is None: + segment_class = 'neutron.services.segments.plugin.Plugin' + _USER_CONFIGURED_SEGMENT_PLUGIN = any( + p in cfg.CONF.service_plugins for p in ['segments', segment_class]) + return _USER_CONFIGURED_SEGMENT_PLUGIN + + class SegmentDbMixin(common_db_mixin.CommonDbMixin): """Mixin class to add segment.""" @@ -258,7 +279,8 @@ def _update_segment_host_mapping_for_agent(resource, event, trigger, context, host, plugin, agent, status): check_segment_for_agent = getattr(plugin, 'check_segment_for_agent', None) - if not check_segment_for_agent: + if (not check_user_configured_segment_plugin() or + not check_segment_for_agent): return phys_nets = _get_phys_nets(agent) if not phys_nets: @@ -289,7 +311,8 @@ def _add_segment_host_mapping_for_segment(resource, event, trigger, return cp = directory.get_plugin() check_segment_for_agent = getattr(cp, 'check_segment_for_agent', None) - if not hasattr(cp, 'get_agents') or not check_segment_for_agent: + if not check_user_configured_segment_plugin() or not hasattr( + cp, 'get_agents') or not check_segment_for_agent: # not an agent-supporting plugin registry.unsubscribe(_add_segment_host_mapping_for_segment, resources.SEGMENT, events.PRECOMMIT_CREATE) diff --git a/neutron/tests/unit/extensions/test_segment.py b/neutron/tests/unit/extensions/test_segment.py index 32f6b6797b5..192dd0a0167 100644 --- a/neutron/tests/unit/extensions/test_segment.py +++ b/neutron/tests/unit/extensions/test_segment.py @@ -81,6 +81,7 @@ class SegmentTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): if not plugin: plugin = TEST_PLUGIN_KLASS service_plugins = {'segments_plugin_name': SERVICE_PLUGIN_KLASS} + cfg.CONF.set_override('service_plugins', [SERVICE_PLUGIN_KLASS]) ext_mgr = SegmentTestExtensionManager() super(SegmentTestCase, self).setUp(plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins) @@ -2531,3 +2532,40 @@ class TestSegmentHostRoutes(TestSegmentML2): self.assertIn(sub_res['gateway_ip'], gateway_ips) self.assertEqual(len(sub_res['host_routes']), 1) self.assertIn(sub_res['host_routes'][0], host_routes) + + +class TestSegmentHostMappingNoStore( + test_db_base_plugin_v2.NeutronDbPluginV2TestCase): + + def setUp(self): + driver_type.register_ml2_drivers_vlan_opts() + cfg.CONF.set_override('network_vlan_ranges', ['phys_net1'], + group='ml2_type_vlan') + cfg.CONF.set_override('service_plugins', []) + super(TestSegmentHostMappingNoStore, self).setUp( + plugin='neutron.plugins.ml2.plugin.Ml2Plugin') + # set to None for simulating server start + db._USER_CONFIGURED_SEGMENT_PLUGIN = None + db.subscribe() + + @mock.patch('neutron.services.segments.db.update_segment_host_mapping') + @mock.patch('neutron.services.segments.db.map_segment_to_hosts') + def test_no_segmenthostmapping_when_disable_segment( + self, mock_map_segment_to_hosts, mock_update_segment_mapping): + with self.network( + arg_list=('provider:network_type', + 'provider:physical_network', + 'provider:segmentation_id'), + **{'provider:network_type': 'vlan', + 'provider:physical_network': 'phys_net1', + 'provider:segmentation_id': '400'}) as network: + network['network'] + mock_map_segment_to_hosts.assert_not_called() + + host1 = 'test_host' + physical_network = 'phys_net1' + helpers.register_ovs_agent( + host=host1, + bridge_mappings={physical_network: 'br-eth-1'}, + plugin=self.plugin) + mock_update_segment_mapping.assert_not_called()