From a2ed921b63b0472be47039a6fed0d12fa6d51908 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Mon, 28 Oct 2019 12:42:55 +0200 Subject: [PATCH] NSX|P: Fix metadata get_subnets Nova calls get_subnets with advanced-service-providers to get the subnets with sepcific nsx IDS. Since the policy plugin is unaware of the MP lswitch id, it will need to get it from the mp, and use the tags to find out the neutron id. The resutls will be cached. Change-Id: Ib6fa0b36f105f745102b0998dd07d884e8377212 --- vmware_nsx/plugins/nsx_p/plugin.py | 49 +++++++++++++++---- .../tests/unit/nsx_p/test_dhcp_metadata.py | 17 ++++--- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/vmware_nsx/plugins/nsx_p/plugin.py b/vmware_nsx/plugins/nsx_p/plugin.py index 36a697154c..32cdf57fdc 100644 --- a/vmware_nsx/plugins/nsx_p/plugin.py +++ b/vmware_nsx/plugins/nsx_p/plugin.py @@ -136,7 +136,9 @@ NAT_RULE_PRIORITY_GW = 3000 NSX_P_CLIENT_SSL_PROFILE = 'neutron-client-ssl-profile' -NET_NSX_ID_CACHE = {} +# Cache for mapping between network ids in neutron and NSX (MP) +NET_NEUTRON_2_NSX_ID_CACHE = {} +NET_NSX_2_NEUTRON_ID_CACHE = {} @resource_extend.has_resource_extenders @@ -810,9 +812,11 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): {'id': network_id, 'e': e}) raise nsx_exc.NsxPluginException(err_msg=msg) - # Remove from cache - if network_id in NET_NSX_ID_CACHE: - del NET_NSX_ID_CACHE[network_id] + # Remove from caches + if network_id in NET_NEUTRON_2_NSX_ID_CACHE: + nsx_id = NET_NEUTRON_2_NSX_ID_CACHE[network_id] + del NET_NEUTRON_2_NSX_ID_CACHE[network_id] + del NET_NSX_2_NEUTRON_ID_CACHE[nsx_id] def update_network(self, context, network_id, network): original_net = super(NsxPolicyPlugin, self).get_network( @@ -967,23 +971,24 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): If it was not realized or timed out retrying, it will return None The nova api will use this to attach to the instance. """ - if network_id in NET_NSX_ID_CACHE: - return NET_NSX_ID_CACHE[network_id] + if network_id in NET_NEUTRON_2_NSX_ID_CACHE: + return NET_NEUTRON_2_NSX_ID_CACHE[network_id] if not self._network_is_external(context, network_id): segment_id = self._get_network_nsx_segment_id(context, network_id) try: nsx_id = self.nsxpolicy.segment.get_realized_logical_switch_id( segment_id) - # Add result to cache - NET_NSX_ID_CACHE[network_id] = nsx_id + # Add result to caches + NET_NEUTRON_2_NSX_ID_CACHE[network_id] = nsx_id + NET_NSX_2_NEUTRON_ID_CACHE[nsx_id] = network_id return nsx_id except nsx_lib_exc.ManagerError: LOG.error("Network %s was not realized", network_id) # Do not cache this result else: # Add empty result to cache - NET_NSX_ID_CACHE[network_id] = None + NET_NEUTRON_2_NSX_ID_CACHE[network_id] = None def _get_network_nsx_segment_id(self, context, network_id): """Return the NSX segment ID matching the neutron network id @@ -2961,7 +2966,31 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): return True def _get_neutron_net_ids_by_nsx_id(self, context, lswitch_id): - return [lswitch_id] + """Translate nsx ls IDs given by Nova to neutron network ids. + + Since there is no DB mapping for this, the plugin will query the NSX + for this, and cache the results. + """ + if lswitch_id not in NET_NSX_2_NEUTRON_ID_CACHE: + # Go to the nsx using passthrough api to get the neutron id + if not cfg.CONF.nsx_p.allow_passthrough: + LOG.warning("Cannot get neutron id for ls %s without " + "passthrough api", lswitch_id) + return [] + ls = self.nsxlib.logical_switch.get(lswitch_id) + neutron_id = None + for tag in ls.get('tags', []): + if tag['scope'] == 'os-neutron-net-id': + neutron_id = tag['tag'] + break + if neutron_id: + # Cache the result + NET_NSX_2_NEUTRON_ID_CACHE[lswitch_id] = neutron_id + NET_NEUTRON_2_NSX_ID_CACHE[neutron_id] = lswitch_id + + if NET_NSX_2_NEUTRON_ID_CACHE.get(lswitch_id): + return [NET_NSX_2_NEUTRON_ID_CACHE[lswitch_id]] + return [] def _get_net_tz(self, context, net_id): bindings = nsx_db.get_network_bindings(context.session, net_id) diff --git a/vmware_nsx/tests/unit/nsx_p/test_dhcp_metadata.py b/vmware_nsx/tests/unit/nsx_p/test_dhcp_metadata.py index 2c4eabc511..7e478a2c1c 100644 --- a/vmware_nsx/tests/unit/nsx_p/test_dhcp_metadata.py +++ b/vmware_nsx/tests/unit/nsx_p/test_dhcp_metadata.py @@ -967,11 +967,16 @@ class NsxNativeMetadataTestCase(test_plugin.NsxPPluginTestCaseMixin): self.assertEqual(len(subnets), 2) self.assertEqual(set([s['id'] for s in subnets]), set([s1['subnet']['id'], s2['subnet']['id']])) - lswitch_id = n1['network']['id'] + lswitch_id = 'dummy' + neutron_id = n1['network']['id'] + nsx_tag = {'tag': neutron_id, 'scope': 'os-neutron-net-id'} # Get only the subnets associated with a particular advanced # service provider (i.e. logical switch). - subnets = self._list('subnets', query_params='%s=%s' % - (as_providers.ADV_SERVICE_PROVIDERS, - lswitch_id))['subnets'] - self.assertEqual(len(subnets), 1) - self.assertEqual(subnets[0]['id'], s1['subnet']['id']) + with mock.patch('vmware_nsxlib.v3.core_resources.' + 'NsxLibLogicalSwitch.get', + return_value={'tags': [nsx_tag]}): + subnets = self._list('subnets', query_params='%s=%s' % + (as_providers.ADV_SERVICE_PROVIDERS, + lswitch_id))['subnets'] + self.assertEqual(len(subnets), 1) + self.assertEqual(subnets[0]['id'], s1['subnet']['id'])