DVR: optimize check_ports_exist_on_l3_agent()

Currently the function gets all ports on the subnet and iterates
through them to find dvr serviceable ports on a particular host.
This patch makes it a single DB query to see if any port exists
matching criterias.

Partial-Bug: #1513678
Change-Id: Ie17885497aacb8fda4a2c4a05f19d08991038557
Co-Authored-By: Oleg Bondarev <obondarev@mirantis.com>
This commit is contained in:
Oleg Bondarev 2015-12-02 14:52:30 +03:00
parent c2483b73c2
commit 226c999de3
2 changed files with 30 additions and 14 deletions

View File

@ -367,6 +367,18 @@ class exception_logger(object):
return call return call
def get_other_dvr_serviced_device_owners():
"""Return device_owner names for ports that should be serviced by DVR
This doesn't return DEVICE_OWNER_COMPUTE_PREFIX since it is a
prefix, not a complete device_owner name, so should be handled
separately (see is_dvr_serviced() below)
"""
return [n_const.DEVICE_OWNER_LOADBALANCER,
n_const.DEVICE_OWNER_LOADBALANCERV2,
n_const.DEVICE_OWNER_DHCP]
def is_dvr_serviced(device_owner): def is_dvr_serviced(device_owner):
"""Check if the port need to be serviced by DVR """Check if the port need to be serviced by DVR
@ -375,11 +387,8 @@ def is_dvr_serviced(device_owner):
if they are required for DVR or any service directly or if they are required for DVR or any service directly or
indirectly associated with DVR. indirectly associated with DVR.
""" """
dvr_serviced_device_owners = (n_const.DEVICE_OWNER_LOADBALANCER,
n_const.DEVICE_OWNER_LOADBALANCERV2,
n_const.DEVICE_OWNER_DHCP)
return (device_owner.startswith(n_const.DEVICE_OWNER_COMPUTE_PREFIX) or return (device_owner.startswith(n_const.DEVICE_OWNER_COMPUTE_PREFIX) or
device_owner in dvr_serviced_device_owners) device_owner in get_other_dvr_serviced_device_owners())
@debtcollector.removals.remove(message="This will removed in the N cycle.") @debtcollector.removals.remove(message="This will removed in the N cycle.")

View File

@ -33,6 +33,7 @@ from neutron.db import agents_db
from neutron.db import agentschedulers_db from neutron.db import agentschedulers_db
from neutron.db import l3_attrs_db from neutron.db import l3_attrs_db
from neutron.db import model_base from neutron.db import model_base
from neutron.db import models_v2
from neutron.extensions import l3agentscheduler from neutron.extensions import l3agentscheduler
from neutron.extensions import portbindings from neutron.extensions import portbindings
from neutron.extensions import router_availability_zone as router_az from neutron.extensions import router_availability_zone as router_az
@ -455,21 +456,27 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase,
if agentschedulers_db.AgentSchedulerDbMixin.is_eligible_agent( if agentschedulers_db.AgentSchedulerDbMixin.is_eligible_agent(
active, l3_agent)] active, l3_agent)]
def check_ports_exist_on_l3agent( def check_ports_exist_on_l3agent(self, context, l3_agent, subnet_ids):
self, context, l3_agent, subnet_ids):
""" """
This function checks for existence of dvr serviceable This function checks for existence of dvr serviceable
ports on the host, running the input l3agent. ports on the host, running the input l3agent.
""" """
core_plugin = manager.NeutronManager.get_plugin() # db query will return ports for all subnets if subnet_ids is empty,
filter = {'fixed_ips': {'subnet_id': subnet_ids}} # so need to check first
ports = core_plugin.get_ports(context, filters=filter) if not subnet_ids:
for port in ports: return False
if (n_utils.is_dvr_serviced(port['device_owner']) and
l3_agent['host'] == port[portbindings.HOST_ID]):
return True
return False core_plugin = manager.NeutronManager.get_plugin()
filters = {'fixed_ips': {'subnet_id': subnet_ids},
portbindings.HOST_ID: [l3_agent['host']]}
ports_query = core_plugin._get_ports_query(context, filters=filters)
owner_filter = or_(
models_v2.Port.device_owner.startswith(
constants.DEVICE_OWNER_COMPUTE_PREFIX),
models_v2.Port.device_owner.in_(
n_utils.get_other_dvr_serviced_device_owners()))
ports_query = ports_query.filter(owner_filter)
return ports_query.first() is not None
def get_l3_agent_candidates(self, context, sync_router, l3_agents, def get_l3_agent_candidates(self, context, sync_router, l3_agents,
ignore_admin_state=False): ignore_admin_state=False):