def bind_router(self, context, router_id, chosen_agent): """Bind the router to the l3 agent which has been chosen.""" try: with context.session.begin(subtransactions=True): binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = chosen_agent binding.router_id = router_id context.session.add(binding) except db_exc.DBDuplicateEntry: LOG.debug( 'Router %(router_id)s has already been scheduled ' 'to L3 agent %(agent_id)s.', { 'agent_id': chosen_agent.id, 'router_id': router_id }) return except db_exc.DBReferenceError: LOG.debug( 'Router %s has already been removed ' 'by concurrent operation', router_id) return LOG.debug( 'Router %(router_id)s is scheduled to L3 agent ' '%(agent_id)s', { 'router_id': router_id, 'agent_id': chosen_agent.id })
def bind_dvr_router_servicenode(self, context, router_id, chosen_snat_agent): """Bind the IR router to service node if not already hosted.""" query = (context.session.query( l3agent_sch_db.RouterL3AgentBinding).filter_by( router_id=router_id)) for bind in query: if bind.l3_agent_id == chosen_snat_agent.id: LOG.debug( 'Distributed Router %(router_id)s already hosted ' 'on snat l3_agent %(snat_id)s', { 'router_id': router_id, 'snat_id': chosen_snat_agent.id }) return with context.session.begin(subtransactions=True): binding = l3agent_sch_db.RouterL3AgentBinding() binding.l3_agent = chosen_snat_agent binding.router_id = router_id context.session.add(binding) LOG.debug( 'Binding the distributed router %(router_id)s to ' 'the snat agent %(snat_id)s', { 'router_id': router_id, 'snat_id': chosen_snat_agent.id })
def _binding_router_to_agent(self, context, router_ids, agent_id): for r_id in router_ids: LOG.debug('_binding_router_to_agent, process:%s-%s' % (r_id, agent_id)) query = context.session.query(l3_agentschedulers_db. RouterL3AgentBinding) query = query.filter(l3_agentschedulers_db.RouterL3AgentBinding. router_id == r_id, l3_agentschedulers_db.RouterL3AgentBinding. l3_agent_id == agent_id) try: query.one() LOG.debug('find old router_agent_binding %s-%s ' % (r_id, agent_id)) except sa_exc.NoResultFound: with context.session.begin(subtransactions=True): binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent_id = agent_id binding.router_id = r_id try: context.session.add(binding) LOG.debug('add router_agent_binding %s-%s' % (r_id, agent_id)) except db_exc.DBError: LOG.debug('add router_agent_binding %s-%s fail' % (r_id, agent_id))
def bind_router(self, context, router_id, chosen_agent): """Bind the router to the l3 agent which has been chosen.""" with context.session.begin(subtransactions=True): binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = chosen_agent binding.router_id = router_id context.session.add(binding) LOG.debug(_('Router %(router_id)s is scheduled to ' 'L3 agent %(agent_id)s'), {'router_id': router_id, 'agent_id': chosen_agent.id})
def bind_router(self, context, router_id, chosen_agent, binding_index=l3_agentschedulers_db.LOWEST_BINDING_INDEX): """Bind the router to the l3 agent which has been chosen.""" # Pre-cache the agent's id so that if an exception is raised we can # safely access its value. Otherwise, sqlalchemy will try to fetch it # from the database during a rollback, which is bad for us. agent_id = chosen_agent.id try: with context.session.begin(subtransactions=True): binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = chosen_agent binding.router_id = router_id binding.binding_index = binding_index context.session.add(binding) except db_exc.DBDuplicateEntry as error: LOG.debug( 'Router %(router_id)s has already been scheduled ' 'to L3 agent %(agent_id)s (tried to bind with ' 'binding_index %(binding_index)d). The conflict was ' 'with columns %(columns)r.', { 'agent_id': agent_id, 'router_id': router_id, 'binding_index': binding_index, 'columns': error.columns }) return except db_exc.DBReferenceError: LOG.debug( 'Router %s has already been removed ' 'by concurrent operation', router_id) return LOG.debug( 'Router %(router_id)s is scheduled to L3 agent ' '%(agent_id)s with binding_index %(binding_index)d', { 'router_id': router_id, 'agent_id': agent_id, 'binding_index': binding_index }) return binding
def schedule(self, plugin, context, router_id): """Schedule the router to an active L3 agent if there is no enable L3 agent hosting it. """ with context.session.begin(subtransactions=True): # allow one router is hosted by just # one enabled l3 agent hosting since active is just a # timing problem. Non-active l3 agent can return to # active any time l3_agents = plugin.get_l3_agents_hosting_routers( context, [router_id], admin_state_up=True) if l3_agents: LOG.debug( _('Router %(router_id)s has already been hosted' ' by L3 agent %(agent_id)s'), { 'router_id': router_id, 'agent_id': l3_agents[0]['id'] }) return sync_router = plugin.get_router(context, router_id) active_l3_agents = plugin.get_l3_agents(context, active=True) if not active_l3_agents: LOG.warn(_('No active L3 agents')) return candidates = plugin.get_l3_agent_candidates( sync_router, active_l3_agents) if not candidates: LOG.warn(_('No L3 agents can host the router %s'), sync_router['id']) return chosen_agent = random.choice(candidates) binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = chosen_agent binding.router_id = sync_router['id'] context.session.add(binding) LOG.debug( _('Router %(router_id)s is scheduled to ' 'L3 agent %(agent_id)s'), { 'router_id': sync_router['id'], 'agent_id': chosen_agent['id'] }) return chosen_agent
def auto_schedule_routers(self, plugin, context, host, router_ids): """Schedule non-hosted routers to L3 Agent running on host. If router_ids is given, each router in router_ids is scheduled if it is not scheduled yet. Otherwise all unscheduled routers are scheduled. Don't schedule the routers which are hosted already by active l3 agents. """ with context.session.begin(subtransactions=True): # query if we have valid l3 agent on the host query = context.session.query(agents_db.Agent) query = query.filter( agents_db.Agent.agent_type == constants.AGENT_TYPE_L3, agents_db.Agent.host == host, agents_db.Agent.admin_state_up == True) try: l3_agent = query.one() except (exc.MultipleResultsFound, exc.NoResultFound): LOG.debug(_('No enabled L3 agent on host %s'), host) return False if agents_db.AgentDbMixin.is_agent_down( l3_agent.heartbeat_timestamp): LOG.warn(_('L3 agent %s is not active'), l3_agent.id) # check if each of the specified routers is hosted if router_ids: unscheduled_router_ids = [] for router_id in router_ids: l3_agents = plugin.get_l3_agents_hosting_routers( context, [router_id], admin_state_up=True) if l3_agents: LOG.debug( _('Router %(router_id)s has already been' ' hosted by L3 agent %(agent_id)s'), { 'router_id': router_id, 'agent_id': l3_agents[0]['id'] }) else: unscheduled_router_ids.append(router_id) if not unscheduled_router_ids: # all (specified) routers are already scheduled return False else: # get all routers that are not hosted #TODO(gongysh) consider the disabled agent's router stmt = ~exists().where(l3_db.Router.id == l3_agentschedulers_db .RouterL3AgentBinding.router_id) unscheduled_router_ids = [ router_id_[0] for router_id_ in context.session.query( l3_db.Router.id).filter(stmt) ] if not unscheduled_router_ids: LOG.debug(_('No non-hosted routers')) return False # check if the configuration of l3 agent is compatible # with the router routers = plugin.get_routers( context, filters={'id': unscheduled_router_ids}) to_removed_ids = [] for router in routers: candidates = plugin.get_l3_agent_candidates(router, [l3_agent]) if not candidates: to_removed_ids.append(router['id']) router_ids = set([r['id'] for r in routers]) - set(to_removed_ids) if not router_ids: LOG.warn( _('No routers compatible with L3 agent configuration' ' on host %s'), host) return False # binding for router_id in router_ids: binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = l3_agent binding.router_id = router_id binding.default = True context.session.add(binding) return True
def schedule(self, plugin, context, router_id): """Schedule the router to the least utilized active L3 agent if there is no enable L3 agent hosting it. """ with context.session.begin(subtransactions=True): # allow one router is hosted by just # one enabled l3 agent hosting since active is just a # timing problem. Non-active l3 agent can return to # active any time # get router object from router_id sync_router = plugin.get_router(context, router_id) l3_agents = plugin.get_l3_agents_hosting_routers( context, [sync_router['id']], admin_state_up=True) if l3_agents: LOG.debug(_('Router %(router_id)s has already been hosted' ' by L3 agent %(agent_id)s'), {'router_id': sync_router['id'], 'agent_id': l3_agents[0]['id']}) return active_l3_agents = plugin.get_l3_agents(context, active=True) if not active_l3_agents: LOG.warn(_('No active L3 agents')) return candidates = plugin.get_l3_agent_candidates(sync_router, active_l3_agents) if not candidates: LOG.warn(_('No L3 agents can host the router %s'), sync_router['id']) return for candidate in candidates: routers = plugin.list_routers_on_l3_agent(context, candidate['id']) LOG.debug(_('Router Scheduler found router hosted count=' '%(router_count)s s for agent_id=%(agent_id)s'), {'router_count': len(routers['routers']), 'agent_id': candidate['id']}) candidate['router_count'] = len(routers['routers']) ordered_agents = sorted(candidates, key=lambda k: k['router_count']) chosen_agent = None for l3_agent in ordered_agents: if agents_db.AgentDbMixin.is_agent_down(l3_agent.heartbeat_timestamp): LOG.debug(_('Router Skipping Preferred agent_id=%s which is down'), l3_agent['id']) continue else: chosen_agent = l3_agent # make sure the agent with the least hosted routers is chosen break LOG.debug(_('Router Scheduler choosing agent=%r'), chosen_agent) binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = chosen_agent binding.router_id = sync_router['id'] context.session.add(binding) LOG.debug(_('Router %(router_id)s is scheduled to ' 'L3 agent %(agent_id)s'), {'router_id': sync_router['id'], 'agent_id': chosen_agent['id']}) return chosen_agent
def auto_schedule_routers(self, plugin, context, host, router_ids): """Schedule non-hosted routers to L3 Agent running on host. If router_ids is given, each router in router_ids is scheduled if it is not scheduled yet. Otherwise all unscheduled routers are scheduled. Don't schedule the routers which are hosted already by active l3 agents. """ with context.session.begin(subtransactions=True): # query if we have valid l3 agent on the host query = context.session.query(agents_db.Agent) query = query.filter(agents_db.Agent.agent_type == constants.AGENT_TYPE_L3, agents_db.Agent.admin_state_up == True) agents = [] for agent in query.all(): router_query = context.session.query(l3_agentschedulers_db.RouterL3AgentBinding) router_count = router_query.filter(l3_agentschedulers_db.RouterL3AgentBinding.l3_agent_id == agent['id']).count() agent['router_count'] = router_count agents.append(agent) LOG.debug(_('Router Scheduler found router hosted count=' '%(router_count)s s for agent_id=%(agent_id)s'), {'router_count': agent['router_count'], 'agent_id': agent['id']}) if not agents: LOG.debug(_('No enabled L3 agents available to schedule to')) return False ordered_agents = sorted(agents, key=lambda k: k['router_count']) l3_agent = None for chosen_agent in ordered_agents: if agents_db.AgentDbMixin.is_agent_down(chosen_agent.heartbeat_timestamp): LOG.debug(_('Router Skipping Preferred agent_id=%s which is down'), chosen_agent['id']) continue else: l3_agent = chosen_agent # make sure the agent with the least hosted routers is chosen break LOG.debug(_('Router Scheduler choosing agent_id=%s'), l3_agent['id']) if agents_db.AgentDbMixin.is_agent_down( l3_agent.heartbeat_timestamp): LOG.warn(_('L3 agent %s is not active'), l3_agent.id) # check if each of the specified routers is hosted if router_ids: if not isinstance(router_ids, (list, tuple)): router_ids = [router_ids] unscheduled_router_ids = [] for router_id in router_ids: l3_agents = plugin.get_l3_agents_hosting_routers( context, [router_id], admin_state_up=True) if l3_agents: LOG.debug(_('Router %(router_id)s has already been' ' hosted by L3 agent %(agent_id)s'), {'router_id': router_id, 'agent_id': l3_agents[0]['id']}) else: unscheduled_router_ids.append(router_id) LOG.info(_("Router is appending router_id=%r to unscheduled_router_ids"), router_id) if not unscheduled_router_ids: # all (specified) routers are already scheduled return False else: # get all routers that are not hosted #TODO(gongysh) consider the disabled agent's router stmt = ~exists().where( l3_db.Router.id == l3_agentschedulers_db.RouterL3AgentBinding.router_id) unscheduled_router_ids = [router_id_[0] for router_id_ in context.session.query( l3_db.Router.id).filter(stmt)] if not unscheduled_router_ids: LOG.debug(_('No non-hosted routers')) return False else: LOG.info(_("Router RouterL3AgentBinding returned unscheduled_router_ids=%r"), unscheduled_router_ids) # check if the configuration of l3 agent is compatible # with the router routers = plugin.get_routers( context, filters={'id': unscheduled_router_ids}) to_removed_ids = [] for router in routers: candidates = plugin.get_l3_agent_candidates(router, [l3_agent]) if not candidates: to_removed_ids.append(router['id']) router_ids = set(unscheduled_router_ids) - set(to_removed_ids) if not router_ids: LOG.warn(_('No routers compatible with L3 agent configuration' ' on host %s'), host) return False # binding for router_id in router_ids: LOG.info(_("Router iterating over router_ids=%r and got router_id=%s" % (router_ids, router_id))) binding = l3_agentschedulers_db.RouterL3AgentBinding() binding.l3_agent = l3_agent binding.router_id = router_id binding.default = True context.session.add(binding) return True