from neutron.db import l3_agentschedulers_db as l3agent_sch_db
from neutron.db import model_base
from neutron.db import models_v2
+from neutron.extensions import l3agentscheduler
from neutron.i18n import _LI, _LW
from neutron import manager
from neutron.plugins.common import constants as service_constants
return
snat_candidates = self.get_snat_candidates(sync_router,
active_l3_agents)
- if snat_candidates:
+ if not snat_candidates:
+ LOG.warn(_LW('No candidates found for SNAT'))
+ return
+ else:
try:
chosen_agent = self.bind_snat_servicenode(
context, router_id, snat_candidates)
context, router_id, chosen_agent)
return chosen_agent
+ def reschedule_router(self, context, router_id, candidates=None):
+ """Reschedule router to new l3 agents
+
+ Remove the router from l3 agents currently hosting it and
+ schedule it again
+ """
+ router = self.get_router(context, router_id)
+ is_distributed = router.get('distributed', False)
+ if not is_distributed:
+ return super(L3_DVRsch_db_mixin, self).reschedule_router(
+ context, router_id, candidates)
+
+ old_agents = self.list_l3_agents_hosting_router(
+ context, router_id)['agents']
+ with context.session.begin(subtransactions=True):
+ for agent in old_agents:
+ self._unbind_router(context, router_id, agent['id'])
+ self.unbind_snat_servicenode(context, router_id)
+
+ self.schedule_router(context, router_id, candidates=candidates)
+ new_agents = self.list_l3_agents_hosting_router(
+ context, router_id)['agents']
+ if not new_agents:
+ raise l3agentscheduler.RouterReschedulingFailed(
+ router_id=router_id)
+
+ l3_notifier = self.agent_notifiers.get(n_const.AGENT_TYPE_L3)
+ if l3_notifier:
+ old_hosts = [agent['host'] for agent in old_agents]
+ new_hosts = [agent['host'] for agent in new_agents]
+ for host in set(old_hosts) - set(new_hosts):
+ l3_notifier.router_removed_from_agent(
+ context, router_id, host)
+ for host in new_hosts:
+ l3_notifier.router_added_to_agent(
+ context, [router_id], host)
+
def _get_active_l3_agent_routers_sync_data(self, context, host, agent,
router_ids):
if n_utils.is_extension_supported(self, n_const.L3_HA_MODE_EXT_ALIAS):
set([a['configurations']['agent_mode'] for a in
l3agents['agents']]))
+ def test_dvr_router_csnat_rescheduling(self):
+ helpers.register_l3_agent(
+ host=L3_HOSTA, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
+ helpers.register_l3_agent(
+ host=L3_HOSTB, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
+ with self.subnet() as s:
+ net_id = s['subnet']['network_id']
+ self._set_net_external(net_id)
+
+ router = {'name': 'router1',
+ 'external_gateway_info': {'network_id': net_id},
+ 'admin_state_up': True,
+ 'distributed': True}
+ r = self.l3plugin.create_router(self.adminContext,
+ {'router': router})
+ self.l3plugin.schedule_router(
+ self.adminContext, r['id'])
+ l3agents = self._list_l3_agents_hosting_router(r['id'])
+ self.assertEqual(2, len(l3agents['agents']))
+ csnat_agent_host = self.l3plugin.get_snat_bindings(
+ self.adminContext, [r['id']])[0]['l3_agent']['host']
+ self._take_down_agent_and_run_reschedule(csnat_agent_host)
+ l3agents = self._list_l3_agents_hosting_router(r['id'])
+ self.assertEqual(1, len(l3agents['agents']))
+ new_csnat_agent_host = self.l3plugin.get_snat_bindings(
+ self.adminContext, [r['id']])[0]['l3_agent']['host']
+ self.assertNotEqual(csnat_agent_host, new_csnat_agent_host)
+
def test_router_sync_data(self):
with self.subnet() as s1,\
self.subnet(cidr='10.0.2.0/24') as s2,\