neutron/neutron/api/rpc/callbacks/resource_manager.py

138 lines
4.6 KiB
Python

# 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 collections
from neutron_lib.callbacks import exceptions
from oslo_log import log as logging
from neutron.api.rpc.callbacks import exceptions as rpc_exc
from neutron.api.rpc.callbacks import resources
LOG = logging.getLogger(__name__)
# TODO(QoS): split the registry/resources_rpc modules into two separate things:
# one for pull and one for push APIs
def _validate_resource_type(resource_type):
if not resources.is_valid_resource_type(resource_type):
raise exceptions.Invalid(element='resource', value=resource_type)
class ResourceCallbacksManager(object, metaclass=abc.ABCMeta):
"""A callback system that allows information providers in a loose manner.
"""
# This hook is to allow tests to get new objects for the class
_singleton = True
def __new__(cls, *args, **kwargs):
if not cls._singleton:
return super(ResourceCallbacksManager, cls).__new__(cls)
if not hasattr(cls, '_instance'):
cls._instance = super(ResourceCallbacksManager, cls).__new__(cls)
return cls._instance
@abc.abstractmethod
def _add_callback(self, callback, resource_type):
pass
@abc.abstractmethod
def _delete_callback(self, callback, resource_type):
pass
def register(self, callback, resource_type):
"""Register a callback for a resource type.
:param callback: the callback. It must raise or return NeutronObject.
:param resource_type: must be a valid resource type.
"""
LOG.debug("Registering callback for %s", resource_type)
_validate_resource_type(resource_type)
self._add_callback(callback, resource_type)
def unregister(self, callback, resource_type):
"""Unregister callback from the registry.
:param callback: the callback.
:param resource_type: must be a valid resource type.
"""
LOG.debug("Unregistering callback for %s", resource_type)
_validate_resource_type(resource_type)
self._delete_callback(callback, resource_type)
@abc.abstractmethod
def clear(self):
"""Brings the manager to a clean state."""
def get_subscribed_types(self):
return list(self._callbacks.keys())
class ProducerResourceCallbacksManager(ResourceCallbacksManager):
_callbacks = dict()
def _add_callback(self, callback, resource_type):
if resource_type in self._callbacks:
raise rpc_exc.CallbacksMaxLimitReached(resource_type=resource_type)
self._callbacks[resource_type] = callback
def _delete_callback(self, callback, resource_type):
try:
del self._callbacks[resource_type]
except KeyError:
raise rpc_exc.CallbackNotFound(resource_type=resource_type)
def clear(self):
self._callbacks = dict()
def get_callback(self, resource_type):
_validate_resource_type(resource_type)
try:
return self._callbacks[resource_type]
except KeyError:
raise rpc_exc.CallbackNotFound(resource_type=resource_type)
class ConsumerResourceCallbacksManager(ResourceCallbacksManager):
_callbacks = collections.defaultdict(set)
def _add_callback(self, callback, resource_type):
self._callbacks[resource_type].add(callback)
def _delete_callback(self, callback, resource_type):
try:
self._callbacks[resource_type].remove(callback)
if not self._callbacks[resource_type]:
del self._callbacks[resource_type]
except KeyError:
raise rpc_exc.CallbackNotFound(resource_type=resource_type)
def clear(self):
self._callbacks = collections.defaultdict(set)
def get_callbacks(self, resource_type):
"""Return the callback if found, None otherwise.
:param resource_type: must be a valid resource type.
"""
_validate_resource_type(resource_type)
callbacks = self._callbacks[resource_type]
if not callbacks:
raise rpc_exc.CallbackNotFound(resource_type=resource_type)
return callbacks