]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
ML2 Type driver refactor part 1
authorArvind Somya <asomya@cisco.com>
Fri, 15 Aug 2014 21:22:05 +0000 (14:22 -0700)
committerArvind Somya <asomya@cisco.com>
Fri, 22 Aug 2014 18:37:25 +0000 (11:37 -0700)
This commit moves segment management from the ML2 plugin to
the type manager in preparation for dynamic segment support.

Partially implements: Blueprint ml2-type-driver-refactor

Change-Id: I068b82369250d115ef91680f19e733ed9aa4659b

neutron/plugins/ml2/managers.py
neutron/plugins/ml2/plugin.py
neutron/tests/unit/ml2/test_ml2_plugin.py

index 33293823c7944fd1deb860e1faa8e092cdb92253..d679e7dd5b21166be8f90d14f20698de10b4c0fd 100644 (file)
 from oslo.config import cfg
 import stevedore
 
+from neutron.api.v2 import attributes
 from neutron.common import exceptions as exc
+from neutron.extensions import multiprovidernet as mpnet
 from neutron.extensions import portbindings
+from neutron.extensions import providernet as provider
 from neutron.openstack.common import log
 from neutron.plugins.ml2.common import exceptions as ml2_exc
+from neutron.plugins.ml2 import db
 from neutron.plugins.ml2 import driver_api as api
 
-
 LOG = log.getLogger(__name__)
 
 
@@ -68,11 +71,95 @@ class TypeManager(stevedore.named.NamedExtensionManager):
                 raise SystemExit(1)
         LOG.info(_("Tenant network_types: %s"), self.tenant_network_types)
 
+    def _process_provider_segment(self, segment):
+        network_type = self._get_attribute(segment, provider.NETWORK_TYPE)
+        physical_network = self._get_attribute(segment,
+                                               provider.PHYSICAL_NETWORK)
+        segmentation_id = self._get_attribute(segment,
+                                              provider.SEGMENTATION_ID)
+
+        if attributes.is_attr_set(network_type):
+            segment = {api.NETWORK_TYPE: network_type,
+                       api.PHYSICAL_NETWORK: physical_network,
+                       api.SEGMENTATION_ID: segmentation_id}
+            self.validate_provider_segment(segment)
+            return segment
+
+        msg = _("network_type required")
+        raise exc.InvalidInput(error_message=msg)
+
+    def _process_provider_create(self, network):
+        if any(attributes.is_attr_set(network.get(f))
+               for f in (provider.NETWORK_TYPE, provider.PHYSICAL_NETWORK,
+                         provider.SEGMENTATION_ID)):
+            # Verify that multiprovider and provider attributes are not set
+            # at the same time.
+            if attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
+                raise mpnet.SegmentsSetInConjunctionWithProviders()
+
+            network_type = self._get_attribute(network, provider.NETWORK_TYPE)
+            physical_network = self._get_attribute(network,
+                                                   provider.PHYSICAL_NETWORK)
+            segmentation_id = self._get_attribute(network,
+                                                  provider.SEGMENTATION_ID)
+            segments = [{provider.NETWORK_TYPE: network_type,
+                         provider.PHYSICAL_NETWORK: physical_network,
+                         provider.SEGMENTATION_ID: segmentation_id}]
+            return [self._process_provider_segment(s) for s in segments]
+        elif attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
+            segments = [self._process_provider_segment(s)
+                        for s in network[mpnet.SEGMENTS]]
+            mpnet.check_duplicate_segments(
+                segments,
+                self.is_partial_segment)
+            return segments
+
+    def _get_attribute(self, attrs, key):
+        value = attrs.get(key)
+        if value is attributes.ATTR_NOT_SPECIFIED:
+            value = None
+        return value
+
+    def _extend_network_dict_provider(self, context, network):
+        id = network['id']
+        segments = db.get_network_segments(context.session, id)
+        if not segments:
+            LOG.error(_("Network %s has no segments"), id)
+            network[provider.NETWORK_TYPE] = None
+            network[provider.PHYSICAL_NETWORK] = None
+            network[provider.SEGMENTATION_ID] = None
+        elif len(segments) > 1:
+            network[mpnet.SEGMENTS] = [
+                {provider.NETWORK_TYPE: segment[api.NETWORK_TYPE],
+                 provider.PHYSICAL_NETWORK: segment[api.PHYSICAL_NETWORK],
+                 provider.SEGMENTATION_ID: segment[api.SEGMENTATION_ID]}
+                for segment in segments]
+        else:
+            segment = segments[0]
+            network[provider.NETWORK_TYPE] = segment[api.NETWORK_TYPE]
+            network[provider.PHYSICAL_NETWORK] = segment[api.PHYSICAL_NETWORK]
+            network[provider.SEGMENTATION_ID] = segment[api.SEGMENTATION_ID]
+
     def initialize(self):
         for network_type, driver in self.drivers.iteritems():
             LOG.info(_("Initializing driver for type '%s'"), network_type)
             driver.obj.initialize()
 
+    def create_network_segments(self, context, network, tenant_id):
+        """Call type drivers to create network segments."""
+        segments = self._process_provider_create(network)
+        session = context.session
+        with session.begin(subtransactions=True):
+            network_id = network['id']
+            if segments:
+                for segment in segments:
+                    segment = self.reserve_provider_segment(
+                        session, segment)
+                    db.add_network_segment(session, network_id, segment)
+            else:
+                segment = self.allocate_tenant_segment(session)
+                db.add_network_segment(session, network_id, segment)
+
     def is_partial_segment(self, segment):
         network_type = segment[api.NETWORK_TYPE]
         driver = self.drivers.get(network_type)
index c29122eaf17cd5329d504df0ce4c8fba61126164..dae053c9273227f42071696f8e52c8d9d5cf0455 100644 (file)
@@ -41,7 +41,6 @@ from neutron.db import quota_db  # noqa
 from neutron.db import securitygroups_rpc_base as sg_db_rpc
 from neutron.extensions import allowedaddresspairs as addr_pair
 from neutron.extensions import extra_dhcp_opt as edo_ext
-from neutron.extensions import multiprovidernet as mpnet
 from neutron.extensions import portbindings
 from neutron.extensions import providernet as provider
 from neutron import manager
@@ -142,75 +141,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
                                   fanout=False)
         return self.conn.consume_in_threads()
 
-    def _process_provider_segment(self, segment):
-        network_type = self._get_attribute(segment, provider.NETWORK_TYPE)
-        physical_network = self._get_attribute(segment,
-                                               provider.PHYSICAL_NETWORK)
-        segmentation_id = self._get_attribute(segment,
-                                              provider.SEGMENTATION_ID)
-
-        if attributes.is_attr_set(network_type):
-            segment = {api.NETWORK_TYPE: network_type,
-                       api.PHYSICAL_NETWORK: physical_network,
-                       api.SEGMENTATION_ID: segmentation_id}
-            self.type_manager.validate_provider_segment(segment)
-            return segment
-
-        msg = _("network_type required")
-        raise exc.InvalidInput(error_message=msg)
-
-    def _process_provider_create(self, network):
-        if any(attributes.is_attr_set(network.get(f))
-               for f in (provider.NETWORK_TYPE, provider.PHYSICAL_NETWORK,
-                         provider.SEGMENTATION_ID)):
-            # Verify that multiprovider and provider attributes are not set
-            # at the same time.
-            if attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
-                raise mpnet.SegmentsSetInConjunctionWithProviders()
-
-            network_type = self._get_attribute(network, provider.NETWORK_TYPE)
-            physical_network = self._get_attribute(network,
-                                                   provider.PHYSICAL_NETWORK)
-            segmentation_id = self._get_attribute(network,
-                                                  provider.SEGMENTATION_ID)
-            segments = [{provider.NETWORK_TYPE: network_type,
-                         provider.PHYSICAL_NETWORK: physical_network,
-                         provider.SEGMENTATION_ID: segmentation_id}]
-            return [self._process_provider_segment(s) for s in segments]
-        elif attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
-            segments = [self._process_provider_segment(s)
-                        for s in network[mpnet.SEGMENTS]]
-            mpnet.check_duplicate_segments(
-                segments,
-                self.type_manager.is_partial_segment)
-            return segments
-
-    def _get_attribute(self, attrs, key):
-        value = attrs.get(key)
-        if value is attributes.ATTR_NOT_SPECIFIED:
-            value = None
-        return value
-
-    def _extend_network_dict_provider(self, context, network):
-        id = network['id']
-        segments = db.get_network_segments(context.session, id)
-        if not segments:
-            LOG.error(_("Network %s has no segments"), id)
-            network[provider.NETWORK_TYPE] = None
-            network[provider.PHYSICAL_NETWORK] = None
-            network[provider.SEGMENTATION_ID] = None
-        elif len(segments) > 1:
-            network[mpnet.SEGMENTS] = [
-                {provider.NETWORK_TYPE: segment[api.NETWORK_TYPE],
-                 provider.PHYSICAL_NETWORK: segment[api.PHYSICAL_NETWORK],
-                 provider.SEGMENTATION_ID: segment[api.SEGMENTATION_ID]}
-                for segment in segments]
-        else:
-            segment = segments[0]
-            network[provider.NETWORK_TYPE] = segment[api.NETWORK_TYPE]
-            network[provider.PHYSICAL_NETWORK] = segment[api.PHYSICAL_NETWORK]
-            network[provider.SEGMENTATION_ID] = segment[api.SEGMENTATION_ID]
-
     def _filter_nets_provider(self, context, nets, filters):
         # TODO(rkukura): Implement filtering.
         return nets
@@ -512,26 +442,16 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
 
     def create_network(self, context, network):
         net_data = network['network']
-        segments = self._process_provider_create(net_data)
         tenant_id = self._get_tenant_id_for_create(context, net_data)
-
         session = context.session
         with session.begin(subtransactions=True):
             self._ensure_default_security_group(context, tenant_id)
             result = super(Ml2Plugin, self).create_network(context, network)
-            network_id = result['id']
             self._process_l3_create(context, result, net_data)
-            # REVISIT(rkukura): Consider moving all segment management
-            # to TypeManager.
-            if segments:
-                for segment in segments:
-                    segment = self.type_manager.reserve_provider_segment(
-                        session, segment)
-                    db.add_network_segment(session, network_id, segment)
-            else:
-                segment = self.type_manager.allocate_tenant_segment(session)
-                db.add_network_segment(session, network_id, segment)
-            self._extend_network_dict_provider(context, result)
+            net_data['id'] = result['id']
+            self.type_manager.create_network_segments(context, net_data,
+                                                      tenant_id)
+            self.type_manager._extend_network_dict_provider(context, result)
             mech_context = driver_context.NetworkContext(self, context,
                                                          result)
             self.mechanism_manager.create_network_precommit(mech_context)
@@ -556,7 +476,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
                                                                     network)
             self._process_l3_update(context, updated_network,
                                     network['network'])
-            self._extend_network_dict_provider(context, updated_network)
+            self.type_manager._extend_network_dict_provider(context,
+                                                            updated_network)
             mech_context = driver_context.NetworkContext(
                 self, context, updated_network,
                 original_network=original_network)
@@ -573,7 +494,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
         session = context.session
         with session.begin(subtransactions=True):
             result = super(Ml2Plugin, self).get_network(context, id, None)
-            self._extend_network_dict_provider(context, result)
+            self.type_manager._extend_network_dict_provider(context, result)
 
         return self._fields(result, fields)
 
@@ -585,7 +506,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
                          self).get_networks(context, filters, None, sorts,
                                             limit, marker, page_reverse)
             for net in nets:
-                self._extend_network_dict_provider(context, net)
+                self.type_manager._extend_network_dict_provider(context, net)
 
             nets = self._filter_nets_provider(context, nets, filters)
             nets = self._filter_nets_l3(context, nets, filters)
index 6cbc858013c927b1d1d992e7086bb650e7dbfbfb..5e2d261ae48be623b3ac2430baa098208c5cf7cc 100644 (file)
@@ -477,7 +477,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase):
                    pnet.PHYSICAL_NETWORK: 'phys_net',
                    pnet.SEGMENTATION_ID: None}
         with testtools.ExpectedException(exc.InvalidInput):
-            self.driver._process_provider_create(segment)
+            self.driver.type_manager._process_provider_create(segment)
 
     def test_create_network_plugin(self):
         data = {'network': {'name': 'net1',
@@ -499,7 +499,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase):
 
     def test_extend_dictionary_no_segments(self):
         network = dict(name='net_no_segment', id='5', tenant_id='tenant_one')
-        self.driver._extend_network_dict_provider(self.context, network)
+        self.driver.type_manager._extend_network_dict_provider(self.context,
+                                                               network)
         self.assertIsNone(network[pnet.NETWORK_TYPE])
         self.assertIsNone(network[pnet.PHYSICAL_NETWORK])
         self.assertIsNone(network[pnet.SEGMENTATION_ID])