]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
DVR:don't reschedule the l3 agent running on compute node
authorOleg Bondarev <obondarev@mirantis.com>
Wed, 25 Nov 2015 12:14:18 +0000 (15:14 +0300)
committerOleg Bondarev <obondarev@mirantis.com>
Tue, 1 Dec 2015 09:48:28 +0000 (12:48 +0300)
For a DVR router, when it updates router gateway_ip, it should not
reschedule the l3 agents running on compute nodes whose mode is dvr,
it just need to reschedule the l3 agents running on network nodes
whose mode is dvr_snat.

Change-Id: Ib8ea6797c88cefb473eff9a8a7b2517a6aa90ca4
Closes-bug: #1496204
Co-Authored-By: Oleg Bondarev <obondarev@mirantis.com>
neutron/db/l3_agentschedulers_db.py
neutron/db/l3_dvrscheduler_db.py
neutron/tests/unit/db/test_agentschedulers_db.py

index e2a01bb829c5a4c5e76459d7a9a167651aa93bb9..9a76b1fd578a5b7c9b57826561b37e897ca763ea 100644 (file)
@@ -279,6 +279,11 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase,
                 RouterL3AgentBinding.l3_agent_id == agent_id)
             query.delete()
 
+    def _unschedule_router(self, context, router_id, agents_ids):
+        with context.session.begin(subtransactions=True):
+            for agent_id in agents_ids:
+                self._unbind_router(context, router_id, agent_id)
+
     def reschedule_router(self, context, router_id, candidates=None):
         """Reschedule router to (a) new l3 agent(s)
 
@@ -288,8 +293,8 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase,
         cur_agents = self.list_l3_agents_hosting_router(
             context, router_id)['agents']
         with context.session.begin(subtransactions=True):
-            for agent in cur_agents:
-                self._unbind_router(context, router_id, agent['id'])
+            cur_agents_ids = [agent['id'] for agent in cur_agents]
+            self._unschedule_router(context, router_id, cur_agents_ids)
 
             self.schedule_router(context, router_id, candidates=candidates)
             new_agents = self.list_l3_agents_hosting_router(
index 0bd446973d63ba37703000fb13e58aca0bf065ca..28081904d6a318f741fa7ae492b7487660b2ac42 100644 (file)
@@ -389,12 +389,14 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
                 context, router_id, chosen_agent)
             return chosen_agent
 
-    def _unbind_router(self, context, router_id, agent_id):
+    def _unschedule_router(self, context, router_id, agents_ids):
         router = self.get_router(context, router_id)
-        super(L3_DVRsch_db_mixin, self)._unbind_router(context, router_id,
-                                                       agent_id)
         if router.get('distributed', False):
-            self.unbind_snat(context, router_id, agent_id)
+            # for DVR router unscheduling means just unscheduling SNAT portion
+            self.unbind_snat_servicenode(context, router_id)
+        else:
+            super(L3_DVRsch_db_mixin, self)._unschedule_router(
+                context, router_id, agents_ids)
 
     def _get_active_l3_agent_routers_sync_data(self, context, host, agent,
                                                router_ids):
index eafb2235ab3753a294106678912766ae4ff22059..dde3b3a20da2da069c541136b0547f77e1f9e40d 100644 (file)
@@ -755,21 +755,20 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
             self.assertFalse(ret_b)
 
     def test_router_is_not_rescheduled_from_dvr_agent(self):
-        router = {'name': 'router1',
-                  'admin_state_up': True,
-                  'distributed': True}
-        subnet_ids = {'id': '1234'}
-        r = self.l3plugin.create_router(
-            self.adminContext, {'router': router})
-        dvr_agent = self._register_dvr_agents()[1]
+        with self.subnet() as s, \
+                mock.patch.object(
+                        self.l3plugin,
+                        'check_ports_exist_on_l3agent') as port_exists:
+            net_id = s['subnet']['network_id']
+            self._set_net_external(net_id)
+            router = {'name': 'router1',
+                      'admin_state_up': True,
+                      'external_gateway_info': {'network_id': net_id},
+                      'distributed': True}
+            r = self.l3plugin.create_router(
+                self.adminContext, {'router': router})
+            dvr_snat_agent, dvr_agent = self._register_dvr_agents()
 
-        with mock.patch.object(
-                self.l3plugin,
-                'check_ports_exist_on_l3agent') as port_exists,\
-            mock.patch.object(
-                self.l3plugin,
-                'get_subnet_ids_on_router') as rtr_subnets:
-            rtr_subnets.return_value = [subnet_ids]
             port_exists.return_value = True
             self.l3plugin.schedule_router(
                 self.adminContext, r['id'])
@@ -777,12 +776,24 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
             self.assertEqual(2, len(agents['agents']))
             self.assertIn(dvr_agent['host'],
                           [a['host'] for a in agents['agents']])
+            # router should not be unscheduled from dvr agent
             self._take_down_agent_and_run_reschedule(dvr_agent['host'])
             agents = self._list_l3_agents_hosting_router(r['id'])
             self.assertEqual(2, len(agents['agents']))
             self.assertIn(dvr_agent['host'],
                           [a['host'] for a in agents['agents']])
 
+            # another dvr_snat agent is needed to test that router is not
+            # unscheduled from dead dvr agent in case rescheduling between
+            # dvr_snat agents happens
+            helpers.register_l3_agent(
+                host='hostC', agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
+            self._take_down_agent_and_run_reschedule(dvr_snat_agent['host'])
+            agents = self._list_l3_agents_hosting_router(r['id'])
+            self.assertEqual(2, len(agents['agents']))
+            self.assertIn(dvr_agent['host'],
+                          [a['host'] for a in agents['agents']])
+
     def test_router_reschedule_succeeded_after_failed_notification(self):
         l3_plugin = (manager.NeutronManager.get_service_plugins()
                      [service_constants.L3_ROUTER_NAT])