]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
DVR: optimize check_ports_exist_on_l3_agent()
authorOleg Bondarev <obondarev@mirantis.com>
Wed, 2 Dec 2015 11:52:30 +0000 (14:52 +0300)
committerOleg Bondarev <obondarev@mirantis.com>
Fri, 25 Dec 2015 14:20:05 +0000 (17:20 +0300)
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>
neutron/common/utils.py
neutron/db/l3_agentschedulers_db.py

index 7237fd9d85a689ec67e30b03f0c0c2ab664b7b73..63af635991818d65201e9bba5204f52e46cdb933 100644 (file)
@@ -367,6 +367,18 @@ class exception_logger(object):
         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):
     """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
     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
-            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.")
index 996dcdacaa8838f55e372b58058bd4bac0f6d1dc..d6ab00ead8f15997c83628bbc4929cb694e1ddad 100644 (file)
@@ -33,6 +33,7 @@ from neutron.db import agents_db
 from neutron.db import agentschedulers_db
 from neutron.db import l3_attrs_db
 from neutron.db import model_base
+from neutron.db import models_v2
 from neutron.extensions import l3agentscheduler
 from neutron.extensions import portbindings
 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(
                     active, l3_agent)]
 
-    def check_ports_exist_on_l3agent(
-            self, context, l3_agent, subnet_ids):
+    def check_ports_exist_on_l3agent(self, context, l3_agent, subnet_ids):
         """
         This function checks for existence of dvr serviceable
         ports on the host, running the input l3agent.
         """
+        # db query will return ports for all subnets if subnet_ids is empty,
+        # so need to check first
+        if not subnet_ids:
+            return False
+
         core_plugin = manager.NeutronManager.get_plugin()
-        filter = {'fixed_ips': {'subnet_id': subnet_ids}}
-        ports = core_plugin.get_ports(context, filters=filter)
-        for port in ports:
-            if (n_utils.is_dvr_serviced(port['device_owner']) and
-                l3_agent['host'] == port[portbindings.HOST_ID]):
-                    return True
-
-        return False
+        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,
                                 ignore_admin_state=False):