diff --git a/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py b/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py index 6c7a531f4..1086a9e58 100644 --- a/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py +++ b/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py @@ -61,7 +61,7 @@ class DhcpAgentNotifyAPI(proxy.RpcProxy): """Notify all the agents that are hosting the network.""" plugin = manager.NeutronManager.get_plugin() if (method != 'network_delete_end' and utils.is_extension_supported( - plugin, constants.AGENT_SCHEDULER_EXT_ALIAS)): + plugin, constants.DHCP_AGENT_SCHEDULER_EXT_ALIAS)): if method == 'port_create_end': # we don't schedule when we create network # because we want to give admin a chance to diff --git a/neutron/api/rpc/agentnotifiers/l3_rpc_agent_api.py b/neutron/api/rpc/agentnotifiers/l3_rpc_agent_api.py index 557cffeea..28fea4c24 100644 --- a/neutron/api/rpc/agentnotifiers/l3_rpc_agent_api.py +++ b/neutron/api/rpc/agentnotifiers/l3_rpc_agent_api.py @@ -67,7 +67,7 @@ class L3AgentNotifyAPI(proxy.RpcProxy): """Notify all the agents that are hosting the routers.""" plugin = manager.NeutronManager.get_plugin() if utils.is_extension_supported( - plugin, constants.AGENT_SCHEDULER_EXT_ALIAS): + plugin, constants.L3_AGENT_SCHEDULER_EXT_ALIAS): adminContext = (context.is_admin and context or context.elevated()) plugin.schedule_routers(adminContext, routers) diff --git a/neutron/common/constants.py b/neutron/common/constants.py index 06b0c53d2..a6a5e99e4 100644 --- a/neutron/common/constants.py +++ b/neutron/common/constants.py @@ -71,4 +71,5 @@ PAGINATION_INFINITE = 'infinite' SORT_DIRECTION_ASC = 'asc' SORT_DIRECTION_DESC = 'desc' -AGENT_SCHEDULER_EXT_ALIAS = 'agent_scheduler' +L3_AGENT_SCHEDULER_EXT_ALIAS = 'l3_agent_scheduler' +DHCP_AGENT_SCHEDULER_EXT_ALIAS = 'dhcp_agent_scheduler' diff --git a/neutron/db/agentschedulers_db.py b/neutron/db/agentschedulers_db.py index f20e4c956..964b1d20a 100644 --- a/neutron/db/agentschedulers_db.py +++ b/neutron/db/agentschedulers_db.py @@ -24,7 +24,8 @@ from neutron.common import constants from neutron.db import agents_db from neutron.db import model_base from neutron.db import models_v2 -from neutron.extensions import agentscheduler +from neutron.extensions import dhcpagentscheduler +from neutron.extensions import l3agentscheduler from neutron.openstack.common import log as logging @@ -55,14 +56,11 @@ class RouterL3AgentBinding(model_base.BASEV2, models_v2.HasId): ondelete='CASCADE')) -class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, - agents_db.AgentDbMixin): - """Mixin class to add agent scheduler extension to db_plugin_base_v2.""" +class AgentSchedulerDbMixin(agents_db.AgentDbMixin): + """Common class for agent scheduler mixins.""" dhcp_agent_notifier = None l3_agent_notifier = None - network_scheduler = None - router_scheduler = None @staticmethod def is_eligible_agent(active, agent): @@ -77,101 +75,31 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, return not agents_db.AgentDbMixin.is_agent_down( agent['heartbeat_timestamp']) - def get_dhcp_agents_hosting_networks( - self, context, network_ids, active=None): - if not network_ids: - return [] - query = context.session.query(NetworkDhcpAgentBinding) - query = query.options(joinedload('dhcp_agent')) - if len(network_ids) == 1: - query = query.filter( - NetworkDhcpAgentBinding.network_id == network_ids[0]) - elif network_ids: - query = query.filter( - NetworkDhcpAgentBinding.network_id in network_ids) - if active is not None: - query = (query.filter(agents_db.Agent.admin_state_up == active)) + def update_agent(self, context, id, agent): + original_agent = self.get_agent(context, id) + result = super(AgentSchedulerDbMixin, self).update_agent( + context, id, agent) + agent_data = agent['agent'] + if ('admin_state_up' in agent_data and + original_agent['admin_state_up'] != agent_data['admin_state_up']): + if (original_agent['agent_type'] == constants.AGENT_TYPE_DHCP and + self.dhcp_agent_notifier): + self.dhcp_agent_notifier.agent_updated( + context, agent_data['admin_state_up'], + original_agent['host']) + elif (original_agent['agent_type'] == constants.AGENT_TYPE_L3 and + self.l3_agent_notifier): + self.l3_agent_notifier.agent_updated( + context, agent_data['admin_state_up'], + original_agent['host']) + return result - return [binding.dhcp_agent - for binding in query - if AgentSchedulerDbMixin.is_eligible_agent(active, - binding.dhcp_agent)] - def add_network_to_dhcp_agent(self, context, id, network_id): - self._get_network(context, network_id) - with context.session.begin(subtransactions=True): - agent_db = self._get_agent(context, id) - if (agent_db['agent_type'] != constants.AGENT_TYPE_DHCP or - not agent_db['admin_state_up']): - raise agentscheduler.InvalidDHCPAgent(id=id) - dhcp_agents = self.get_dhcp_agents_hosting_networks( - context, [network_id]) - for dhcp_agent in dhcp_agents: - if id == dhcp_agent.id: - raise agentscheduler.NetworkHostedByDHCPAgent( - network_id=network_id, agent_id=id) - binding = NetworkDhcpAgentBinding() - binding.dhcp_agent_id = id - binding.network_id = network_id - context.session.add(binding) - if self.dhcp_agent_notifier: - self.dhcp_agent_notifier.network_added_to_agent( - context, network_id, agent_db.host) +class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase, + AgentSchedulerDbMixin): + """Mixin class to add l3 agent scheduler extension to db_plugin_base_v2.""" - def remove_network_from_dhcp_agent(self, context, id, network_id): - agent = self._get_agent(context, id) - with context.session.begin(subtransactions=True): - try: - query = context.session.query(NetworkDhcpAgentBinding) - binding = query.filter( - NetworkDhcpAgentBinding.network_id == network_id, - NetworkDhcpAgentBinding.dhcp_agent_id == id).one() - except exc.NoResultFound: - raise agentscheduler.NetworkNotHostedByDhcpAgent( - network_id=network_id, agent_id=id) - context.session.delete(binding) - if self.dhcp_agent_notifier: - self.dhcp_agent_notifier.network_removed_from_agent( - context, network_id, agent.host) - - def list_networks_on_dhcp_agent(self, context, id): - query = context.session.query(NetworkDhcpAgentBinding.network_id) - query = query.filter(NetworkDhcpAgentBinding.dhcp_agent_id == id) - - net_ids = [item[0] for item in query] - if net_ids: - return {'networks': - self.get_networks(context, filters={'id': net_ids})} - else: - return {'networks': []} - - def list_active_networks_on_active_dhcp_agent(self, context, host): - agent = self._get_agent_by_type_and_host( - context, constants.AGENT_TYPE_DHCP, host) - if not agent.admin_state_up: - return [] - query = context.session.query(NetworkDhcpAgentBinding.network_id) - query = query.filter(NetworkDhcpAgentBinding.dhcp_agent_id == agent.id) - - net_ids = [item[0] for item in query] - if net_ids: - return self.get_networks( - context, - filters={'id': net_ids, 'admin_state_up': [True]} - ) - else: - return [] - - def list_dhcp_agents_hosting_network(self, context, network_id): - dhcp_agents = self.get_dhcp_agents_hosting_networks( - context, [network_id]) - agent_ids = [dhcp_agent.id for dhcp_agent in dhcp_agents] - if agent_ids: - return { - 'agents': - self.get_agents(context, filters={'id': agent_ids})} - else: - return {'agents': []} + router_scheduler = None def add_router_to_l3_agent(self, context, id, router_id): """Add a l3 agent to host a router.""" @@ -181,14 +109,14 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, if (agent_db['agent_type'] != constants.AGENT_TYPE_L3 or not agent_db['admin_state_up'] or not self.get_l3_agent_candidates(router, [agent_db])): - raise agentscheduler.InvalidL3Agent(id=id) + raise l3agentscheduler.InvalidL3Agent(id=id) query = context.session.query(RouterL3AgentBinding) try: binding = query.filter( RouterL3AgentBinding.l3_agent_id == agent_db.id, RouterL3AgentBinding.router_id == router_id).one() if binding: - raise agentscheduler.RouterHostedByL3Agent( + raise l3agentscheduler.RouterHostedByL3Agent( router_id=router_id, agent_id=id) except exc.NoResultFound: pass @@ -197,7 +125,7 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, agent_db.host, router_id) if not result: - raise agentscheduler.RouterSchedulingFailed( + raise l3agentscheduler.RouterSchedulingFailed( router_id=router_id, agent_id=id) if self.l3_agent_notifier: @@ -220,7 +148,7 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, try: binding = query.one() except exc.NoResultFound: - raise agentscheduler.RouterNotHostedByL3Agent( + raise l3agentscheduler.RouterNotHostedByL3Agent( router_id=router_id, agent_id=id) context.session.delete(binding) if self.l3_agent_notifier: @@ -305,18 +233,6 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, else: return {'agents': []} - def schedule_network(self, context, created_network): - if self.network_scheduler: - chosen_agent = self.network_scheduler.schedule( - self, context, created_network) - if not chosen_agent: - LOG.warn(_('Fail scheduling network %s'), created_network) - return chosen_agent - - def auto_schedule_networks(self, context, host): - if self.network_scheduler: - self.network_scheduler.auto_schedule_networks(self, context, host) - def get_l3_agents(self, context, active=None, filters=None): query = context.session.query(agents_db.Agent) query = query.filter( @@ -372,21 +288,118 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase, for router in routers: self.schedule_router(context, router) - def update_agent(self, context, id, agent): - original_agent = self.get_agent(context, id) - result = super(AgentSchedulerDbMixin, self).update_agent( - context, id, agent) - agent_data = agent['agent'] - if ('admin_state_up' in agent_data and - original_agent['admin_state_up'] != agent_data['admin_state_up']): - if (original_agent['agent_type'] == constants.AGENT_TYPE_DHCP and - self.dhcp_agent_notifier): - self.dhcp_agent_notifier.agent_updated( - context, agent_data['admin_state_up'], - original_agent['host']) - elif (original_agent['agent_type'] == constants.AGENT_TYPE_L3 and - self.l3_agent_notifier): - self.l3_agent_notifier.agent_updated( - context, agent_data['admin_state_up'], - original_agent['host']) - return result + +class DhcpAgentSchedulerDbMixin(dhcpagentscheduler + .DhcpAgentSchedulerPluginBase, + AgentSchedulerDbMixin): + """Mixin class to add DHCP agent scheduler extension to db_plugin_base_v2. + """ + + network_scheduler = None + + def get_dhcp_agents_hosting_networks( + self, context, network_ids, active=None): + if not network_ids: + return [] + query = context.session.query(NetworkDhcpAgentBinding) + query = query.options(joinedload('dhcp_agent')) + if len(network_ids) == 1: + query = query.filter( + NetworkDhcpAgentBinding.network_id == network_ids[0]) + elif network_ids: + query = query.filter( + NetworkDhcpAgentBinding.network_id in network_ids) + if active is not None: + query = (query.filter(agents_db.Agent.admin_state_up == active)) + + return [binding.dhcp_agent + for binding in query + if AgentSchedulerDbMixin.is_eligible_agent(active, + binding.dhcp_agent)] + + def add_network_to_dhcp_agent(self, context, id, network_id): + self._get_network(context, network_id) + with context.session.begin(subtransactions=True): + agent_db = self._get_agent(context, id) + if (agent_db['agent_type'] != constants.AGENT_TYPE_DHCP or + not agent_db['admin_state_up']): + raise dhcpagentscheduler.InvalidDHCPAgent(id=id) + dhcp_agents = self.get_dhcp_agents_hosting_networks( + context, [network_id]) + for dhcp_agent in dhcp_agents: + if id == dhcp_agent.id: + raise dhcpagentscheduler.NetworkHostedByDHCPAgent( + network_id=network_id, agent_id=id) + binding = NetworkDhcpAgentBinding() + binding.dhcp_agent_id = id + binding.network_id = network_id + context.session.add(binding) + if self.dhcp_agent_notifier: + self.dhcp_agent_notifier.network_added_to_agent( + context, network_id, agent_db.host) + + def remove_network_from_dhcp_agent(self, context, id, network_id): + agent = self._get_agent(context, id) + with context.session.begin(subtransactions=True): + try: + query = context.session.query(NetworkDhcpAgentBinding) + binding = query.filter( + NetworkDhcpAgentBinding.network_id == network_id, + NetworkDhcpAgentBinding.dhcp_agent_id == id).one() + except exc.NoResultFound: + raise dhcpagentscheduler.NetworkNotHostedByDhcpAgent( + network_id=network_id, agent_id=id) + context.session.delete(binding) + if self.dhcp_agent_notifier: + self.dhcp_agent_notifier.network_removed_from_agent( + context, network_id, agent.host) + + def list_networks_on_dhcp_agent(self, context, id): + query = context.session.query(NetworkDhcpAgentBinding.network_id) + query = query.filter(NetworkDhcpAgentBinding.dhcp_agent_id == id) + + net_ids = [item[0] for item in query] + if net_ids: + return {'networks': + self.get_networks(context, filters={'id': net_ids})} + else: + return {'networks': []} + + def list_active_networks_on_active_dhcp_agent(self, context, host): + agent = self._get_agent_by_type_and_host( + context, constants.AGENT_TYPE_DHCP, host) + if not agent.admin_state_up: + return [] + query = context.session.query(NetworkDhcpAgentBinding.network_id) + query = query.filter(NetworkDhcpAgentBinding.dhcp_agent_id == agent.id) + + net_ids = [item[0] for item in query] + if net_ids: + return self.get_networks( + context, + filters={'id': net_ids, 'admin_state_up': [True]} + ) + else: + return [] + + def list_dhcp_agents_hosting_network(self, context, network_id): + dhcp_agents = self.get_dhcp_agents_hosting_networks( + context, [network_id]) + agent_ids = [dhcp_agent.id for dhcp_agent in dhcp_agents] + if agent_ids: + return { + 'agents': self.get_agents(context, filters={'id': agent_ids})} + else: + return {'agents': []} + + def schedule_network(self, context, created_network): + if self.network_scheduler: + chosen_agent = self.network_scheduler.schedule( + self, context, created_network) + if not chosen_agent: + LOG.warn(_('Fail scheduling network %s'), created_network) + return chosen_agent + + def auto_schedule_networks(self, context, host): + if self.network_scheduler: + self.network_scheduler.auto_schedule_networks(self, context, host) diff --git a/neutron/db/dhcp_rpc_base.py b/neutron/db/dhcp_rpc_base.py index 353f09f31..60858328f 100644 --- a/neutron/db/dhcp_rpc_base.py +++ b/neutron/db/dhcp_rpc_base.py @@ -35,7 +35,7 @@ class DhcpRpcCallbackMixin(object): LOG.debug(_('Network list requested from %s'), host) plugin = manager.NeutronManager.get_plugin() if utils.is_extension_supported( - plugin, constants.AGENT_SCHEDULER_EXT_ALIAS): + plugin, constants.DHCP_AGENT_SCHEDULER_EXT_ALIAS): if cfg.CONF.network_auto_schedule: plugin.auto_schedule_networks(context, host) nets = plugin.list_active_networks_on_active_dhcp_agent( diff --git a/neutron/db/l3_rpc_base.py b/neutron/db/l3_rpc_base.py index 193681990..4b1387187 100644 --- a/neutron/db/l3_rpc_base.py +++ b/neutron/db/l3_rpc_base.py @@ -42,7 +42,7 @@ class L3RpcCallbackMixin(object): context = neutron_context.get_admin_context() plugin = manager.NeutronManager.get_plugin() if utils.is_extension_supported( - plugin, constants.AGENT_SCHEDULER_EXT_ALIAS): + plugin, constants.L3_AGENT_SCHEDULER_EXT_ALIAS): if cfg.CONF.router_auto_schedule: plugin.auto_schedule_routers(context, host, router_id) routers = plugin.list_active_sync_routers_on_active_l3_agent( diff --git a/neutron/extensions/dhcpagentscheduler.py b/neutron/extensions/dhcpagentscheduler.py new file mode 100644 index 000000000..994ad8eb1 --- /dev/null +++ b/neutron/extensions/dhcpagentscheduler.py @@ -0,0 +1,154 @@ +# 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. + +from abc import abstractmethod + +from neutron.api import extensions +from neutron.api.v2 import base +from neutron.api.v2 import resource +from neutron.common import constants +from neutron.common import exceptions +from neutron.extensions import agent +from neutron import manager +from neutron import policy +from neutron import wsgi + +DHCP_NET = 'dhcp-network' +DHCP_NETS = DHCP_NET + 's' +DHCP_AGENT = 'dhcp-agent' +DHCP_AGENTS = DHCP_AGENT + 's' + + +class NetworkSchedulerController(wsgi.Controller): + def index(self, request, **kwargs): + plugin = manager.NeutronManager.get_plugin() + policy.enforce(request.context, + "get_%s" % DHCP_NETS, + {}) + return plugin.list_networks_on_dhcp_agent( + request.context, kwargs['agent_id']) + + def create(self, request, body, **kwargs): + plugin = manager.NeutronManager.get_plugin() + policy.enforce(request.context, + "create_%s" % DHCP_NET, + {}) + return plugin.add_network_to_dhcp_agent( + request.context, kwargs['agent_id'], body['network_id']) + + def delete(self, request, id, **kwargs): + plugin = manager.NeutronManager.get_plugin() + policy.enforce(request.context, + "delete_%s" % DHCP_NET, + {}) + return plugin.remove_network_from_dhcp_agent( + request.context, kwargs['agent_id'], id) + + +class DhcpAgentsHostingNetworkController(wsgi.Controller): + def index(self, request, **kwargs): + plugin = manager.NeutronManager.get_plugin() + policy.enforce(request.context, + "get_%s" % DHCP_AGENTS, + {}) + return plugin.list_dhcp_agents_hosting_network( + request.context, kwargs['network_id']) + + +class Dhcpagentscheduler(extensions.ExtensionDescriptor): + """Extension class supporting dhcp agent scheduler. + """ + + @classmethod + def get_name(cls): + return "DHCP Agent Scheduler" + + @classmethod + def get_alias(cls): + return constants.DHCP_AGENT_SCHEDULER_EXT_ALIAS + + @classmethod + def get_description(cls): + return "Schedule networks among dhcp agents" + + @classmethod + def get_namespace(cls): + return "http://docs.openstack.org/ext/dhcp_agent_scheduler/api/v1.0" + + @classmethod + def get_updated(cls): + return "2013-02-07T10:00:00-00:00" + + @classmethod + def get_resources(cls): + """Returns Ext Resources.""" + exts = [] + parent = dict(member_name="agent", + collection_name="agents") + controller = resource.Resource(NetworkSchedulerController(), + base.FAULT_MAP) + exts.append(extensions.ResourceExtension( + DHCP_NETS, controller, parent)) + + parent = dict(member_name="network", + collection_name="networks") + + controller = resource.Resource(DhcpAgentsHostingNetworkController(), + base.FAULT_MAP) + exts.append(extensions.ResourceExtension( + DHCP_AGENTS, controller, parent)) + return exts + + def get_extended_resources(self, version): + return {} + + +class InvalidDHCPAgent(agent.AgentNotFound): + message = _("Agent %(id)s is not a valid DHCP Agent or has been disabled") + + +class NetworkHostedByDHCPAgent(exceptions.Conflict): + message = _("The network %(network_id)s has been already hosted" + " by the DHCP Agent %(agent_id)s.") + + +class NetworkNotHostedByDhcpAgent(exceptions.Conflict): + message = _("The network %(network_id)s is not hosted" + " by the DHCP agent %(agent_id)s.") + + +class DhcpAgentSchedulerPluginBase(object): + """REST API to operate the DHCP agent scheduler. + + All of method must be in an admin context. + """ + + @abstractmethod + def add_network_to_dhcp_agent(self, context, id, network_id): + pass + + @abstractmethod + def remove_network_from_dhcp_agent(self, context, id, network_id): + pass + + @abstractmethod + def list_networks_on_dhcp_agent(self, context, id): + pass + + @abstractmethod + def list_dhcp_agents_hosting_network(self, context, network_id): + pass diff --git a/neutron/extensions/agentscheduler.py b/neutron/extensions/l3agentscheduler.py similarity index 57% rename from neutron/extensions/agentscheduler.py rename to neutron/extensions/l3agentscheduler.py index f30156cc8..d851cb0e2 100644 --- a/neutron/extensions/agentscheduler.py +++ b/neutron/extensions/l3agentscheduler.py @@ -27,42 +27,12 @@ from neutron import manager from neutron import policy from neutron import wsgi -DHCP_NET = 'dhcp-network' -DHCP_NETS = DHCP_NET + 's' -DHCP_AGENT = 'dhcp-agent' -DHCP_AGENTS = DHCP_AGENT + 's' L3_ROUTER = 'l3-router' L3_ROUTERS = L3_ROUTER + 's' L3_AGENT = 'l3-agent' L3_AGENTS = L3_AGENT + 's' -class NetworkSchedulerController(wsgi.Controller): - def index(self, request, **kwargs): - plugin = manager.NeutronManager.get_plugin() - policy.enforce(request.context, - "get_%s" % DHCP_NETS, - {}) - return plugin.list_networks_on_dhcp_agent( - request.context, kwargs['agent_id']) - - def create(self, request, body, **kwargs): - plugin = manager.NeutronManager.get_plugin() - policy.enforce(request.context, - "create_%s" % DHCP_NET, - {}) - return plugin.add_network_to_dhcp_agent( - request.context, kwargs['agent_id'], body['network_id']) - - def delete(self, request, id, **kwargs): - plugin = manager.NeutronManager.get_plugin() - policy.enforce(request.context, - "delete_%s" % DHCP_NET, - {}) - return plugin.remove_network_from_dhcp_agent( - request.context, kwargs['agent_id'], id) - - class RouterSchedulerController(wsgi.Controller): def index(self, request, **kwargs): plugin = manager.NeutronManager.get_plugin() @@ -91,16 +61,6 @@ class RouterSchedulerController(wsgi.Controller): request.context, kwargs['agent_id'], id) -class DhcpAgentsHostingNetworkController(wsgi.Controller): - def index(self, request, **kwargs): - plugin = manager.NeutronManager.get_plugin() - policy.enforce(request.context, - "get_%s" % DHCP_AGENTS, - {}) - return plugin.list_dhcp_agents_hosting_network( - request.context, kwargs['network_id']) - - class L3AgentsHostingRouterController(wsgi.Controller): def index(self, request, **kwargs): plugin = manager.NeutronManager.get_plugin() @@ -111,29 +71,29 @@ class L3AgentsHostingRouterController(wsgi.Controller): request.context, kwargs['router_id']) -class Agentscheduler(extensions.ExtensionDescriptor): - """Extension class supporting agent scheduler. +class L3agentscheduler(extensions.ExtensionDescriptor): + """Extension class supporting l3 agent scheduler. """ @classmethod def get_name(cls): - return "Agent Schedulers" + return "L3 Agent Scheduler" @classmethod def get_alias(cls): - return constants.AGENT_SCHEDULER_EXT_ALIAS + return constants.L3_AGENT_SCHEDULER_EXT_ALIAS @classmethod def get_description(cls): - return "Schedule resources among agents" + return "Schedule routers among l3 agents" @classmethod def get_namespace(cls): - return "http://docs.openstack.org/ext/agent_scheduler/api/v1.0" + return "http://docs.openstack.org/ext/l3_agent_scheduler/api/v1.0" @classmethod def get_updated(cls): - return "2013-02-03T10:00:00-00:00" + return "2013-02-07T10:00:00-00:00" @classmethod def get_resources(cls): @@ -141,24 +101,12 @@ class Agentscheduler(extensions.ExtensionDescriptor): exts = [] parent = dict(member_name="agent", collection_name="agents") - controller = resource.Resource(NetworkSchedulerController(), - base.FAULT_MAP) - exts.append(extensions.ResourceExtension( - DHCP_NETS, controller, parent)) controller = resource.Resource(RouterSchedulerController(), base.FAULT_MAP) exts.append(extensions.ResourceExtension( L3_ROUTERS, controller, parent)) - parent = dict(member_name="network", - collection_name="networks") - - controller = resource.Resource(DhcpAgentsHostingNetworkController(), - base.FAULT_MAP) - exts.append(extensions.ResourceExtension( - DHCP_AGENTS, controller, parent)) - parent = dict(member_name="router", collection_name="routers") @@ -172,20 +120,6 @@ class Agentscheduler(extensions.ExtensionDescriptor): return {} -class InvalidDHCPAgent(agent.AgentNotFound): - message = _("Agent %(id)s is not a valid DHCP Agent or has been disabled") - - -class NetworkHostedByDHCPAgent(exceptions.Conflict): - message = _("The network %(network_id)s has been already hosted" - " by the DHCP Agent %(agent_id)s.") - - -class NetworkNotHostedByDhcpAgent(exceptions.Conflict): - message = _("The network %(network_id)s is not hosted" - " by the DHCP agent %(agent_id)s.") - - class InvalidL3Agent(agent.AgentNotFound): message = _("Agent %(id)s is not a L3 Agent or has been disabled") @@ -205,28 +139,12 @@ class RouterNotHostedByL3Agent(exceptions.Conflict): " by L3 agent %(agent_id)s.") -class AgentSchedulerPluginBase(object): - """REST API to operate the agent scheduler. +class L3AgentSchedulerPluginBase(object): + """REST API to operate the l3 agent scheduler. All of method must be in an admin context. """ - @abstractmethod - def add_network_to_dhcp_agent(self, context, id, network_id): - pass - - @abstractmethod - def remove_network_from_dhcp_agent(self, context, id, network_id): - pass - - @abstractmethod - def list_networks_on_dhcp_agent(self, context, id): - pass - - @abstractmethod - def list_dhcp_agents_hosting_network(self, context, network_id): - pass - @abstractmethod def add_router_to_l3_agent(self, context, id, router_id): pass diff --git a/neutron/plugins/brocade/NeutronPlugin.py b/neutron/plugins/brocade/NeutronPlugin.py index 04ed7fb29..137fb979e 100644 --- a/neutron/plugins/brocade/NeutronPlugin.py +++ b/neutron/plugins/brocade/NeutronPlugin.py @@ -197,7 +197,8 @@ class AgentNotifierApi(proxy.RpcProxy, class BrocadePluginV2(db_base_plugin_v2.NeutronDbPluginV2, extraroute_db.ExtraRoute_db_mixin, sg_db_rpc.SecurityGroupServerRpcMixin, - agentschedulers_db.AgentSchedulerDbMixin): + agentschedulers_db.L3AgentSchedulerDbMixin, + agentschedulers_db.DhcpAgentSchedulerDbMixin): """BrocadePluginV2 is a Neutron plugin. Provides L2 Virtual Network functionality using VDX. Upper @@ -213,7 +214,8 @@ class BrocadePluginV2(db_base_plugin_v2.NeutronDbPluginV2, self.supported_extension_aliases = ["binding", "security-group", "router", "extraroute", - "agent", "agent_scheduler"] + "agent", "l3_agent_scheduler", + "dhcp_agent_scheduler"] self.physical_interface = (cfg.CONF.PHYSICAL_INTERFACE. physical_interface) diff --git a/neutron/plugins/linuxbridge/lb_neutron_plugin.py b/neutron/plugins/linuxbridge/lb_neutron_plugin.py index 4d7c5cd8e..db9e8c88e 100644 --- a/neutron/plugins/linuxbridge/lb_neutron_plugin.py +++ b/neutron/plugins/linuxbridge/lb_neutron_plugin.py @@ -188,7 +188,8 @@ class LinuxBridgePluginV2(db_base_plugin_v2.NeutronDbPluginV2, extraroute_db.ExtraRoute_db_mixin, l3_gwmode_db.L3_NAT_db_mixin, sg_db_rpc.SecurityGroupServerRpcMixin, - agentschedulers_db.AgentSchedulerDbMixin, + agentschedulers_db.L3AgentSchedulerDbMixin, + agentschedulers_db.DhcpAgentSchedulerDbMixin, portbindings_db.PortBindingMixin): """Implement the Neutron abstractions using Linux bridging. @@ -215,7 +216,9 @@ class LinuxBridgePluginV2(db_base_plugin_v2.NeutronDbPluginV2, _supported_extension_aliases = ["provider", "router", "ext-gw-mode", "binding", "quotas", "security-group", - "agent", "extraroute", "agent_scheduler"] + "agent", "extraroute", + "l3_agent_scheduler", + "dhcp_agent_scheduler"] @property def supported_extension_aliases(self): diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index c30dbff63..942b09523 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -49,7 +49,8 @@ TYPE_MULTI_SEGMENT = 'multi-segment' class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, extraroute_db.ExtraRoute_db_mixin, sg_db_rpc.SecurityGroupServerRpcMixin, - agentschedulers_db.AgentSchedulerDbMixin, + agentschedulers_db.L3AgentSchedulerDbMixin, + agentschedulers_db.DhcpAgentSchedulerDbMixin, portbindings_db.PortBindingMixin): """Implement the Neutron L2 abstractions using modules. @@ -70,7 +71,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, # List of supported extensions _supported_extension_aliases = ["provider", "router", "extraroute", "binding", "quotas", "security-group", - "agent", "agent_scheduler"] + "agent", "l3_agent_scheduler", + "dhcp_agent_scheduler"] @property def supported_extension_aliases(self): diff --git a/neutron/plugins/nec/nec_plugin.py b/neutron/plugins/nec/nec_plugin.py index d3444e4e2..144f6da67 100644 --- a/neutron/plugins/nec/nec_plugin.py +++ b/neutron/plugins/nec/nec_plugin.py @@ -64,7 +64,8 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base, extraroute_db.ExtraRoute_db_mixin, l3_gwmode_db.L3_NAT_db_mixin, sg_db_rpc.SecurityGroupServerRpcMixin, - agentschedulers_db.AgentSchedulerDbMixin): + agentschedulers_db.L3AgentSchedulerDbMixin, + agentschedulers_db.DhcpAgentSchedulerDbMixin): """NECPluginV2 controls an OpenFlow Controller. The Neutron NECPluginV2 maps L2 logical networks to L2 virtualized networks @@ -79,7 +80,9 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base, """ _supported_extension_aliases = ["router", "ext-gw-mode", "quotas", "binding", "security-group", - "extraroute", "agent", "agent_scheduler"] + "extraroute", "agent", + "l3_agent_scheduler", + "dhcp_agent_scheduler"] @property def supported_extension_aliases(self): diff --git a/neutron/plugins/nicira/NeutronPlugin.py b/neutron/plugins/nicira/NeutronPlugin.py index acb933e04..eeebb24bc 100644 --- a/neutron/plugins/nicira/NeutronPlugin.py +++ b/neutron/plugins/nicira/NeutronPlugin.py @@ -132,7 +132,7 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2, qos_db.NVPQoSDbMixin, nvp_sec.NVPSecurityGroups, nvp_meta.NvpMetadataAccess, - agentschedulers_db.AgentSchedulerDbMixin): + agentschedulers_db.DhcpAgentSchedulerDbMixin): """L2 Virtual network plugin. NvpPluginV2 is a Neutron plugin that provides L2 Virtual Network diff --git a/neutron/plugins/openvswitch/ovs_neutron_plugin.py b/neutron/plugins/openvswitch/ovs_neutron_plugin.py index b98892966..14194e974 100644 --- a/neutron/plugins/openvswitch/ovs_neutron_plugin.py +++ b/neutron/plugins/openvswitch/ovs_neutron_plugin.py @@ -218,7 +218,8 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, extraroute_db.ExtraRoute_db_mixin, l3_gwmode_db.L3_NAT_db_mixin, sg_db_rpc.SecurityGroupServerRpcMixin, - agentschedulers_db.AgentSchedulerDbMixin, + agentschedulers_db.L3AgentSchedulerDbMixin, + agentschedulers_db.DhcpAgentSchedulerDbMixin, portbindings_db.PortBindingMixin): """Implement the Neutron abstractions using Open vSwitch. @@ -247,7 +248,9 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, _supported_extension_aliases = ["provider", "router", "ext-gw-mode", "binding", "quotas", "security-group", - "agent", "extraroute", "agent_scheduler"] + "agent", "extraroute", + "l3_agent_scheduler", + "dhcp_agent_scheduler"] @property def supported_extension_aliases(self): diff --git a/neutron/tests/unit/openvswitch/test_agent_scheduler.py b/neutron/tests/unit/openvswitch/test_agent_scheduler.py index 8dbe0c1d3..c4c7ac3cb 100644 --- a/neutron/tests/unit/openvswitch/test_agent_scheduler.py +++ b/neutron/tests/unit/openvswitch/test_agent_scheduler.py @@ -29,7 +29,8 @@ from neutron.db import agents_db from neutron.db import dhcp_rpc_base from neutron.db import l3_rpc_base from neutron.extensions import agent -from neutron.extensions import agentscheduler +from neutron.extensions import dhcpagentscheduler +from neutron.extensions import l3agentscheduler from neutron import manager from neutron.openstack.common import timeutils from neutron.openstack.common import uuidutils @@ -89,7 +90,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPOk.code, admin_context=True): path = "/agents/%s/%s.%s" % (agent_id, - agentscheduler.L3_ROUTERS, + l3agentscheduler.L3_ROUTERS, self.fmt) return self._request_list(path, expected_code=expected_code, admin_context=admin_context) @@ -98,7 +99,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPOk.code, admin_context=True): path = "/agents/%s/%s.%s" % (agent_id, - agentscheduler.DHCP_NETS, + dhcpagentscheduler.DHCP_NETS, self.fmt) return self._request_list(path, expected_code=expected_code, admin_context=admin_context) @@ -107,7 +108,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPOk.code, admin_context=True): path = "/routers/%s/%s.%s" % (router_id, - agentscheduler.L3_AGENTS, + l3agentscheduler.L3_AGENTS, self.fmt) return self._request_list(path, expected_code=expected_code, admin_context=admin_context) @@ -116,7 +117,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPOk.code, admin_context=True): path = "/networks/%s/%s.%s" % (network_id, - agentscheduler.DHCP_AGENTS, + dhcpagentscheduler.DHCP_AGENTS, self.fmt) return self._request_list(path, expected_code=expected_code, admin_context=admin_context) @@ -125,7 +126,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPCreated.code, admin_context=True): path = "/agents/%s/%s.%s" % (id, - agentscheduler.L3_ROUTERS, + l3agentscheduler.L3_ROUTERS, self.fmt) req = self._path_create_request(path, {'router_id': router_id}, @@ -137,7 +138,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPCreated.code, admin_context=True): path = "/agents/%s/%s.%s" % (id, - agentscheduler.DHCP_NETS, + dhcpagentscheduler.DHCP_NETS, self.fmt) req = self._path_create_request(path, {'network_id': network_id}, @@ -149,7 +150,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPNoContent.code, admin_context=True): path = "/agents/%s/%s/%s.%s" % (id, - agentscheduler.DHCP_NETS, + dhcpagentscheduler.DHCP_NETS, network_id, self.fmt) req = self._path_delete_request(path, @@ -161,7 +162,7 @@ class AgentSchedulerTestMixIn(object): expected_code=exc.HTTPNoContent.code, admin_context=True): path = "/agents/%s/%s/%s.%s" % (id, - agentscheduler.L3_ROUTERS, + l3agentscheduler.L3_ROUTERS, router_id, self.fmt) req = self._path_delete_request(path, admin_context=admin_context)