Fix regression in routers auto scheduling logic

Routers auto scheduling works when an l3 agent starts and performs
a full sync with neutron server. Neutron server looks for all
unscheduled routers and schedules them to that agent if applicable.
This was broken by commit 0e97feb0f3
which changed full sync logic a bit: now l3 agent requests all ids
of routers scheduled to it first. get_router_ids() didn't call
routers auto scheduling which caused the regression.
This patch adds routers auto scheduling to get_router_ids().

Closes-Bug: #1541348
Change-Id: If6d4e7b3a4839c93296985e169631e5583d9fa12
This commit is contained in:
Oleg Bondarev 2016-02-03 15:01:52 +03:00
parent b80d77ddfe
commit 51adde5eb9
3 changed files with 40 additions and 26 deletions

View File

@ -63,7 +63,16 @@ class L3RpcCallback(object):
return self._l3plugin
def get_router_ids(self, context, host):
"""Returns IDs of routers scheduled to l3 agent on <host>"""
"""Returns IDs of routers scheduled to l3 agent on <host>
This will autoschedule unhosted routers to l3 agent on <host> and then
return all ids of routers scheduled to it.
"""
if utils.is_extension_supported(
self.l3plugin, constants.L3_AGENT_SCHEDULER_EXT_ALIAS):
if cfg.CONF.router_auto_schedule:
self.l3plugin.auto_schedule_routers(context, host,
router_ids=None)
return self.l3plugin.list_router_ids_on_host(context, host)
@db_api.retry_db_errors
@ -80,7 +89,10 @@ class L3RpcCallback(object):
context = neutron_context.get_admin_context()
if utils.is_extension_supported(
self.l3plugin, constants.L3_AGENT_SCHEDULER_EXT_ALIAS):
if cfg.CONF.router_auto_schedule:
# only auto schedule routers that were specifically requested;
# on agent full sync routers will be auto scheduled in
# get_router_ids()
if cfg.CONF.router_auto_schedule and router_ids:
self.l3plugin.auto_schedule_routers(context, host, router_ids)
routers = (
self.l3plugin.list_active_sync_routers_on_active_l3_agent(

View File

@ -668,7 +668,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
l3_rpc_cb = l3_rpc.L3RpcCallback()
self._register_agent_states()
# schedule the router to host A
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
plugin = manager.NeutronManager.get_service_plugins().get(
service_constants.L3_ROUTER_NAT)
@ -694,7 +694,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self._register_agent_states()
with self.router() as r1, self.router() as r2:
# schedule the routers to host A
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
rs_mock = mock.patch.object(
plugin, 'reschedule_router',
@ -713,7 +713,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self._register_agent_states()
# schedule the router to host A
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
with mock.patch('neutron.db.l3_agentschedulers_db.'
'L3AgentSchedulerDbMixin.reschedule_router') as rr:
# take down some unrelated agent and run reschedule check
@ -731,7 +731,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
mock.patch.object(plugin, '_get_agent') as get_agent_mock:
# schedule the routers to the agent
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
self._take_down_agent_and_run_reschedule(L3_HOSTA)
# since _get_agent is mocked it will return Mock object and
# agent.is_active will return true, so no rescheduling will be done
@ -746,11 +746,11 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self._register_agent_states()
# schedule the router to host A
ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
ret_a = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
self._take_down_agent_and_run_reschedule(L3_HOSTA)
# B should now pick up the router
ret_b = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTB)
ret_b = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
self.assertEqual(ret_b, ret_a)
def test_router_no_reschedule_from_dead_admin_down_agent(self):
@ -759,7 +759,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self._register_agent_states()
# schedule the router to host A
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
self._set_agent_admin_state_up(L3_HOSTA, False)
self._take_down_agent_and_run_reschedule(L3_HOSTA)
@ -771,7 +771,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self.assertEqual(binding.l3_agent.host, L3_HOSTA)
# B should not pick up the router
ret_b = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTB)
ret_b = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
self.assertFalse(ret_b)
def test_router_reschedule_succeeded_after_failed_notification(self):
@ -782,7 +782,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self._register_agent_states()
with self.router() as router:
# schedule the router to host A
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
with mock.patch.object(
l3_notifier, 'router_added_to_agent') as notification_mock:
notification_mock.side_effect = [
@ -805,7 +805,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
self._register_agent_states()
with self.router() as router:
# schedule the router to host A
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
with mock.patch.object(
l3_notifier, 'router_added_to_agent') as notification_mock:
notification_mock.side_effect = oslo_messaging.MessagingTimeout
@ -836,12 +836,12 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
with self.router() as router:
l3_rpc_cb = l3_rpc.L3RpcCallback()
self._register_agent_states()
ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
ret_b = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTB)
ret_a = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
ret_b = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
l3_agents = self._list_l3_agents_hosting_router(
router['router']['id'])
self.assertEqual(1, len(ret_a))
self.assertIn(router['router']['id'], [r['id'] for r in ret_a])
self.assertIn(router['router']['id'], ret_a)
self.assertFalse(len(ret_b))
self.assertEqual(1, len(l3_agents['agents']))
self.assertEqual(L3_HOSTA, l3_agents['agents'][0]['host'])
@ -850,19 +850,19 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
with self.router():
l3_rpc_cb = l3_rpc.L3RpcCallback()
self._register_agent_states()
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
def test_router_auto_schedule_with_hosted_2(self):
# one agent hosts one router
l3_rpc_cb = l3_rpc.L3RpcCallback()
with self.router() as router1:
hosta_id = helpers.register_l3_agent(host=L3_HOSTA).id
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
self._disable_agent(hosta_id, admin_state_up=False)
with self.router() as router2:
hostb_id = helpers.register_l3_agent(host=L3_HOSTB).id
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTB)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
l3_agents_1 = self._list_l3_agents_hosting_router(
router1['router']['id'])
l3_agents_2 = self._list_l3_agents_hosting_router(
@ -889,9 +889,9 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
L3_HOSTB)
self._disable_agent(hosta_id)
# first agent will not host router since it is disabled
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
# second agent will host all the routers since first is disabled.
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTB)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
hostb_routers = self._list_routers_hosted_by_l3_agent(hostb_id)
num_hostb_routers = len(hostb_routers['routers'])
hosta_routers = self._list_routers_hosted_by_l3_agent(hosta_id)
@ -904,7 +904,7 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
l3_rpc_cb = l3_rpc.L3RpcCallback()
agent = helpers.register_l3_agent(
host=L3_HOSTA, router_id=router1['router']['id'])
l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
hosta_routers = self._list_routers_hosted_by_l3_agent(agent.id)
num_hosta_routers = len(hosta_routers['routers'])
l3_agents_1 = self._list_l3_agents_hosting_router(
@ -928,6 +928,8 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
routers = (v1, v2, v3)
router_ids = [r['router']['id'] for r in routers]
# auto schedule routers first
l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
# Get all routers
ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
self.assertEqual(3, len(ret_a))

View File

@ -2926,8 +2926,8 @@ class L3NatDBIntAgentSchedulingTestCase(L3BaseForIntTests,
helpers.register_l3_agent(
host='host2', internal_only=False,
ext_net_id=s2['subnet']['network_id'])
l3_rpc_cb.sync_routers(self.adminContext,
host='host1')
l3_rpc_cb.get_router_ids(self.adminContext,
host='host1')
self._assert_router_on_agent(r['router']['id'], 'host1')
self._add_external_gateway_to_router(
@ -2951,8 +2951,8 @@ class L3NatDBIntAgentSchedulingTestCase(L3BaseForIntTests,
helpers.register_l3_agent(
host='host2', internal_only=False,
ext_net_id='', ext_bridge='')
l3_rpc_cb.sync_routers(self.adminContext,
host='host1')
l3_rpc_cb.get_router_ids(self.adminContext,
host='host1')
self._assert_router_on_agent(r['router']['id'], 'host1')
self._add_external_gateway_to_router(