DVR:don't reschedule the l3 agent running on compute node

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>
This commit is contained in:
Oleg Bondarev 2015-11-25 15:14:18 +03:00
parent 5b804251ac
commit 13ce7c8555
3 changed files with 38 additions and 20 deletions

View 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(

View 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):

View 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])