Exemple #1
0
    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
            })
Exemple #2
0
 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))
Exemple #4
0
 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})
Exemple #5
0
    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
Exemple #6
0
    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
Exemple #7
0
    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
Exemple #8
0
    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
Exemple #9
0
    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