neutron-lib/neutron_lib/plugins/directory.py
Armando Migliaccio 763fe5ed23 Introduce Plugin Directory for Neutron
The NeutronManager is heavily relied on across Neutron projects
primarily to look up plugins at runtime. During the init phase
however, the Manager lays down all sorts of plumbing needed for
other core objectives. Rehoming it as is would be not only
impossible, but also perpetrating the bad pattern where the
class itself holds too many responsibilities.

This patch extract the part whose responsibility is the mapping
between aliases and plugins. The NeutronManager will then make
use of this registry to store the plugin mapping, and subprojects
will stop using the manager in favor of the newly introduced
plugin directory.

Partially-implement: blueprint neutron-lib

Change-Id: I83b0217ea16d2c3f4ada05686c50470e50bd5208
2016-10-28 00:57:30 -07:00

93 lines
2.6 KiB
Python

# 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 weakref
from oslo_concurrency import lockutils
from neutron_lib import constants
_synchronized = lockutils.synchronized_with_prefix("neutron-")
class _PluginDirectory(object):
"""A directory of activated plugins in a Neutron Deployment.
The directory is bootstrapped by a Neutron Manager running in
the context of a Neutron Server process.
"""
def __init__(self):
self._plugins = {}
def add_plugin(self, alias, plugin):
"""Add a plugin of type 'alias'."""
self._plugins[alias] = plugin
def get_plugin(self, alias):
"""Get a plugin for a given alias or None if not present."""
return self.plugins.get(alias)
@property
def plugins(self):
"""The mapping alias -> weak reference to the plugin."""
return dict((x, weakref.proxy(y))
for x, y in self._plugins.items())
@property
def unique_plugins(self):
"""A sequence of the unique plugins activated in the environments."""
return tuple(weakref.proxy(x) for x in set(self._plugins.values()))
@property
def is_loaded(self):
"""True if the directory is non empty."""
return len(self._plugins) > 0
# Create a singleton plugins directory for the Neutron server instance.
# Accessing these methods before a Neutron Manager has had the chance
# to load the environment may result in callers handling an empty directory.
_PLUGIN_DIRECTORY = None
@_synchronized("plugin-directory")
def _create_plugin_directory():
global _PLUGIN_DIRECTORY
_PLUGIN_DIRECTORY = _PluginDirectory()
return _PLUGIN_DIRECTORY
def _get_plugin_directory():
if _PLUGIN_DIRECTORY is None:
return _create_plugin_directory()
return _PLUGIN_DIRECTORY
def add_plugin(alias, plugin):
_get_plugin_directory().add_plugin(alias, plugin)
def get_plugin(alias=constants.CORE):
return _get_plugin_directory().get_plugin(alias)
def get_plugins():
return _get_plugin_directory().plugins
def get_unique_plugins():
return _get_plugin_directory().unique_plugins