AgentExtensionsManager and AgentCoreResourceExtension
This patch introduces the following classes: L2Agent - abstract class for common L2Agent implementions. AgentExtensionsManager - to load AgentCoreResourceExtension. AgentCoreResourceExtension - interface class to define the AgentCoreResourceExtension API. This allows better segregation between L2 Agent Core and L2 Agent Extensions. The patch is missing unit test but it was tested manually. I added a unit tests @TODO comments to come back to them later. Change-Id: I813de7ff1bee188f4294f4b3eb3645ebd903297b
This commit is contained in:
parent
2d38c742e8
commit
c26142be33
|
@ -0,0 +1,61 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class AgentCoreResourceExtension(object):
|
||||||
|
"""Define stable abstract interface for Agent extension.
|
||||||
|
|
||||||
|
An agent extension extends the agent core functionality.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def initialize(self, resource_rpc):
|
||||||
|
"""Perform agent core resource extension initialization.
|
||||||
|
|
||||||
|
Called after all extensions have been loaded.
|
||||||
|
No abstract methods defined below will be
|
||||||
|
called prior to this method being called.
|
||||||
|
:param resource_rpc - the agent side rpc for getting
|
||||||
|
resource by type and id
|
||||||
|
"""
|
||||||
|
self.resource_rpc = resource_rpc
|
||||||
|
|
||||||
|
def handle_network(self, context, data):
|
||||||
|
"""handle agent extension for network.
|
||||||
|
|
||||||
|
:param context - rpc context
|
||||||
|
:param data - network data
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def handle_subnet(self, context, data):
|
||||||
|
"""handle agent extension for subnet.
|
||||||
|
|
||||||
|
:param context - rpc context
|
||||||
|
:param data - subnet data
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def handle_port(self, context, data):
|
||||||
|
"""handle agent extension for port.
|
||||||
|
|
||||||
|
:param context - rpc context
|
||||||
|
:param data - port data
|
||||||
|
"""
|
||||||
|
pass
|
|
@ -0,0 +1,70 @@
|
||||||
|
# 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
|
||||||
|
import stevedore
|
||||||
|
|
||||||
|
from neutron.i18n import _LE, _LI
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(QoS) add unit tests to Agent extensions mgr
|
||||||
|
class AgentExtensionsManager(stevedore.named.NamedExtensionManager):
|
||||||
|
"""Manage agent extensions."""
|
||||||
|
|
||||||
|
def __init__(self, agent_extensions):
|
||||||
|
# Ordered list of agent extensions, defining
|
||||||
|
# the order in which the agent extensions are called.
|
||||||
|
|
||||||
|
LOG.info(_LI("Configured agent extensions names: %s"),
|
||||||
|
agent_extensions)
|
||||||
|
|
||||||
|
super(AgentExtensionsManager, self).__init__(
|
||||||
|
'neutron.agent.l2.extensions', agent_extensions,
|
||||||
|
invoke_on_load=True, name_order=True)
|
||||||
|
LOG.info(_LI("Loaded agent extensions names: %s"), self.names())
|
||||||
|
|
||||||
|
def _call_on_agent_extensions(self, method_name, context, data):
|
||||||
|
"""Helper method for calling a method across all agent extensions."""
|
||||||
|
for extension in self:
|
||||||
|
try:
|
||||||
|
getattr(extension.obj, method_name)(context, data)
|
||||||
|
# TODO(QoS) add agent extensions exception and catch them here
|
||||||
|
except AttributeError:
|
||||||
|
LOG.exception(
|
||||||
|
_LE("Agent Extension '%(name)s' failed in %(method)s"),
|
||||||
|
{'name': extension.name, 'method': method_name}
|
||||||
|
)
|
||||||
|
|
||||||
|
def initialize(self, resource_rpc):
|
||||||
|
# Initialize each agent extension in the list.
|
||||||
|
for extension in self:
|
||||||
|
LOG.info(_LI("Initializing agent extension '%s'"), extension.name)
|
||||||
|
extension.obj.initialize(resource_rpc)
|
||||||
|
|
||||||
|
def handle_network(self, context, data):
|
||||||
|
"""Notify all agent extensions to handle network."""
|
||||||
|
self._call_on_agent_extensions("handle_network", context, data)
|
||||||
|
|
||||||
|
def handle_subnet(self, context, data):
|
||||||
|
"""Notify all agent extensions to handle subnet."""
|
||||||
|
self._call_on_agent_extensions("handle_subnet", context, data)
|
||||||
|
|
||||||
|
def handle_port(self, context, data):
|
||||||
|
"""Notify all agent extensions to handle port."""
|
||||||
|
self._call_on_agent_extensions("handle_port", context, data)
|
||||||
|
#TODO(Qos) we are missing how to handle delete. we can pass action
|
||||||
|
#type in all the handle methods or add handle_delete_resource methods
|
|
@ -0,0 +1,55 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
from neutron.agent.l2 import agent_extensions_manager
|
||||||
|
|
||||||
|
|
||||||
|
#TODO(QoS): add unit tests to L2 Agent
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class L2Agent(object):
|
||||||
|
"""Define stable abstract interface for L2 Agent
|
||||||
|
|
||||||
|
This class initialize the agent extension manager and
|
||||||
|
provides API for calling the extensions manager process
|
||||||
|
extensions methods.
|
||||||
|
"""
|
||||||
|
def __init__(self, polling_interval):
|
||||||
|
self.polling_interval = polling_interval
|
||||||
|
self.agent_extensions_mgr = None
|
||||||
|
self.resource_rpc = None
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
#TODO(QoS): get extensions from server ????
|
||||||
|
agent_extensions = ('qos', )
|
||||||
|
self.agent_extensions_mgr = (
|
||||||
|
agent_extensions_manager.AgentExtensionsManager(
|
||||||
|
agent_extensions))
|
||||||
|
self.agent_extensions_mgr.initialize(self.resource_rpc)
|
||||||
|
|
||||||
|
def process_network_extensions(self, context, network):
|
||||||
|
self.agent_extensions_mgr.handle_network(
|
||||||
|
context, network)
|
||||||
|
|
||||||
|
def process_subnet_extensions(self, context, subnet):
|
||||||
|
self.agent_extensions_mgr.handle_subnet(
|
||||||
|
context, subnet)
|
||||||
|
|
||||||
|
def process_port_extensions(self, context, port):
|
||||||
|
self.agent_extensions_mgr.handle_port(
|
||||||
|
context, port)
|
|
@ -202,6 +202,7 @@ neutron.openstack.common.cache.backends =
|
||||||
neutron.ipam_drivers =
|
neutron.ipam_drivers =
|
||||||
fake = neutron.tests.unit.ipam.fake_driver:FakeDriver
|
fake = neutron.tests.unit.ipam.fake_driver:FakeDriver
|
||||||
internal = neutron.ipam.drivers.neutrondb_ipam.driver:NeutronDbPool
|
internal = neutron.ipam.drivers.neutrondb_ipam.driver:NeutronDbPool
|
||||||
|
neutron.agent.l2.extensions =
|
||||||
# These are for backwards compat with Icehouse notification_driver configuration values
|
# These are for backwards compat with Icehouse notification_driver configuration values
|
||||||
oslo.messaging.notify.drivers =
|
oslo.messaging.notify.drivers =
|
||||||
neutron.openstack.common.notifier.log_notifier = oslo_messaging.notify._impl_log:LogDriver
|
neutron.openstack.common.notifier.log_notifier = oslo_messaging.notify._impl_log:LogDriver
|
||||||
|
|
Loading…
Reference in New Issue