deb-sahara/sahara/plugins/base.py
Vitaly Gridnev 5e91182f05 make ability to return real plugins in list ops
seriailized plugins are needed only when list
of plugins is requested by API. otherwise
we should return usual plugin objects

Change-Id: Iadcebf358d41ec9acf00750967f5ec9e83e95543
bp: plugin-management-api
2016-07-13 19:14:33 +03:00

164 lines
4.7 KiB
Python

# Copyright (c) 2013 Mirantis Inc.
#
# 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
from oslo_config import cfg
from oslo_log import log as logging
import six
from stevedore import enabled
from sahara import conductor as cond
from sahara import exceptions as ex
from sahara.i18n import _
from sahara.i18n import _LI
from sahara.plugins import labels
from sahara.utils import resources
conductor = cond.API
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
def required(fun):
return abc.abstractmethod(fun)
def required_with_default(fun):
return fun
def optional(fun):
fun.__not_implemented__ = True
return fun
@six.add_metaclass(abc.ABCMeta)
class PluginInterface(resources.BaseResource):
__resource_name__ = 'plugin'
name = 'plugin_interface'
@required
def get_title(self):
"""Plugin title
For example:
"Vanilla Provisioning"
"""
pass
@required_with_default
def get_description(self):
"""Optional description of the plugin
This information is targeted to be displayed in UI.
"""
pass
def to_dict(self):
return {
'name': self.name,
'title': self.get_title(),
'description': self.get_description(),
}
class PluginManager(object):
def __init__(self):
self.plugins = {}
self.default_label_schema = {}
self._load_cluster_plugins()
self.label_handler = labels.LabelHandler(self.plugins)
def _load_cluster_plugins(self):
config_plugins = CONF.plugins
extension_manager = enabled.EnabledExtensionManager(
check_func=lambda ext: ext.name in config_plugins,
namespace='sahara.cluster.plugins',
invoke_on_load=True
)
for ext in extension_manager.extensions:
if ext.name in self.plugins:
raise ex.ConfigurationError(
_("Plugin with name '%s' already exists.") % ext.name)
ext.obj.name = ext.name
self.plugins[ext.name] = ext.obj
LOG.info(_LI("Plugin {plugin_name} loaded {entry_point}").format(
plugin_name=ext.name,
entry_point=ext.entry_point_target))
if len(self.plugins) < len(config_plugins):
loaded_plugins = set(six.iterkeys(self.plugins))
requested_plugins = set(config_plugins)
raise ex.ConfigurationError(
_("Plugins couldn't be loaded: %s") %
", ".join(requested_plugins - loaded_plugins))
def get_plugins(self, serialized=False):
if serialized:
return [self.serialize_plugin(name) for name in CONF.plugins]
return [self.get_plugin(name) for name in CONF.plugins]
def get_plugin(self, plugin_name):
return self.plugins.get(plugin_name)
def is_plugin_implements(self, plugin_name, fun_name):
plugin = self.get_plugin(plugin_name)
fun = getattr(plugin, fun_name)
if not (fun and callable(fun)):
return False
return not hasattr(fun, '__not_implemented__')
def serialize_plugin(self, plugin_name, version=None):
plugin = self.get_plugin(plugin_name)
if plugin:
res = plugin.as_resource()
res._info.update(self.label_handler.get_label_full_details(
plugin_name))
if version:
if version in plugin.get_versions():
res._info.update(plugin.get_version_details(version))
else:
return None
return res
def update_plugin(self, plugin_name, values):
self.label_handler.update_plugin(plugin_name, values)
return self.serialize_plugin(plugin_name)
def validate_plugin_update(self, plugin_name, values):
return self.label_handler.validate_plugin_update(plugin_name, values)
def get_plugin_update_validation_jsonschema(self):
return self.label_handler.get_plugin_update_validation_jsonschema()
def validate_plugin_labels(self, plugin, version):
self.label_handler.validate_plugin_labels(plugin, version)
PLUGINS = None
def setup_plugins():
global PLUGINS
PLUGINS = PluginManager()