NSX|V3: transparent support for logical switches

Leverage the NSX networks support for transparent VLANS.
NOTE that the feature needs the configuration variable
cfg.CONF.vlan_transparent to be set to True.
(this is in the neutron configuration file)

This is currently only supported with overlay backing networks.
This is supported from NSX 2.2 onwards.

Change-Id: I4195a4fade42f798689ef19e6d6b59209547beaa
This commit is contained in:
Adit Sarfaty 2017-11-09 11:29:09 +02:00
parent c1ee02253f
commit c45004d4b7
3 changed files with 94 additions and 5 deletions

View File

@ -0,0 +1,6 @@
---
prelude: >
The NSX-V3 plugin supports transparent vlan networks.
features:
- |
The NSX-V3 plugin supports transparent vlan networks for guest vlan.

View File

@ -32,6 +32,7 @@ from neutron.api.rpc.handlers import dhcp_rpc
from neutron.api.rpc.handlers import metadata_rpc
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.common import utils as nc_utils
from neutron.db import _resource_extend as resource_extend
from neutron.db import _utils as db_utils
from neutron.db import agents_db
@ -53,8 +54,10 @@ from neutron.db import models_v2
from neutron.db import portbindings_db
from neutron.db import portsecurity_db
from neutron.db import securitygroups_db
from neutron.db import vlantransparent_db
from neutron.extensions import providernet
from neutron.extensions import securitygroup as ext_sg
from neutron.extensions import vlantransparent as ext_vlan
from neutron.plugins.common import utils as n_utils
from neutron.quota import resource_registry
from neutron_lib.api.definitions import extra_dhcp_opt as ext_edo
@ -166,6 +169,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
portsecurity_db.PortSecurityDbMixin,
extradhcpopt_db.ExtraDhcpOptMixin,
dns_db.DNSDbMixin,
vlantransparent_db.Vlantransparent_db_mixin,
mac_db.MacLearningDbMixin,
nsx_com_az.NSXAvailabilityZonesPluginCommon,
l3_attrs_db.ExtraAttributesMixin):
@ -285,6 +289,17 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if cfg.CONF.api_replay_mode:
self.supported_extension_aliases.append('api-replay')
# Support transparent VLANS from 2.2.0 onwards. The feature is only
# supported if the global configuration flag vlan_transparent is
# True
if cfg.CONF.vlan_transparent:
if self.nsxlib.feature_supported(nsxlib_consts.FEATURE_TRUNK_VLAN):
self.supported_extension_aliases.append("vlan-transparent")
else:
raise NotImplementedError(
_("Current NSX version %s doesn't support "
"transparent vlans") % self.nsxlib.get_version())
# Register NSXv3 trunk driver to support trunk extensions
self.trunk_driver = trunk_driver.NsxV3TrunkDriver.create(self)
@ -718,7 +733,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
return self.conn.consume_in_threads()
def _validate_provider_create(self, context, network_data, az):
def _validate_provider_create(self, context, network_data, az,
transparent_vlan):
is_provider_net = any(
validators.is_attr_set(network_data.get(f))
for f in (pnet.NETWORK_TYPE,
@ -833,6 +849,12 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
err_msg = (_('%(tz)s transport zone is required for '
'creating a %(net)s provider network') %
{'tz': tz_type, 'net': net_type})
elif (transparent_vlan and
tz_type == nsxlib_tz.TRANSPORT_TYPE_VLAN):
raise NotImplementedError(_(
"Transparent support only for internal overlay "
"networks"))
if not err_msg:
switch_mode = nsxlib_tz.get_host_switch_mode(physical_net)
@ -858,8 +880,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self.nsxlib.router.validate_tier0(self.tier0_groups_dict, tier0_uuid)
return (True, utils.NetworkTypes.L3_EXT, tier0_uuid, 0)
def _create_network_at_the_backend(self, context, net_data, az):
provider_data = self._validate_provider_create(context, net_data, az)
def _create_network_at_the_backend(self, context, net_data, az,
transparent_vlan):
provider_data = self._validate_provider_create(context, net_data, az,
transparent_vlan)
if (provider_data['switch_mode'] ==
self.nsxlib.transport_zone.HOST_SWITCH_MODE_ENS):
@ -892,11 +916,16 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
'tags': tags,
'admin_state': admin_state,
'vlan_id': provider_data['vlan_id']})
trunk_vlan_range = None
if transparent_vlan:
# all vlan tags are allowed for guest vlan
trunk_vlan_range = [const.MIN_VLAN_TAG, const.MAX_VLAN_TAG]
nsx_result = self.nsxlib.logical_switch.create(
net_name, provider_data['physical_net'], tags,
admin_state=admin_state,
vlan_id=provider_data['vlan_id'],
description=net_data.get('description'))
description=net_data.get('description'),
trunk_vlan_range=trunk_vlan_range)
nsx_id = nsx_result['id']
return (provider_data['is_provider_net'],
@ -991,15 +1020,26 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
az = self.get_obj_az_by_hints(net_data)
self._ensure_default_security_group(context, tenant_id)
# Update the transparent vlan if configured
vlt = False
if nc_utils.is_extension_supported(self, 'vlan-transparent'):
vlt = ext_vlan.get_vlan_transparent(net_data)
nsx_net_id = None
if validators.is_attr_set(external) and external:
if vlt:
raise NotImplementedError(_(
"Transparent support only for internal overlay networks"))
self._assert_on_external_net_with_qos(net_data)
is_provider_net, net_type, physical_net, vlan_id = (
self._validate_external_net_create(net_data))
else:
is_provider_net, net_type, physical_net, vlan_id, nsx_net_id = (
self._create_network_at_the_backend(context, net_data, az))
self._create_network_at_the_backend(context, net_data, az,
vlt))
is_backend_network = True
try:
rollback_network = False
with db_api.context_manager.writer.using(context):
@ -1039,6 +1079,11 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
neutron_net_id,
nsx_net_id)
if vlt:
super(NsxV3Plugin, self).update_network(context,
created_net['id'],
{'network': {'vlan_transparent': vlt}})
rollback_network = True
is_ddi_network = self._is_ddi_supported_on_network(
context, created_net['id'])

View File

@ -19,6 +19,7 @@ from neutron.db import models_v2
from neutron.extensions import address_scope
from neutron.extensions import l3
from neutron.extensions import securitygroup as secgrp
from neutron.extensions import vlantransparent as ext_vlan
from neutron.tests.unit import _test_extension_portbindings as test_bindings
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
from neutron.tests.unit.extensions import test_address_scope
@ -268,6 +269,17 @@ class NsxV3PluginTestCaseMixin(test_plugin.NeutronDbPluginV2TestCase,
class TestNetworksV2(test_plugin.TestNetworksV2, NsxV3PluginTestCaseMixin):
def setUp(self, plugin=PLUGIN_NAME,
ext_mgr=None,
service_plugins=None):
# add vlan transparent to the configuration
cfg.CONF.set_override('vlan_transparent', True)
super(TestNetworksV2, self).setUp(plugin=plugin,
ext_mgr=ext_mgr)
def tearDown(self):
super(TestNetworksV2, self).tearDown()
@mock.patch.object(nsx_plugin.NsxV3Plugin, 'validate_availability_zones')
def test_create_network_with_availability_zone(self, mock_validate_az):
name = 'net-with-zone'
@ -503,6 +515,32 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxV3PluginTestCaseMixin):
self.assertEqual('NsxENSPortSecurity',
res['NeutronError']['type'])
def test_create_transparent_vlan_network(self):
providernet_args = {ext_vlan.VLANTRANSPARENT: True}
with mock.patch(
'vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
'get_transport_type', return_value='OVERLAY'),\
self.network(name='vt_net',
providernet_args=providernet_args,
arg_list=(ext_vlan.VLANTRANSPARENT, )) as net:
self.assertTrue(net['network'].get(ext_vlan.VLANTRANSPARENT))
def test_create_provider_vlan_network_with_transparent(self):
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
pnet.SEGMENTATION_ID: 11,
ext_vlan.VLANTRANSPARENT: True}
with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
'get_transport_type', return_value='VLAN'):
result = self._create_network(fmt='json', name='badvlan_net',
admin_state_up=True,
providernet_args=providernet_args,
arg_list=(pnet.NETWORK_TYPE,
pnet.SEGMENTATION_ID,
ext_vlan.VLANTRANSPARENT))
data = self.deserialize('json', result)
# should fail
self.assertIn('NotImplementedError', data)
class TestSubnetsV2(test_plugin.TestSubnetsV2, NsxV3PluginTestCaseMixin):