From a5ed7ce8ff069463247f907c31e6bfa6e22570d2 Mon Sep 17 00:00:00 2001 From: Shih-Hao Li Date: Thu, 17 Mar 2016 15:33:06 -0700 Subject: [PATCH] NSX|V3: Optimize finding metadata port Search metadata ports in one step instead of finding all router interface ports followed by checking their IP address. This will avoid lots of lookups and iterations in a scale test. Change-Id: I57cf3c236ba82a5c7f307fbed4c3d6c857e87974 --- vmware_nsx/dhcp_meta/rpc.py | 59 +++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/vmware_nsx/dhcp_meta/rpc.py b/vmware_nsx/dhcp_meta/rpc.py index c2277194e9..005d48297a 100644 --- a/vmware_nsx/dhcp_meta/rpc.py +++ b/vmware_nsx/dhcp_meta/rpc.py @@ -15,7 +15,6 @@ # from eventlet import greenthread -import netaddr from neutron_lib import constants as const from neutron_lib import exceptions as ntn_exc from oslo_config import cfg @@ -105,32 +104,36 @@ def handle_router_metadata_access(plugin, context, router_id, interface=None): "the metadata access network")) return ctx_elevated = context.elevated() - device_filter = {'device_id': [router_id], - 'device_owner': const.ROUTER_INTERFACE_OWNERS} - # Retrieve ports calling database plugin - ports = db_base_plugin_v2.NeutronDbPluginV2.get_ports( - plugin, ctx_elevated, filters=device_filter) + on_demand = getattr(plugin_cfg, 'metadata_on_demand', False) try: - if ports: - on_demand = getattr(plugin_cfg, 'metadata_on_demand', False) - if interface: - if (not on_demand or _find_dhcp_disabled_subnet( - plugin, ctx_elevated, ports)) and ( - not _find_metadata_port(plugin, ctx_elevated, ports)): - _create_metadata_access_network( - plugin, ctx_elevated, router_id) - elif (len(ports) == 1 and _find_metadata_port( - plugin, ctx_elevated, ports)) or (on_demand and - not _find_dhcp_disabled_subnet(plugin, ctx_elevated, ports)): + if interface: + # Add interface case + filters = {'device_id': [router_id], + 'device_owner': const.ROUTER_INTERFACE_OWNERS, + 'fixed_ips': {'ip_address': [METADATA_GATEWAY_IP]}} + # Retrieve metadata ports by calling database plugin + ports = db_base_plugin_v2.NeutronDbPluginV2.get_ports( + plugin, ctx_elevated, filters=filters) + if not ports and (not on_demand or + _find_dhcp_disabled_subnet_by_router( + plugin, ctx_elevated, router_id)): + _create_metadata_access_network( + plugin, ctx_elevated, router_id) + else: + # Remove interface case + filters = {'device_id': [router_id], + 'device_owner': const.ROUTER_INTERFACE_OWNERS} + # Retrieve router interface ports by calling database plugin + ports = db_base_plugin_v2.NeutronDbPluginV2.get_ports( + plugin, ctx_elevated, filters=filters) + if len(ports) == 1 or (on_demand and not + _find_dhcp_disabled_subnet_by_port( + plugin, ctx_elevated, ports)): # Delete the internal metadata network if the router port # is the last port left or no more DHCP-disabled subnet # attached to the router. _destroy_metadata_access_network( plugin, ctx_elevated, router_id, ports) - else: - LOG.debug("No router interface found for router '%s'. " - "No metadata access network should be " - "created or destroyed", router_id) # TODO(salvatore-orlando): A better exception handling in the # NSX plugin would allow us to improve error handling here except (ntn_exc.NeutronException, nsx_exc.NsxPluginException, @@ -144,13 +147,11 @@ def handle_router_metadata_access(plugin, context, router_id, interface=None): def _find_metadata_port(plugin, context, ports): for port in ports: for fixed_ip in port['fixed_ips']: - cidr = netaddr.IPNetwork( - plugin.get_subnet(context, fixed_ip['subnet_id'])['cidr']) - if cidr in netaddr.IPNetwork(METADATA_SUBNET_CIDR): + if fixed_ip['ip_address'] == METADATA_GATEWAY_IP: return port -def _find_dhcp_disabled_subnet(plugin, context, ports): +def _find_dhcp_disabled_subnet_by_port(plugin, context, ports): for port in ports: for fixed_ip in port['fixed_ips']: subnet = plugin.get_subnet(context, fixed_ip['subnet_id']) @@ -158,6 +159,14 @@ def _find_dhcp_disabled_subnet(plugin, context, ports): return subnet +def _find_dhcp_disabled_subnet_by_router(plugin, context, router_id): + filters = {'device_id': [router_id], + 'device_owner': const.ROUTER_INTERFACE_OWNERS} + ports = db_base_plugin_v2.NeutronDbPluginV2.get_ports( + plugin, context, filters=filters) + return _find_dhcp_disabled_subnet_by_port(plugin, context, ports) + + def _create_metadata_access_network(plugin, context, router_id): # Add network # Network name is likely to be truncated on NSX