Adding VLAN Transparency support for ML2 along with REST API changes

* 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
This commit is contained in:
Pritesh Kothari 2015-02-23 09:52:28 -08:00
parent 87a534f9b0
commit 7dbe0d0486
11 changed files with 57 additions and 3 deletions

View 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

View 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,

View 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 = [

View 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)

View 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.")

View 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):

View 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):

View 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)

View 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",

View 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'}}

View 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)