]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fixes race condition and boosts the scheduling performance
authorSwaminathan Vasudevan <swaminathan.vasudevan@hp.com>
Wed, 15 Apr 2015 04:34:33 +0000 (21:34 -0700)
committerSwaminathan Vasudevan <swaminathan.vasudevan@hp.com>
Fri, 17 Apr 2015 16:07:05 +0000 (09:07 -0700)
This patch fixes a race-condition that occurs when the
scheduler tries to check for dvr serviceable ports before
it schedules a router when a subnet is associated with
a router.

Sometimes the dhcp port creation is delayed and so the
router is not scheduled to the l3-agent.

Also it boosts the scheduling performance on dvr-snat
node for scheduling a router.

This patch will provide a work around to fix this race
condition and to boost the scheduling performance
by scheduling a router on a dvr-snat when
dhcp is enabled on the provided subnet, instead of checking
all the available ports on the subnet.

Closes-Bug: #1442494

Change-Id: I089fefdd8535bdc9ed90b3230438ab0bfb6aab4f

neutron/db/l3_agentschedulers_db.py
neutron/tests/unit/scheduler/test_l3_agent_scheduler.py

index 931436bddcbcea121799ed9d0c78347fa763847e..f661dcc62217ae7e62c7741ea95d2c749fd7d391 100644 (file)
@@ -379,6 +379,25 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase,
             return False
 
         core_plugin = manager.NeutronManager.get_plugin()
+        # NOTE(swami):Before checking for existence of dvr
+        # serviceable ports on the host managed by the l3
+        # agent, let's verify if at least one subnet has
+        # dhcp enabled. If so, then the host will have a
+        # dvr serviceable port, which is in fact the DHCP
+        # port.
+        # This optimization is valid assuming that the L3
+        # DVR_SNAT node will be the one hosting the DHCP
+        # Agent.
+        agent_conf = self.get_configuration_dict(l3_agent)
+        agent_mode = agent_conf.get(constants.L3_AGENT_MODE,
+                                    constants.L3_AGENT_MODE_LEGACY)
+
+        for subnet_id in subnet_ids:
+            subnet_dict = core_plugin.get_subnet(context, subnet_id)
+            if (subnet_dict['enable_dhcp'] and (
+                agent_mode == constants.L3_AGENT_MODE_DVR_SNAT)):
+                return True
+
         filter = {'fixed_ips': {'subnet_id': subnet_ids}}
         ports = core_plugin.get_ports(context, filters=filter)
         for port in ports:
index c08991aafe29989ca4a10f9d43d4c29a9683ec70..09e3f708021ed7b7cf9f4b573a3d41f061d86588 100644 (file)
@@ -722,6 +722,29 @@ class L3SchedulerTestBaseMixin(object):
                                                 l3_agent, router['id'])
         self.assertFalse(val)
 
+    def test_check_ports_exist_on_l3agent_with_dhcp_enabled_subnets(self):
+        self._register_l3_dvr_agents()
+        router = self._make_router(self.fmt,
+                                   tenant_id=str(uuid.uuid4()),
+                                   name='r2')
+        router['external_gateway_info'] = None
+        router['id'] = str(uuid.uuid4())
+        router['distributed'] = True
+
+        agent_list = [self.l3_dvr_snat_agent]
+        subnet = {'id': str(uuid.uuid4()),
+                  'enable_dhcp': True}
+
+        self.get_subnet_ids_on_router = mock.Mock(
+            return_value=[subnet['id']])
+
+        self.plugin.get_subnet = mock.Mock(return_value=subnet)
+        self.plugin.get_ports = mock.Mock()
+        val = self.check_ports_exist_on_l3agent(
+            self.adminContext, agent_list[0], router['id'])
+        self.assertTrue(val)
+        self.assertFalse(self.plugin.get_ports.called)
+
     def test_check_ports_exist_on_l3agent_if_no_subnets_then_return(self):
         l3_agent, router = self._prepare_check_ports_exist_tests()
         with mock.patch.object(manager.NeutronManager,
@@ -749,9 +772,12 @@ class L3SchedulerTestBaseMixin(object):
                 'binding:host_id': 'host_1',
                 'device_owner': 'compute:',
                 'id': 1234}
+        subnet = {'id': str(uuid.uuid4()),
+                  'enable_dhcp': False}
         self.plugin.get_ports.return_value = [port]
         self.get_subnet_ids_on_router = mock.Mock(
             return_value=[port['subnet_id']])
+        self.plugin.get_subnet = mock.Mock(return_value=subnet)
         val = self.check_ports_exist_on_l3agent(self.adminContext,
                                                 l3_agent, router['id'])
         self.assertTrue(val)