From c45004d4b70a5dde8972c5c1735e44ba4050ed25 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Thu, 9 Nov 2017 11:29:09 +0200 Subject: [PATCH] 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 --- ...xv3-trnasparent-vlan-fe06e1d3aa2fbcd9.yaml | 6 ++ vmware_nsx/plugins/nsx_v3/plugin.py | 55 +++++++++++++++++-- vmware_nsx/tests/unit/nsx_v3/test_plugin.py | 38 +++++++++++++ 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/nsxv3-trnasparent-vlan-fe06e1d3aa2fbcd9.yaml diff --git a/releasenotes/notes/nsxv3-trnasparent-vlan-fe06e1d3aa2fbcd9.yaml b/releasenotes/notes/nsxv3-trnasparent-vlan-fe06e1d3aa2fbcd9.yaml new file mode 100644 index 0000000000..48adb67864 --- /dev/null +++ b/releasenotes/notes/nsxv3-trnasparent-vlan-fe06e1d3aa2fbcd9.yaml @@ -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. diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index f46d2a7009..f72d2d2470 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -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']) diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index e82be3c9cc..637536aaaf 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -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):