Implement L3 Agent Extension Manager

Using the generalized agent extension mechanism, create an agent extension
manager in the L3 agent, so that the L3 agent can load agent extensions.

Co-Authored-By: Margaret Frances <margaret_frances@cable.comcast.com>
Implements: blueprint l3-agent-extensions
Needed-By: Iff506bd11b83d396305e631f3dd95d44cf38fd63

Change-Id: I6da92cb8b9fcbb603e120eababcf4ce711da3e30
This commit is contained in:
Nate Johnston 2016-07-07 21:32:28 +00:00
parent 97c491294c
commit 93a8dc3dbe
4 changed files with 145 additions and 0 deletions

View File

@ -32,6 +32,7 @@ from neutron.agent.l3 import dvr_edge_router as dvr_router
from neutron.agent.l3 import dvr_local_router as dvr_local_router from neutron.agent.l3 import dvr_local_router as dvr_local_router
from neutron.agent.l3 import ha from neutron.agent.l3 import ha
from neutron.agent.l3 import ha_router from neutron.agent.l3 import ha_router
from neutron.agent.l3 import l3_agent_extensions_manager as l3_ext_manager
from neutron.agent.l3 import legacy_router from neutron.agent.l3 import legacy_router
from neutron.agent.l3 import namespace_manager from neutron.agent.l3 import namespace_manager
from neutron.agent.l3 import namespaces from neutron.agent.l3 import namespaces
@ -223,6 +224,8 @@ class L3NATAgent(ha.AgentMixin,
continue continue
break break
self.init_extension_manager(self.plugin_rpc)
self.metadata_driver = None self.metadata_driver = None
if self.conf.enable_metadata_proxy: if self.conf.enable_metadata_proxy:
self.metadata_driver = metadata_driver.MetadataDriver(self) self.metadata_driver = metadata_driver.MetadataDriver(self)
@ -341,6 +344,7 @@ class L3NATAgent(ha.AgentMixin,
try: try:
self._router_removed(router_id) self._router_removed(router_id)
self.l3_ext_manager.delete_router(self.context, router_id)
except Exception: except Exception:
LOG.exception(_LE('Error while deleting router %s'), router_id) LOG.exception(_LE('Error while deleting router %s'), router_id)
return False return False
@ -363,6 +367,13 @@ class L3NATAgent(ha.AgentMixin,
registry.notify(resources.ROUTER, events.AFTER_DELETE, self, router=ri) registry.notify(resources.ROUTER, events.AFTER_DELETE, self, router=ri)
def init_extension_manager(self, connection):
l3_ext_manager.register_opts(self.conf)
self.l3_ext_manager = (
l3_ext_manager.L3AgentExtensionsManager(self.conf))
self.l3_ext_manager.initialize(
connection, l3_constants.L3_AGENT_MODE)
def router_deleted(self, context, router_id): def router_deleted(self, context, router_id):
"""Deal with router deletion RPC message.""" """Deal with router deletion RPC message."""
LOG.debug('Got router deleted notification for %s', router_id) LOG.debug('Got router deleted notification for %s', router_id)
@ -426,6 +437,7 @@ class L3NATAgent(ha.AgentMixin,
ri.router = router ri.router = router
ri.process(self) ri.process(self)
registry.notify(resources.ROUTER, events.AFTER_CREATE, self, router=ri) registry.notify(resources.ROUTER, events.AFTER_CREATE, self, router=ri)
self.l3_ext_manager.add_router(self.context, router)
def _process_updated_router(self, router): def _process_updated_router(self, router):
ri = self.router_info[router['id']] ri = self.router_info[router['id']]
@ -434,6 +446,7 @@ class L3NATAgent(ha.AgentMixin,
self, router=ri) self, router=ri)
ri.process(self) ri.process(self)
registry.notify(resources.ROUTER, events.AFTER_UPDATE, self, router=ri) registry.notify(resources.ROUTER, events.AFTER_UPDATE, self, router=ri)
self.l3_ext_manager.update_router(self.context, router)
def _resync_router(self, router_update, def _resync_router(self, router_update,
priority=queue.PRIORITY_SYNC_ROUTERS_TASK): priority=queue.PRIORITY_SYNC_ROUTERS_TASK):

View File

@ -0,0 +1,55 @@
# 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 six
from neutron.agent import agent_extension
@six.add_metaclass(abc.ABCMeta)
class L3AgentCoreResourceExtension(agent_extension.AgentCoreResourceExtension):
"""Define stable abstract interface for l3 agent extensions.
An agent extension extends the agent core functionality.
"""
@abc.abstractmethod
def add_router(self, context, data):
"""add agent extension for router.
Called on router create.
:param context: rpc context
:param data: router data
"""
@abc.abstractmethod
def update_router(self, context, data):
"""Handle agent extension for update.
Called on router update.
:param context: rpc context
:param data: router data
"""
@abc.abstractmethod
def delete_router(self, context, data):
"""Delete router from agent extension.
:param context: rpc context
:param data: router data
"""

View File

@ -0,0 +1,72 @@
# Copyright (c) 2015 Mellanox Technologies, Ltd
# 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 oslo_log import log
from neutron._i18n import _LE
from neutron.agent import agent_extensions_manager as agent_ext_manager
LOG = log.getLogger(__name__)
L3_AGENT_EXT_MANAGER_NAMESPACE = 'neutron.agent.l3.extensions'
def register_opts(conf):
agent_ext_manager.register_opts(conf)
class L3AgentExtensionsManager(agent_ext_manager.AgentExtensionsManager):
"""Manage l3 agent extensions."""
def __init__(self, conf):
super(L3AgentExtensionsManager, self).__init__(conf,
L3_AGENT_EXT_MANAGER_NAMESPACE)
def add_router(self, context, data):
"""Notify all agent extensions to add router."""
for extension in self:
if hasattr(self, 'add_router'):
extension.obj.add_router(context, data)
else:
LOG.error(
_LE("Agent Extension '%(name)s' does not "
"implement method add_router"),
{'name': extension.name}
)
def update_router(self, context, data):
"""Notify all agent extensions to update router."""
for extension in self:
if hasattr(self, 'update_router'):
extension.obj.update_router(context, data)
else:
LOG.error(
_LE("Agent Extension '%(name)s' does not "
"implement method update_router"),
{'name': extension.name}
)
def delete_router(self, context, data):
"""Notify all agent extensions to delete router."""
for extension in self:
if hasattr(self, 'delete_router'):
extension.obj.delete_router(context, data)
else:
LOG.error(
_LE("Agent Extension '%(name)s' does not "
"implement method delete_router"),
{'name': extension.name}
)

View File

@ -0,0 +1,5 @@
---
features:
- The neutron L3 agent now has the ability to load
agent extensions, which allows other services to
integrate without additional agent changes.