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
This commit is contained in:
Shih-Hao Li 2016-03-17 15:33:06 -07:00
parent b653266abb
commit a5ed7ce8ff

View File

@ -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