Load resources dynamically

Automatically load all resources as "plugins" when importing the package
heat.engine.resources, instead of having to list them explicitly.

Change-Id: I9d11ab9a5b1dd21bc5f9c2f0aad95c035a9c9aa0
Signed-off-by: Zane Bitter <zbitter@redhat.com>
This commit is contained in:
Zane Bitter 2012-11-27 16:15:56 +01:00
parent faca9953c0
commit b487adbf8b
4 changed files with 52 additions and 69 deletions

View File

@ -28,6 +28,22 @@ from heat.openstack.common import log as logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_resource_classes = {}
def get_class(resource_type):
return _resource_classes.get(resource_type)
def _register_class(resource_type, resource_class):
logger.info(_('Registering resource type %s') % resource_type)
if resource_type in _resource_classes:
logger.warning(_('Replacing existing resource type %s') %
resource_type)
_resource_classes[resource_type] = resource_class
class Metadata(object): class Metadata(object):
''' '''
A descriptor for accessing the metadata of a resource while ensuring the A descriptor for accessing the metadata of a resource while ensuring the
@ -86,8 +102,7 @@ class Resource(object):
return super(Resource, cls).__new__(cls) return super(Resource, cls).__new__(cls)
# Select the correct subclass to instantiate # Select the correct subclass to instantiate
from heat.engine.resources import register ResourceClass = get_class(json['Type']) or GenericResource
ResourceClass = register.get_class(json['Type']) or GenericResource
return ResourceClass(name, json, stack) return ResourceClass(name, json, stack)
def __init__(self, name, json_snippet, stack): def __init__(self, name, json_snippet, stack):

View File

@ -12,3 +12,37 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
def _register_resources(type_pairs):
from heat.engine import resource
for res_name, res_class in type_pairs:
resource._register_class(res_name, res_class)
def _get_module_resources(module):
if callable(getattr(module, 'resource_mapping', None)):
try:
return module.resource_mapping().iteritems()
except Exception as ex:
logger.error(_('Failed to load resources from %s') % str(module))
else:
return []
def _register_modules(modules):
import itertools
resource_lists = (_get_module_resources(m) for m in modules)
_register_resources(itertools.chain.from_iterable(resource_lists))
def _initialise():
import sys
from heat.common import plugin_loader
_register_modules(plugin_loader.load_modules(sys.modules[__name__]))
_initialise()

View File

@ -1,67 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.
"""
Register of resource types and their mapping to Resource classes.
"""
from heat.engine.resources import autoscaling
from heat.engine.resources import cloud_watch
from heat.engine.resources import dbinstance
from heat.engine.resources import eip
from heat.engine.resources import instance
from heat.engine.resources import loadbalancer
from heat.engine.resources import s3
from heat.engine.resources import security_group
from heat.engine.resources import stack
from heat.engine.resources import user
from heat.engine.resources import volume
from heat.engine.resources import wait_condition
from heat.engine.resources.quantum import floatingip
from heat.engine.resources.quantum import net
from heat.engine.resources.quantum import port
from heat.engine.resources.quantum import router
from heat.engine.resources.quantum import subnet
from heat.openstack.common import log as logging
logger = logging.getLogger('heat.engine.resources.register')
_modules = [
autoscaling, cloud_watch, dbinstance, eip, instance, loadbalancer, s3,
security_group, stack, user, volume, wait_condition, floatingip, net, port,
router, subnet,
]
_resource_classes = {}
def get_class(resource_type):
return _resource_classes.get(resource_type)
def _register_class(resource_type, resource_class):
logger.info(_('Registering resource type %s') % resource_type)
if resource_type in _resource_classes:
logger.warning(_('Replacing existing resource type %s') %
resource_type)
_resource_classes[resource_type] = resource_class
for m in _modules:
for res_type, res_class in m.resource_mapping().items():
_register_class(res_type, res_class)

View File

@ -22,6 +22,7 @@ from heat.engine import api
from heat.engine.event import Event from heat.engine.event import Event
from heat.engine import identifier from heat.engine import identifier
from heat.engine import parser from heat.engine import parser
from heat.engine import resources
from heat.engine import watchrule from heat.engine import watchrule
from heat.openstack.common import cfg from heat.openstack.common import cfg