remove unnecessary files under neutron/scheduler
Change-Id: Ic563ed6223df25e0e694e6463af547828cc598b4
This commit is contained in:
parent
a7b1f969fe
commit
aa337ef161
|
@ -1,16 +0,0 @@
|
||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2013 OpenStack Foundation.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
|
@ -1,132 +0,0 @@
|
||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2013 OpenStack Foundation.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
from oslo.config import cfg
|
|
||||||
from sqlalchemy import sql
|
|
||||||
|
|
||||||
from neutron.common import constants
|
|
||||||
from neutron.db import agents_db
|
|
||||||
from neutron.db import agentschedulers_db
|
|
||||||
from neutron.openstack.common.db import exception as db_exc
|
|
||||||
from neutron.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ChanceScheduler(object):
|
|
||||||
"""Allocate a DHCP agent for a network in a random way.
|
|
||||||
More sophisticated scheduler (similar to filter scheduler in nova?)
|
|
||||||
can be introduced later.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _schedule_bind_network(self, context, agents, network_id):
|
|
||||||
for agent in agents:
|
|
||||||
context.session.begin(subtransactions=True)
|
|
||||||
try:
|
|
||||||
binding = agentschedulers_db.NetworkDhcpAgentBinding()
|
|
||||||
binding.dhcp_agent = agent
|
|
||||||
binding.network_id = network_id
|
|
||||||
context.session.add(binding)
|
|
||||||
# try to actually write the changes and catch integrity
|
|
||||||
# DBDuplicateEntry
|
|
||||||
context.session.commit()
|
|
||||||
except db_exc.DBDuplicateEntry:
|
|
||||||
# it's totally ok, someone just did our job!
|
|
||||||
context.session.rollback()
|
|
||||||
LOG.info(_('Agent %s already present'), agent)
|
|
||||||
LOG.debug(_('Network %(network_id)s is scheduled to be '
|
|
||||||
'hosted by DHCP agent %(agent_id)s'),
|
|
||||||
{'network_id': network_id,
|
|
||||||
'agent_id': agent})
|
|
||||||
|
|
||||||
def schedule(self, plugin, context, network):
|
|
||||||
"""Schedule the network to active DHCP agent(s).
|
|
||||||
|
|
||||||
A list of scheduled agents is returned.
|
|
||||||
"""
|
|
||||||
agents_per_network = cfg.CONF.dhcp_agents_per_network
|
|
||||||
|
|
||||||
#TODO(gongysh) don't schedule the networks with only
|
|
||||||
# subnets whose enable_dhcp is false
|
|
||||||
with context.session.begin(subtransactions=True):
|
|
||||||
dhcp_agents = plugin.get_dhcp_agents_hosting_networks(
|
|
||||||
context, [network['id']], active=True)
|
|
||||||
if len(dhcp_agents) >= agents_per_network:
|
|
||||||
LOG.debug(_('Network %s is hosted already'),
|
|
||||||
network['id'])
|
|
||||||
return
|
|
||||||
n_agents = agents_per_network - len(dhcp_agents)
|
|
||||||
enabled_dhcp_agents = plugin.get_agents_db(
|
|
||||||
context, filters={
|
|
||||||
'agent_type': [constants.AGENT_TYPE_DHCP],
|
|
||||||
'admin_state_up': [True]})
|
|
||||||
if not enabled_dhcp_agents:
|
|
||||||
LOG.warn(_('No more DHCP agents'))
|
|
||||||
return
|
|
||||||
active_dhcp_agents = [
|
|
||||||
agent for agent in set(enabled_dhcp_agents)
|
|
||||||
if not agents_db.AgentDbMixin.is_agent_down(
|
|
||||||
agent['heartbeat_timestamp'])
|
|
||||||
and agent not in dhcp_agents
|
|
||||||
]
|
|
||||||
if not active_dhcp_agents:
|
|
||||||
LOG.warn(_('No more DHCP agents'))
|
|
||||||
return
|
|
||||||
n_agents = min(len(active_dhcp_agents), n_agents)
|
|
||||||
chosen_agents = random.sample(active_dhcp_agents, n_agents)
|
|
||||||
self._schedule_bind_network(context, chosen_agents, network['id'])
|
|
||||||
return chosen_agents
|
|
||||||
|
|
||||||
def auto_schedule_networks(self, plugin, context, host):
|
|
||||||
"""Schedule non-hosted networks to the DHCP agent on
|
|
||||||
the specified host.
|
|
||||||
"""
|
|
||||||
agents_per_network = cfg.CONF.dhcp_agents_per_network
|
|
||||||
with context.session.begin(subtransactions=True):
|
|
||||||
query = context.session.query(agents_db.Agent)
|
|
||||||
query = query.filter(agents_db.Agent.agent_type ==
|
|
||||||
constants.AGENT_TYPE_DHCP,
|
|
||||||
agents_db.Agent.host == host,
|
|
||||||
agents_db.Agent.admin_state_up == sql.true())
|
|
||||||
dhcp_agents = query.all()
|
|
||||||
for dhcp_agent in dhcp_agents:
|
|
||||||
if agents_db.AgentDbMixin.is_agent_down(
|
|
||||||
dhcp_agent.heartbeat_timestamp):
|
|
||||||
LOG.warn(_('DHCP agent %s is not active'), dhcp_agent.id)
|
|
||||||
continue
|
|
||||||
fields = ['network_id', 'enable_dhcp']
|
|
||||||
subnets = plugin.get_subnets(context, fields=fields)
|
|
||||||
net_ids = set(s['network_id'] for s in subnets
|
|
||||||
if s['enable_dhcp'])
|
|
||||||
if not net_ids:
|
|
||||||
LOG.debug(_('No non-hosted networks'))
|
|
||||||
return False
|
|
||||||
for net_id in net_ids:
|
|
||||||
agents = plugin.get_dhcp_agents_hosting_networks(
|
|
||||||
context, [net_id], active=True)
|
|
||||||
if len(agents) >= agents_per_network:
|
|
||||||
continue
|
|
||||||
if any(dhcp_agent.id == agent.id for agent in agents):
|
|
||||||
continue
|
|
||||||
binding = agentschedulers_db.NetworkDhcpAgentBinding()
|
|
||||||
binding.dhcp_agent = dhcp_agent
|
|
||||||
binding.network_id = net_id
|
|
||||||
context.session.add(binding)
|
|
||||||
return True
|
|
|
@ -1,194 +0,0 @@
|
||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2013 OpenStack Foundation.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import abc
|
|
||||||
import random
|
|
||||||
|
|
||||||
import six
|
|
||||||
from sqlalchemy.orm import exc
|
|
||||||
from sqlalchemy import sql
|
|
||||||
|
|
||||||
from neutron.common import constants
|
|
||||||
from neutron.db import agents_db
|
|
||||||
from neutron.db import l3_agentschedulers_db
|
|
||||||
from neutron.db import l3_db
|
|
||||||
from neutron.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class L3Scheduler(object):
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def schedule(self, plugin, context, router_id, candidates=None):
|
|
||||||
"""Schedule the router to an active L3 agent.
|
|
||||||
|
|
||||||
Schedule the router only if it is not already scheduled.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
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 == sql.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 = ~sql.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
|
|
||||||
|
|
||||||
for router_id in router_ids:
|
|
||||||
self.bind_router(context, router_id, l3_agent)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_candidates(self, plugin, context, sync_router):
|
|
||||||
"""Return L3 agents where a router could be scheduled."""
|
|
||||||
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, [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
|
|
||||||
|
|
||||||
return candidates
|
|
||||||
|
|
||||||
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})
|
|
||||||
|
|
||||||
|
|
||||||
class ChanceScheduler(L3Scheduler):
|
|
||||||
"""Randomly allocate an L3 agent for a router."""
|
|
||||||
|
|
||||||
def schedule(self, plugin, context, router_id, candidates=None):
|
|
||||||
with context.session.begin(subtransactions=True):
|
|
||||||
sync_router = plugin.get_router(context, router_id)
|
|
||||||
candidates = candidates or self.get_candidates(
|
|
||||||
plugin, context, sync_router)
|
|
||||||
if not candidates:
|
|
||||||
return
|
|
||||||
|
|
||||||
chosen_agent = random.choice(candidates)
|
|
||||||
self.bind_router(context, router_id, chosen_agent)
|
|
||||||
return chosen_agent
|
|
||||||
|
|
||||||
|
|
||||||
class LeastRoutersScheduler(L3Scheduler):
|
|
||||||
"""Allocate to an L3 agent with the least number of routers bound."""
|
|
||||||
|
|
||||||
def schedule(self, plugin, context, router_id, candidates=None):
|
|
||||||
with context.session.begin(subtransactions=True):
|
|
||||||
sync_router = plugin.get_router(context, router_id)
|
|
||||||
candidates = candidates or self.get_candidates(
|
|
||||||
plugin, context, sync_router)
|
|
||||||
if not candidates:
|
|
||||||
return
|
|
||||||
|
|
||||||
candidate_ids = [candidate['id'] for candidate in candidates]
|
|
||||||
chosen_agent = plugin.get_l3_agent_with_min_routers(
|
|
||||||
context, candidate_ids)
|
|
||||||
|
|
||||||
self.bind_router(context, router_id, chosen_agent)
|
|
||||||
|
|
||||||
return chosen_agent
|
|
Loading…
Reference in New Issue