]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Adding VLAN Transparency support for ML2 along with REST API changes
authorPritesh Kothari <pritesh.kothari@cisco.com>
Mon, 23 Feb 2015 17:52:28 +0000 (09:52 -0800)
committerPritesh Kothari <pritesh.kothari@cisco.com>
Wed, 18 Mar 2015 18:46:03 +0000 (11:46 -0700)
* Exposing vlan transparency attributes via the network api
  calls so POST and GET operations can be performed.
* Tied in the vlan transparency attribute with create network
  call and use the config default.
* Update the unit test to cover vlan tranparency.
* Add support for ml2 to take advantage of vlan transparency
  attribute.

DocImpact
APIImpact
Partially Implements: blueprint nfv-vlan-trunks

Change-Id: Ie87087a70b83dab589419aa5c17ce7ccafd64cbd

etc/neutron.conf
neutron/api/v2/attributes.py
neutron/common/config.py
neutron/db/db_base_plugin_v2.py
neutron/plugins/ml2/common/exceptions.py
neutron/plugins/ml2/driver_api.py
neutron/plugins/ml2/managers.py
neutron/tests/functional/api/test_v2_plugin.py
neutron/tests/unit/test_api_v2.py
neutron/tests/unit/test_db_plugin.py
neutron/tests/unit/test_extension_pnet.py

index eb25c750350a9f5a1b6963387120a349c5af3059..02ce4f1db6906ad38cb9a7f3d9cb3fc171dd4d44 100644 (file)
@@ -207,6 +207,13 @@ lock_path = $state_path/lock
 # l3_ha_net_cidr = 169.254.192.0/18
 # =========== end of items for l3 extension =======
 
+# ========== items for VLAN trunking networks ==========
+# Setting this flag to True will allow plugins that support it to
+# create VLAN transparent networks. This flag has no effect for
+# plugins that do not support VLAN transparent networks.
+# vlan_transparent = False
+# ========== end of items for VLAN trunking networks ==========
+
 # =========== WSGI parameters related to the API server ==============
 # Number of separate worker processes to spawn.  The default, 0, runs the
 # worker thread in the current process.  Greater than 0 launches that number of
index 8235e000fdfef792a97123028a642c4785df3490..a776ac428f79e62153aef9dddd43c80b0b9c54f1 100644 (file)
@@ -698,6 +698,9 @@ RESOURCE_ATTRIBUTE_MAP = {
                       'validate': {'type:string': None},
                       'required_by_policy': True,
                       'is_visible': True},
+        'vlan_transparent': {'allow_post': True, 'allow_put': False,
+                             'convert_to': convert_to_boolean,
+                             'default': False, 'is_visible': True},
         SHARED: {'allow_post': True,
                  'allow_put': True,
                  'default': False,
index a0572c94eba255abfce99349f0ee66547c01ff09..11c505997421dcfe57b2e7141683eaf24d6cd8fd 100644 (file)
@@ -125,6 +125,9 @@ core_opts = [
                 help=_('If True, effort is made to advertise MTU settings '
                        'to VMs via network methods (DHCP and RA MTU options) '
                        'when the network\'s preferred MTU is known.')),
+    cfg.BoolOpt('vlan_transparent', default=False,
+                help=_('If True, then allow plugins that support it to '
+                       'create VLAN transparent networks.')),
 ]
 
 core_cli_opts = [
index 8950da5b41f7e2bbeebb2b5803a47ffd0bc3cfd8..fad9665e7b70f68a4a5f8da30e3a14b28f911096 100644 (file)
@@ -784,6 +784,7 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                'mtu': network.get('mtu', constants.DEFAULT_NETWORK_MTU),
                'status': network['status'],
                'shared': network['shared'],
+               'vlan_transparent': network['vlan_transparent'],
                'subnets': [subnet['id']
                            for subnet in network['subnets']]}
         # Call auxiliary extend functions, if any
@@ -872,6 +873,7 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                     'admin_state_up': n['admin_state_up'],
                     'mtu': n.get('mtu', constants.DEFAULT_NETWORK_MTU),
                     'shared': n['shared'],
+                    'vlan_transparent': n.get('vlan_transparent', False),
                     'status': n.get('status', constants.NET_STATUS_ACTIVE)}
             network = models_v2.Network(**args)
             context.session.add(network)
index ed94b1e1f14072d328d3daa0c24b804798d64652..41f46944f6acf963889dda06aad4dd2a920424e5 100644 (file)
@@ -21,3 +21,8 @@ from neutron.common import exceptions
 class MechanismDriverError(exceptions.NeutronException):
     """Mechanism driver call failed."""
     message = _("%(method)s failed.")
+
+
+class VlanTransparencyError(exceptions.NeutronException):
+    """Vlan Transparency not supported by all mechanism drivers."""
+    message = _("Backend does not support VLAN Transparency.")
index 894a5c3d3019d0a4bce2c8b1dc12771a284a7f4b..15503ff36fce59f805567ecaf6d14c1732d9b9c6 100644 (file)
@@ -811,6 +811,15 @@ class MechanismDriver(object):
         """
         pass
 
+    def check_vlan_transparency(self, context):
+        """Check if the network supports vlan transparency.
+
+        :param context: NetworkContext instance describing the network.
+
+        Check if the network supports vlan transparency or not.
+        """
+        pass
+
 
 @six.add_metaclass(abc.ABCMeta)
 class ExtensionDriver(object):
index 1d4a2162b42f932de4843e935fdb0e6014578b93..df932c66bb87504980a9f4be647c214892da5bb5 100644 (file)
@@ -293,6 +293,19 @@ class MechanismManager(stevedore.named.NamedExtensionManager):
             LOG.info(_LI("Initializing mechanism driver '%s'"), driver.name)
             driver.obj.initialize()
 
+    def _check_vlan_transparency(self, context):
+        """Helper method for checking vlan transparecncy support.
+
+        :param context: context parameter to pass to each method call
+        :raises: neutron.plugins.ml2.common.VlanTransparencyError
+        if any mechanism driver doesn't support vlan transparency.
+        """
+        if not cfg.CONF.vlan_transparent:
+            return
+        for driver in self.ordered_mech_drivers:
+            if driver.obj.check_vlan_transparency(context) is False:
+                raise ml2_exc.VlanTransparencyError()
+
     def _call_on_drivers(self, method_name, context,
                          continue_on_failure=False):
         """Helper method for calling a method across all mechanism drivers.
@@ -332,6 +345,7 @@ class MechanismManager(stevedore.named.NamedExtensionManager):
         to the caller, triggering a rollback. There is no guarantee
         that all mechanism drivers are called in this case.
         """
+        self._check_vlan_transparency(context)
         self._call_on_drivers("create_network_precommit", context)
 
     def create_network_postcommit(self, context):
index 081f6df7483fe278af189a817a08670c22514a7f..76eafe5b10889919c081614d964eedad474505ce 100644 (file)
@@ -65,6 +65,7 @@ class PluginClient(base_v2.BaseNeutronClient):
         # Supply defaults that are expected to be set by the api
         # framwork
         kwargs.setdefault('admin_state_up', True)
+        kwargs.setdefault('vlan_transparent', False)
         kwargs.setdefault('shared', False)
         data = dict(network=kwargs)
         result = self.plugin.create_network(self.ctx, data)
index 75d2a26e251292594325e6f9863fb59b252990b3..de9d079c41da111a305e4b7e5b2e158333b4994f 100644 (file)
@@ -768,6 +768,7 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase):
         net_id = _uuid()
         initial_input = {'network': {'name': 'net1', 'tenant_id': _uuid()}}
         full_input = {'network': {'admin_state_up': True,
+                                  'vlan_transparent': False,
                                   'shared': False}}
         full_input['network'].update(initial_input['network'])
 
@@ -802,6 +803,7 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase):
         # tenant_id should be fetched from env
         initial_input = {'network': {'name': 'net1'}}
         full_input = {'network': {'admin_state_up': True,
+                      'vlan_transparent': False,
                       'shared': False, 'tenant_id': tenant_id}}
         full_input['network'].update(initial_input['network'])
 
@@ -1411,7 +1413,8 @@ class ExtensionTestCase(base.BaseTestCase, testlib_plugin.PluginSetupHelper):
         net_id = _uuid()
         initial_input = {'network': {'name': 'net1', 'tenant_id': _uuid(),
                                      'v2attrs:something_else': "abc"}}
-        data = {'network': {'admin_state_up': True, 'shared': False}}
+        data = {'network': {'admin_state_up': True, 'shared': False,
+                            'vlan_transparent': False}}
         data['network'].update(initial_input['network'])
 
         return_value = {'subnets': [], 'status': "ACTIVE",
index 2e727953efca6efca27ff7bcd57084405239db3f..ff7246212a72faa2043aa57a00d36a121ddfa177 100644 (file)
@@ -296,8 +296,8 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase,
         data = {'network': {'name': name,
                             'admin_state_up': admin_state_up,
                             'tenant_id': self._tenant_id}}
-        for arg in (('admin_state_up', 'tenant_id', 'shared') +
-                    (arg_list or ())):
+        for arg in (('admin_state_up', 'tenant_id', 'shared',
+                     'vlan_transparent') + (arg_list or ())):
             # Arg must be present
             if arg in kwargs:
                 data['network'][arg] = kwargs[arg]
@@ -2033,6 +2033,12 @@ class TestNetworksV2(NeutronDbPluginV2TestCase):
             self.assertEqual(net['network']['mtu'],
                              constants.DEFAULT_NETWORK_MTU)
 
+    def test_create_network_vlan_transparent(self):
+        name = "vlan_transparent"
+        cfg.CONF.set_override('vlan_transparent', True)
+        with self.network(name=name, vlan_transparent=True) as net:
+            self.assertEqual(net['network']['vlan_transparent'], True)
+
     def test_update_network(self):
         with self.network() as network:
             data = {'network': {'name': 'a_brand_new_name'}}
index 420745986fabbdc38703038a9f667587ac2b7cd2..a2bf86757b5d6af5c2ae63f04c70857dbf950a44 100644 (file)
@@ -141,6 +141,7 @@ class ProvidernetExtensionTestCase(testlib_api.WebTestCase,
         exp_input = {'network': data}
         exp_input['network'].update({'admin_state_up': True,
                                      'tenant_id': 'an_admin',
+                                     'vlan_transparent': False,
                                      'shared': False})
         instance.create_network.assert_called_with(mock.ANY,
                                                    network=exp_input)