def get_l3_agent_candidates(self, context, sync_router, l3_agents,
                                ignore_admin_state=False):
        """Get the valid l3 agents for the router from a list of l3_agents.

        It will not return agents in 'dvr' mode for a dvr router as dvr
        routers are not explicitly scheduled to l3 agents on compute nodes
        """
        candidates = []
        is_router_distributed = sync_router.get('distributed', False)
        for l3_agent in l3_agents:
            if not ignore_admin_state and not l3_agent.admin_state_up:
                # ignore_admin_state True comes from manual scheduling
                # where admin_state_up judgement is already done.
                continue

            agent_conf = self.get_configuration_dict(l3_agent)
            agent_mode = agent_conf.get(n_const.L3_AGENT_MODE,
                                        n_const.L3_AGENT_MODE_LEGACY)
            if (agent_mode == n_const.L3_AGENT_MODE_DVR or
                    (agent_mode == n_const.L3_AGENT_MODE_LEGACY and
                     is_router_distributed)):
                continue

            router_id = agent_conf.get('router_id', None)
            if router_id and router_id != sync_router['id']:
                continue

            handle_internal_only_routers = agent_conf.get(
                'handle_internal_only_routers', True)
            gateway_external_network_id = agent_conf.get(
                'gateway_external_network_id', None)

            ex_net_id = (sync_router['external_gateway_info'] or {}).get(
                'network_id')
            if ((not ex_net_id and not handle_internal_only_routers) or
                (ex_net_id and gateway_external_network_id and
                 ex_net_id != gateway_external_network_id)):
                continue

            candidates.append(l3_agent)
        return candidates
dataset/ETHPy150Open openstack/neutron/neutron/db/l3_agentschedulers_db.py/L3AgentSchedulerDbMixin.get_l3_agent_candidates/original