karbor/karbor/services/protection/protectable_registry.py

121 lines
4.4 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.
from karbor.exception import ListProtectableResourceFailed
from karbor.services.protection.graph import build_graph
from oslo_config import cfg
from oslo_log import log as logging
from stevedore import extension
LOG = logging.getLogger(__name__)
def _warn_missing_protectable(extmanager, ep, err):
LOG.warning("Could not load %(name)s: %(error)s")
class ProtectableRegistry(object):
def __init__(self):
super(ProtectableRegistry, self).__init__()
self._protectable_map = {}
self._plugin_map = {}
def load_plugins(self):
"""Load all protectable plugins configured and register them.
"""
mgr = extension.ExtensionManager(
namespace='karbor.protectables',
invoke_on_load=True,
on_load_failure_callback=_warn_missing_protectable)
for e in mgr:
self.register_plugin(e.obj)
def register_plugin(self, plugin):
self._plugin_map[plugin.get_resource_type()] = plugin
def _get_protectable(self, context, resource_type, conf=cfg.CONF):
if resource_type in self._protectable_map:
return self._protectable_map[resource_type]
protectable = self._plugin_map[resource_type].instance(
context, conf)
self._protectable_map[resource_type] = protectable
return protectable
def list_resource_types(self):
"""List all resource types supported by protectables.
:return: The list of supported resource types.
"""
return [type for type in self._plugin_map.keys()]
def get_protectable_resource_plugin(self, resource_type):
"""Get the protectable plugin with the specified type."""
return self._plugin_map.get(resource_type)
def list_resources(self, context, resource_type, parameters=None):
"""List resource instances of given type.
:param resource_type: The resource type to list instance.
:return: The list of resource instance.
"""
protectable = self._get_protectable(context, resource_type)
return protectable.list_resources(context, parameters=parameters)
def show_resource(self, context, resource_type, resource_id,
parameters=None):
"""List resource instances of given type.
:param resource_type: The resource type of instance.
:param resource_id: The resource id of instance.
:return: The show of resource instance.
"""
protectable = self._get_protectable(context, resource_type)
return protectable.show_resource(context, resource_id,
parameters=parameters)
def fetch_dependent_resources(self, context, resource):
"""List dependent resources under given parent resource.
:param resource: The parent resource to list dependent resources.
:return: The list of dependent resources.
"""
result = []
for plugin in self._plugin_map.values():
if resource.type in plugin.get_parent_resource_types():
protectable = self._get_protectable(
context,
plugin.get_resource_type())
try:
protectable_resources = \
protectable.get_dependent_resources(context, resource)
except ListProtectableResourceFailed as e:
LOG.error("List resources failed, so skip it. "
"Error: {0}".format(e))
protectable_resources = []
result.extend(protectable_resources)
return result
def build_graph(self, context, resources):
def fetch_dependent_resources_context(resource):
return self.fetch_dependent_resources(context, resource)
return build_graph(
start_nodes=resources,
get_child_nodes_func=fetch_dependent_resources_context,
)