diff --git a/devstack/lib/vmware_nsx_v3 b/devstack/lib/vmware_nsx_v3 index 26b033d4a1..5d415403a3 100644 --- a/devstack/lib/vmware_nsx_v3 +++ b/devstack/lib/vmware_nsx_v3 @@ -100,10 +100,10 @@ function _nsxv3_ini_set { } function neutron_plugin_configure_service { - _nsxv3_ini_set default_overlay_tz_uuid $DEFAULT_OVERLAY_TZ_UUID "The VMware NSX plugin won't work without a default transport zone." - _nsxv3_ini_set default_vlan_tz_uuid $DEFAULT_VLAN_TZ_UUID + _nsxv3_ini_set default_overlay_tz $DEFAULT_OVERLAY_TZ_UUID "The VMware NSX plugin won't work without a default transport zone." + _nsxv3_ini_set default_vlan_tz $DEFAULT_VLAN_TZ_UUID if [[ "$DEFAULT_TIER0_ROUTER_UUID" != "" ]]; then - _nsxv3_ini_set default_tier0_router_uuid $DEFAULT_TIER0_ROUTER_UUID + _nsxv3_ini_set default_tier0_router $DEFAULT_TIER0_ROUTER_UUID Q_L3_ENABLED=True Q_L3_ROUTER_PER_TENANT=True fi @@ -123,7 +123,7 @@ function neutron_plugin_configure_service { _nsxv3_ini_set retries $NSX_RETRIES _nsxv3_ini_set insecure $NSX_INSECURE _nsxv3_ini_set ca_file $NSX_CA_FILE - _nsxv3_ini_set default_bridge_cluster_uuid $DEFAULT_BRIDGE_CLUSTER_UUID + _nsxv3_ini_set default_bridge_cluster $DEFAULT_BRIDGE_CLUSTER_UUID } function neutron_plugin_setup_interface_driver { diff --git a/releasenotes/notes/rename_uuid_config_params-b36c379f64838334.yaml b/releasenotes/notes/rename_uuid_config_params-b36c379f64838334.yaml new file mode 100644 index 0000000000..a34c8fa8e5 --- /dev/null +++ b/releasenotes/notes/rename_uuid_config_params-b36c379f64838334.yaml @@ -0,0 +1,13 @@ +--- +prelude: > + The 'default_tier0_router_uuid', 'default_overlay_tz_uuid', + 'default_vlan_tz_uuid', and 'default_bridge_cluster_uuid' + options have been deprecated and replaced by 'default_tier0_router', + 'default_overlay_tz', 'default_vlan_tz', and 'default_bridge_cluster' + respectively, which can accept both name or uuid +deprecations: + - The 'default_tier0_router_uuid', 'default_overlay_tz_uuid', + 'default_vlan_tz_uuid', and 'default_bridge_cluster_uuid' + options have been deprecated and replaced by 'default_tier0_router', + 'default_overlay_tz', 'default_vlan_tz', and 'default_bridge_cluster' + respectively, which can accept both name or uuid diff --git a/vmware_nsx/common/config.py b/vmware_nsx/common/config.py index b4d194d76f..507f73743b 100644 --- a/vmware_nsx/common/config.py +++ b/vmware_nsx/common/config.py @@ -249,25 +249,30 @@ nsx_v3_opts = [ "[://][:]\nIf scheme is not " "provided https is used. If port is not provided port " "80 is used for http and port 443 for https.")), - cfg.StrOpt('default_overlay_tz_uuid', - deprecated_name='default_tz_uuid', - help=_("This is the UUID of the default NSX overlay transport " - "zone that will be used for creating tunneled isolated " - "Neutron networks. It needs to be created in NSX " - "before starting Neutron with the NSX plugin.")), - cfg.StrOpt('default_vlan_tz_uuid', + cfg.StrOpt('default_overlay_tz', + deprecated_name='default_overlay_tz_uuid', + help=_("This is the name or UUID of the default NSX overlay " + "transport zone that will be used for creating " + "tunneled isolated Neutron networks. It needs to be " + "created in NSX before starting Neutron with the NSX " + "plugin.")), + cfg.StrOpt('default_vlan_tz', + deprecated_name='default_vlan_tz_uuid', help=_("(Optional) Only required when creating VLAN or flat " - "provider networks. UUID of default NSX VLAN transport " - "zone that will be used for bridging between Neutron " - "networks, if no physical network has been specified")), - cfg.StrOpt('default_bridge_cluster_uuid', - help=_("(Optional) UUID of the default NSX bridge cluster that " - "will be used to perform L2 gateway bridging between " - "VXLAN and VLAN networks. If default bridge cluster " - "UUID is not specified, admin will have to manually " - "create a L2 gateway corresponding to a NSX Bridge " - "Cluster using L2 gateway APIs. This field must be " - "specified on one of the active neutron servers only.")), + "provider networks. Name or UUID of default NSX VLAN " + "transport zone that will be used for bridging between " + "Neutron networks, if no physical network has been " + "specified")), + cfg.StrOpt('default_bridge_cluster', + deprecated_name='default_bridge_cluster_uuid', + help=_("(Optional) Name or UUID of the default NSX bridge " + "cluster that will be used to perform L2 gateway " + "bridging between VXLAN and VLAN networks. If default " + "bridge cluster UUID is not specified, admin will have " + "to manually create a L2 gateway corresponding to a " + "NSX Bridge Cluster using L2 gateway APIs. This field " + "must be specified on one of the active neutron " + "servers only.")), cfg.IntOpt('retries', default=10, help=_('Maximum number of times to retry API requests upon ' @@ -306,10 +311,11 @@ nsx_v3_opts = [ cfg.IntOpt('redirects', default=2, help=_('Number of times a HTTP redirect should be followed.')), - cfg.StrOpt('default_tier0_router_uuid', - help=_("UUID of the default tier0 router that will be used for " - "connecting to tier1 logical routers and configuring " - "external networks")), + cfg.StrOpt('default_tier0_router', + deprecated_name='default_tier0_router_uuid', + help=_("Name or UUID of the default tier0 router that will be " + "used for connecting to tier1 logical routers and " + "configuring external networks")), cfg.IntOpt('number_of_nested_groups', default=8, help=_("(Optional) The number of nested groups which are used " diff --git a/vmware_nsx/nsxlib/v3/__init__.py b/vmware_nsx/nsxlib/v3/__init__.py index d5b555c5ed..71ad55cea9 100644 --- a/vmware_nsx/nsxlib/v3/__init__.py +++ b/vmware_nsx/nsxlib/v3/__init__.py @@ -231,3 +231,57 @@ def delete_bridge_endpoint(bridge_endpoint_id): """ resource = 'bridge-endpoints/%s' % bridge_endpoint_id client.delete_resource(resource) + + +def _get_resource_by_name_or_id(name_or_id, resource): + all_results = client.get_resource(resource)['results'] + matched_results = [] + for rs in all_results: + if rs.get('id') == name_or_id: + # Matched by id - must be unique + return name_or_id + + if rs.get('display_name') == name_or_id: + # Matched by name - add to the list to verify it is unique + matched_results.append(rs) + + if len(matched_results) == 0: + err_msg = (_("Could not find %(resource)s %(name)s") % + {'name': name_or_id, 'resource': resource}) + raise nsx_exc.NsxPluginException(err_msg=err_msg) + elif len(matched_results) > 1: + err_msg = (_("Found multiple %(resource)s named %(name)s") % + {'name': name_or_id, 'resource': resource}) + raise nsx_exc.NsxPluginException(err_msg=err_msg) + + return matched_results[0].get('id') + + +def get_transport_zone_id_by_name_or_id(name_or_id): + """Get a transport zone by it's display name or uuid + + Return the transport zone data, or raise an exception if not found or + not unique + """ + + return _get_resource_by_name_or_id(name_or_id, 'transport-zones') + + +def get_logical_router_id_by_name_or_id(name_or_id): + """Get a logical router by it's display name or uuid + + Return the logical router data, or raise an exception if not found or + not unique + """ + + return _get_resource_by_name_or_id(name_or_id, 'logical-routers') + + +def get_bridge_cluster_id_by_name_or_id(name_or_id): + """Get a bridge cluster by it's display name or uuid + + Return the bridge cluster data, or raise an exception if not found or + not unique + """ + + return _get_resource_by_name_or_id(name_or_id, 'bridge-clusters') diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 69b8178255..c240a36755 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -180,6 +180,31 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, raise nsx_exc.NsxPluginException(msg) self._unsubscribe_callback_events() + # translate configured transport zones/rotuers names to uuid + self._translate_configured_names_2_uuids() + + def _translate_configured_names_2_uuids(self): + # default VLAN transport zone name / uuid + self._default_vlan_tz_uuid = None + if cfg.CONF.nsx_v3.default_vlan_tz: + tz_id = nsxlib.get_transport_zone_id_by_name_or_id( + cfg.CONF.nsx_v3.default_vlan_tz) + self._default_vlan_tz_uuid = tz_id + + # default overlay transport zone name / uuid + self._default_overlay_tz_uuid = None + if cfg.CONF.nsx_v3.default_overlay_tz: + tz_id = nsxlib.get_transport_zone_id_by_name_or_id( + cfg.CONF.nsx_v3.default_overlay_tz) + self._default_overlay_tz_uuid = tz_id + + # default tier0 router + self._default_tier0_router = None + if cfg.CONF.nsx_v3.default_tier0_router: + rtr_id = nsxlib.get_logical_router_id_by_name_or_id( + cfg.CONF.nsx_v3.default_tier0_router) + self._default_tier0_router = rtr_id + def _extend_port_dict_binding(self, context, port_data): port_data[pbin.VIF_TYPE] = pbin.VIF_TYPE_OVS port_data[pbin.VNIC_TYPE] = pbin.VNIC_NORMAL @@ -344,11 +369,11 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, # Set VLAN id to 0 for flat networks vlan_id = '0' if physical_net is None: - physical_net = cfg.CONF.nsx_v3.default_vlan_tz_uuid + physical_net = self._default_vlan_tz_uuid elif net_type == utils.NsxV3NetworkTypes.VLAN: # Use default VLAN transport zone if physical network not given if physical_net is None: - physical_net = cfg.CONF.nsx_v3.default_vlan_tz_uuid + physical_net = self._default_vlan_tz_uuid # Validate VLAN id if not vlan_id: @@ -394,7 +419,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, if physical_net is None: # Default to transport type overlay - physical_net = cfg.CONF.nsx_v3.default_overlay_tz_uuid + physical_net = self._default_overlay_tz_uuid return is_provider_net, net_type, physical_net, vlan_id @@ -407,7 +432,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, def _validate_external_net_create(self, net_data): is_provider_net = False if not attributes.is_attr_set(net_data.get(pnet.PHYSICAL_NETWORK)): - tier0_uuid = cfg.CONF.nsx_v3.default_tier0_router_uuid + tier0_uuid = self._default_tier0_router else: tier0_uuid = net_data[pnet.PHYSICAL_NETWORK] is_provider_net = True @@ -1237,7 +1262,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, return network = self.get_network(context, network_id) if not network.get(pnet.PHYSICAL_NETWORK): - return cfg.CONF.nsx_v3.default_tier0_router_uuid + return self._default_tier0_router else: return network.get(pnet.PHYSICAL_NETWORK) diff --git a/vmware_nsx/services/l2gateway/nsx_v3/driver.py b/vmware_nsx/services/l2gateway/nsx_v3/driver.py index b52c4808ec..ab1d886741 100644 --- a/vmware_nsx/services/l2gateway/nsx_v3/driver.py +++ b/vmware_nsx/services/l2gateway/nsx_v3/driver.py @@ -49,7 +49,7 @@ class NsxV3Driver(l2gateway_db.L2GatewayMixin): gateway_resource = l2gw_const.GATEWAY_RESOURCE_NAME def __init__(self): - # Create a default L2 gateway if default_bridge_cluster_uuid is + # Create a default L2 gateway if default_bridge_cluster is # provided in nsx.ini self._ensure_default_l2_gateway() self.subscribe_callback_notifications() @@ -69,16 +69,20 @@ class NsxV3Driver(l2gateway_db.L2GatewayMixin): Create a default logical L2 gateway. Create a logical L2 gateway in the neutron database if the - default_bridge_cluster_uuid config parameter is set and if it is + default_bridge_cluster config parameter is set and if it is not previously created. If not set, return. """ - def_l2gw_uuid = cfg.CONF.nsx_v3.default_bridge_cluster_uuid - # Return if no default_bridge_cluster_uuid set in config - if not def_l2gw_uuid: - LOG.info(_LI("NSX: Default bridge cluster UUID not configured " + def_l2gw_name = cfg.CONF.nsx_v3.default_bridge_cluster + # Return if no default_bridge_cluster set in config + if not def_l2gw_name: + LOG.info(_LI("NSX: Default bridge cluster not configured " "in nsx.ini. No default L2 gateway created.")) return admin_ctx = context.get_admin_context() + + def_l2gw_uuid = nsxlib.get_bridge_cluster_id_by_name_or_id( + def_l2gw_name) + # Optimistically create the default L2 gateway in neutron DB device = {'device_name': def_l2gw_uuid, 'interfaces': [{'name': 'default-bridge-cluster'}]} diff --git a/vmware_nsx/tests/unit/nsx_v3/mocks.py b/vmware_nsx/tests/unit/nsx_v3/mocks.py index 79c5d2249f..0c336ef9f8 100644 --- a/vmware_nsx/tests/unit/nsx_v3/mocks.py +++ b/vmware_nsx/tests/unit/nsx_v3/mocks.py @@ -22,6 +22,7 @@ from vmware_nsx.common import nsx_constants FAKE_NAME = "fake_name" DEFAULT_TIER0_ROUTER_UUID = "efad0078-9204-4b46-a2d8-d4dd31ed448f" +NSX_BRIDGE_CLUSTER_NAME = 'default bridge cluster' FAKE_MANAGER = "fake_manager_ip" diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index b07e2183fb..5e3758f0c4 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -123,6 +123,20 @@ class NsxV3PluginTestCaseMixin(test_plugin.NeutronDbPluginV2TestCase, 'display_name': nsx_plugin.NSX_V3_NO_PSEC_PROFILE_NAME }), headers=nsx_client.JSONRESTClient._DEFAULT_HEADERS) + self.mock_api.post( + 'api/v1/transport-zones', + data=jsonutils.dumps({ + 'id': uuidutils.generate_uuid(), + 'display_name': nsxlib_testcase.NSX_TZ_NAME + }), headers=nsx_client.JSONRESTClient._DEFAULT_HEADERS) + + self.mock_api.post( + 'api/v1/bridge-clusters', + data=jsonutils.dumps({ + 'id': uuidutils.generate_uuid(), + 'display_name': nsx_v3_mocks.NSX_BRIDGE_CLUSTER_NAME + }), headers=nsx_client.JSONRESTClient._DEFAULT_HEADERS) + super(NsxV3PluginTestCaseMixin, self).setUp(plugin=plugin, ext_mgr=ext_mgr) diff --git a/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py b/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py index bc15e52f9d..6f5c880f1f 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py @@ -18,8 +18,8 @@ import mock import unittest from oslo_config import cfg -from oslo_utils import uuidutils from requests import exceptions as requests_exceptions + from vmware_nsx.nsxlib.v3 import client as nsx_client from vmware_nsx.nsxlib.v3 import cluster as nsx_cluster @@ -30,6 +30,7 @@ NSX_INSECURE = False NSX_CERT = '/opt/stack/certs/nsx.pem' NSX_HTTP_TIMEOUT = 10 NSX_HTTP_READ_TIMEOUT = 180 +NSX_TZ_NAME = 'default transport zone' V3_CLIENT_PKG = 'vmware_nsx.nsxlib.v3.client' BRIDGE_FNS = ['create_resource', 'delete_resource', @@ -40,8 +41,7 @@ class NsxLibTestCase(unittest.TestCase): @classmethod def setup_conf_overrides(cls): - cfg.CONF.set_override('default_overlay_tz_uuid', - uuidutils.generate_uuid(), 'nsx_v3') + cfg.CONF.set_override('default_overlay_tz', NSX_TZ_NAME, 'nsx_v3') cfg.CONF.set_override('nsx_api_user', NSX_USER, 'nsx_v3') cfg.CONF.set_override('nsx_api_password', NSX_PASSWORD, 'nsx_v3') cfg.CONF.set_override('nsx_api_managers', [NSX_MANAGER], 'nsx_v3') diff --git a/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py b/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py index 9a2f689936..17a359b273 100644 --- a/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py +++ b/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py @@ -26,8 +26,10 @@ from neutron.tests import base from neutron_lib import exceptions as n_exc from vmware_nsx.common import nsx_constants +from vmware_nsx.nsxlib import v3 as nsxlib from vmware_nsx.services.l2gateway.common import plugin as l2gw_plugin from vmware_nsx.services.l2gateway.nsx_v3 import driver as nsx_v3_driver +from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsx_v3_plugin @@ -69,14 +71,16 @@ class TestNsxV3L2GatewayDriver(test_l2gw_db.L2GWTestCase, self.assertTrue(debug.called) def test_create_default_l2_gateway(self): - def_bridge_cluster_id = uuidutils.generate_uuid() + def_bridge_cluster_name = nsx_v3_mocks.NSX_BRIDGE_CLUSTER_NAME with mock.patch.object(nsx_v3_driver.NsxV3Driver, 'subscribe_callback_notifications'): - cfg.CONF.set_override("default_bridge_cluster_uuid", - def_bridge_cluster_id, + cfg.CONF.set_override("default_bridge_cluster", + def_bridge_cluster_name, "nsx_v3") l2gw_plugin.NsxL2GatewayPlugin() l2gws = self.driver._get_l2_gateways(self.context) + def_bridge_cluster_id = nsxlib.get_bridge_cluster_id_by_name_or_id( + def_bridge_cluster_name) def_l2gw = None for l2gw in l2gws: for device in l2gw['devices']: @@ -89,11 +93,11 @@ class TestNsxV3L2GatewayDriver(test_l2gw_db.L2GWTestCase, 'default-bridge-cluster') def test_create_duplicate_default_l2_gateway_noop(self): - def_bridge_cluster_id = uuidutils.generate_uuid() + def_bridge_cluster_name = nsx_v3_mocks.NSX_BRIDGE_CLUSTER_NAME with mock.patch.object(nsx_v3_driver.NsxV3Driver, 'subscribe_callback_notifications'): - cfg.CONF.set_override("default_bridge_cluster_uuid", - def_bridge_cluster_id, + cfg.CONF.set_override("default_bridge_cluster", + def_bridge_cluster_name, "nsx_v3") l2gw_plugin.NsxL2GatewayPlugin() l2gw_plugin.NsxL2GatewayPlugin()