summaryrefslogtreecommitdiffstats
path: root/openstack
diff options
context:
space:
mode:
authorRussell Bryant <rbryant@redhat.com>2012-10-23 23:33:10 -0400
committerJason Kölker <jason@koelker.net>2012-11-05 01:03:31 -0600
commite0f57e92dfad742abf5aebeedc4f05700d5cd4a5 (patch)
tree1d718fb572b17e4aa3c845268d8599384fe737d4 /openstack
parentdfd3ce97cd3e4eb1b5956d091fe6e8b7f49b4d67 (diff)
downloadoslo-e0f57e92dfad742abf5aebeedc4f05700d5cd4a5.tar.gz
oslo-e0f57e92dfad742abf5aebeedc4f05700d5cd4a5.tar.xz
oslo-e0f57e92dfad742abf5aebeedc4f05700d5cd4a5.zip
Remove openstack.common.config and extensions.
Remove the config module. All core openstack projects are using the cfg module instead so no further development will be done on this module. Also remove the extensions module. This code was imported but there has been no attempt to get any projects to use it. Change-Id: I4a974ba1ea25e94fd55cad243cde5f1ef6a17289
Diffstat (limited to 'openstack')
-rw-r--r--openstack/common/config.py337
-rw-r--r--openstack/common/extensions.py539
2 files changed, 0 insertions, 876 deletions
diff --git a/openstack/common/config.py b/openstack/common/config.py
deleted file mode 100644
index 12645f3..0000000
--- a/openstack/common/config.py
+++ /dev/null
@@ -1,337 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-"""
-Routines for configuring Openstack Projects
-"""
-
-import logging
-import logging.config
-import logging.handlers
-import optparse
-import os
-import sys
-
-from paste import deploy
-
-DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s"
-DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
-
-
-def parse_options(parser, cli_args=None):
- """
- Returns the parsed CLI options, command to run and its arguments, merged
- with any same-named options found in a configuration file.
-
- The function returns a tuple of (options, args), where options is a
- mapping of option key/str(value) pairs, and args is the set of arguments
- (not options) supplied on the command-line.
-
- The reason that the option values are returned as strings only is that
- ConfigParser and paste.deploy only accept string values...
-
- :param parser: The option parser
- :param cli_args: (Optional) Set of arguments to process. If not present,
- sys.argv[1:] is used.
- :retval tuple of (options, args)
- """
-
- (options, args) = parser.parse_args(cli_args)
-
- return (vars(options), args)
-
-
-def add_common_options(parser):
- """
- Given a supplied optparse.OptionParser, adds an OptionGroup that
- represents all common configuration options.
-
- :param parser: optparse.OptionParser
- """
- help_text = ("The following configuration options are common to "
- "this app's programs.")
-
- group = optparse.OptionGroup(parser, "Common Options", help_text)
- group.add_option('-v', '--verbose', default=False, dest="verbose",
- action="store_true",
- help="Print more verbose output")
- group.add_option('-d', '--debug', default=False, dest="debug",
- action="store_true",
- help="Print debugging output")
- group.add_option('--config-file', default=None, metavar="PATH",
- help="Path to the config file to use. When not specified "
- "(the default), we generally look at the first "
- "argument specified to be a config file, and if "
- "that is also missing, we search standard "
- "directories for a config file.")
- parser.add_option_group(group)
-
-
-def add_log_options(parser):
- """
- Given a supplied optparse.OptionParser, adds an OptionGroup that
- represents all the configuration options around logging.
-
- :param parser: optparse.OptionParser
- """
- help_text = ("The following configuration options are specific to "
- "logging functionality for this program.")
-
- group = optparse.OptionGroup(parser, "Logging Options", help_text)
- group.add_option('--log-config', default=None, metavar="PATH",
- help="If this option is specified, the logging "
- "configuration file specified is used and overrides "
- "any other logging options specified. Please see "
- "the Python logging module documentation for "
- "details on logging configuration files.")
- group.add_option('--log-date-format', metavar="FORMAT",
- default=DEFAULT_LOG_DATE_FORMAT,
- help="Format string for %(asctime)s in log records. "
- "Default: %default")
- group.add_option('--log-file', default=None, metavar="PATH",
- help="(Optional) Name of log file to output to. "
- "If not set, logging will go to stdout.")
- group.add_option("--log-dir", default=None,
- help="(Optional) The directory to keep log files in "
- "(will be prepended to --logfile)")
- group.add_option('--use-syslog', default=False, dest="use_syslog",
- action="store_true",
- help="Use syslog for logging.")
- parser.add_option_group(group)
-
-
-def setup_logging(options, conf):
- """
- Sets up the logging options for a log with supplied name
-
- :param options: Mapping of typed option key/values
- :param conf: Mapping of untyped key/values from config file
- """
-
- if options.get('log_config', None):
- # Use a logging configuration file for all settings...
- if os.path.exists(options['log_config']):
- logging.config.fileConfig(options['log_config'])
- return
- else:
- raise RuntimeError("Unable to locate specified logging "
- "config file: %s" % options['log_config'])
-
- # If either the CLI option or the conf value
- # is True, we set to True
- debug = (options.get('debug') or
- get_option(conf, 'debug', type='bool', default=False))
- verbose = (options.get('verbose') or
- get_option(conf, 'verbose', type='bool', default=False))
- root_logger = logging.root
- if debug:
- root_logger.setLevel(logging.DEBUG)
- elif verbose:
- root_logger.setLevel(logging.INFO)
- else:
- root_logger.setLevel(logging.WARNING)
-
- # Set log configuration from options...
- # Note that we use a hard-coded log format in the options
- # because of Paste.Deploy bug #379
- # http://trac.pythonpaste.org/pythonpaste/ticket/379
- log_format = options.get('log_format', DEFAULT_LOG_FORMAT)
- log_date_format = options.get('log_date_format', DEFAULT_LOG_DATE_FORMAT)
- formatter = logging.Formatter(log_format, log_date_format)
-
- logfile = options.get('log_file')
- if not logfile:
- logfile = conf.get('log_file')
-
- use_syslog = (options.get('use_syslog') or
- get_option(conf, 'use_syslog', type='bool', default=False))
-
- if use_syslog:
- handler = logging.handlers.SysLogHandler(address='/dev/log')
- elif logfile:
- logdir = options.get('log_dir')
- if not logdir:
- logdir = conf.get('log_dir')
- if logdir:
- logfile = os.path.join(logdir, logfile)
- handler = logging.FileHandler(logfile)
- else:
- handler = logging.StreamHandler(sys.stdout)
-
- handler.setFormatter(formatter)
- root_logger.addHandler(handler)
-
-
-def fix_path(path):
- """
- Return the full absolute path
- """
- return os.path.abspath(os.path.expanduser(path))
-
-
-def find_config_file(app_name, options, args, config_dir=None):
- """
- Return the first config file found for an application.
-
- We search for the paste config file in the following order:
- * If --config-file option is used, use that
- * If args[0] is a file, use that
- * Search for $app.conf in standard directories:
- * .
- * ~.config_dir/
- * ~
- * /etc/config_dir
- * /etc
-
- :retval Full path to config file, or None if no config file found
- """
- config_dir = config_dir or app_name
-
- if options.get('config_file'):
- if os.path.exists(options['config_file']):
- return fix_path(options['config_file'])
- elif args:
- if os.path.exists(args[0]):
- return fix_path(args[0])
-
- # Handle standard directory search for $app_name.conf
- config_file_dirs = [fix_path(os.getcwd()),
- fix_path(os.path.join('~', '.' + config_dir)),
- fix_path('~'),
- os.path.join('/etc', config_dir),
- '/etc']
-
- for cfg_dir in config_file_dirs:
- cfg_file = os.path.join(cfg_dir, '%s.conf' % app_name)
- if os.path.exists(cfg_file):
- return cfg_file
-
-
-def load_paste_config(app_name, options, args, config_dir=None):
- """
- Looks for a config file to use for an app and returns the
- config file path and a configuration mapping from a paste config file.
-
- We search for the paste config file in the following order:
- * If --config-file option is used, use that
- * If args[0] is a file, use that
- * Search for $app_name.conf in standard directories:
- * .
- * ~.config_dir/
- * ~
- * /etc/config_dir
- * /etc
-
- :param app_name: Name of the application to load config for, or None.
- None signifies to only load the [DEFAULT] section of
- the config file.
- :param options: Set of typed options returned from parse_options()
- :param args: Command line arguments from argv[1:]
- :retval Tuple of (conf_file, conf)
-
- :raises RuntimeError when config file cannot be located or there was a
- problem loading the configuration file.
- """
- conf_file = find_config_file(app_name, options, args, config_dir)
- if not conf_file:
- raise RuntimeError("Unable to locate any configuration file. "
- "Cannot load application %s" % app_name)
- try:
- conf = deploy.appconfig("config:%s" % conf_file, name=app_name)
- return conf_file, conf
- except Exception, e:
- raise RuntimeError("Error trying to load config %s: %s"
- % (conf_file, e))
-
-
-def load_paste_app(app_name, options, args, config_dir=None):
- """
- Builds and returns a WSGI app from a paste config file.
-
- We search for the paste config file in the following order:
- * If --config-file option is used, use that
- * If args[0] is a file, use that
- * Search for $app_name.conf in standard directories:
- * .
- * ~.config_dir/
- * ~
- * /etc/config_dir
- * /etc
-
- :param app_name: Name of the application to load
- :param options: Set of typed options returned from parse_options()
- :param args: Command line arguments from argv[1:]
-
- :raises RuntimeError when config file cannot be located or application
- cannot be loaded from config file
- """
- conf_file, conf = load_paste_config(app_name, options,
- args, config_dir)
-
- try:
- # Setup logging early, supplying both the CLI options and the
- # configuration mapping from the config file
- setup_logging(options, conf)
-
- # We only update the conf dict for the verbose and debug
- # flags. Everything else must be set up in the conf file...
- debug = (options.get('debug') or
- get_option(conf, 'debug', type='bool', default=False))
- verbose = (options.get('verbose') or
- get_option(conf, 'verbose', type='bool', default=False))
- conf['debug'] = debug
- conf['verbose'] = verbose
-
- # Log the options used when starting if we're in debug mode...
- if debug:
- logger = logging.getLogger(app_name)
- logger.debug("*" * 80)
- logger.debug("Configuration options gathered from config file:")
- logger.debug(conf_file)
- logger.debug("================================================")
- items = dict([(k, v) for k, v in conf.items()
- if k not in ('__file__', 'here')])
- for key, value in sorted(items.items()):
- logger.debug("%(key)-30s %(value)s" % locals())
- logger.debug("*" * 80)
- app = deploy.loadapp("config:%s" % conf_file, name=app_name)
- except (LookupError, ImportError), e:
- raise RuntimeError("Unable to load %(app_name)s from "
- "configuration file %(conf_file)s."
- "\nGot: %(e)r" % locals())
- return conf, app
-
-
-def get_option(options, option, **kwargs):
- if option in options:
- value = options[option]
- type_ = kwargs.get('type', 'str')
- if type_ == 'bool':
- if hasattr(value, 'lower'):
- return value.lower() == 'true'
- else:
- return value
- elif type_ == 'int':
- return int(value)
- elif type_ == 'float':
- return float(value)
- else:
- return value
- elif 'default' in kwargs:
- return kwargs['default']
- else:
- raise KeyError("option '%s' not found" % option)
diff --git a/openstack/common/extensions.py b/openstack/common/extensions.py
deleted file mode 100644
index 906906d..0000000
--- a/openstack/common/extensions.py
+++ /dev/null
@@ -1,539 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# Copyright 2011 Justin Santa Barbara
-# 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 imp
-import logging
-from lxml import etree
-import os
-import routes
-import webob.dec
-import webob.exc
-
-from openstack.common import exception
-from openstack.common.gettextutils import _
-from openstack.common import wsgi
-
-
-LOG = logging.getLogger('extensions')
-DEFAULT_XMLNS = "http://docs.openstack.org/"
-XMLNS_ATOM = "http://www.w3.org/2005/Atom"
-
-
-class ExtensionDescriptor(object):
- """Base class that defines the contract for extensions.
-
- Note that you don't have to derive from this class to have a valid
- extension; it is purely a convenience.
-
- """
-
- def get_name(self):
- """The name of the extension.
-
- e.g. 'Fox In Socks'
-
- """
- raise NotImplementedError()
-
- def get_alias(self):
- """The alias for the extension.
-
- e.g. 'FOXNSOX'
-
- """
- raise NotImplementedError()
-
- def get_description(self):
- """Friendly description for the extension.
-
- e.g. 'The Fox In Socks Extension'
-
- """
- raise NotImplementedError()
-
- def get_namespace(self):
- """The XML namespace for the extension.
-
- e.g. 'http://www.fox.in.socks/api/ext/pie/v1.0'
-
- """
- raise NotImplementedError()
-
- def get_updated(self):
- """The timestamp when the extension was last updated.
-
- e.g. '2011-01-22T13:25:27-06:00'
-
- """
- # NOTE(justinsb): Not sure of the purpose of this is, vs the XML NS
- raise NotImplementedError()
-
- def get_resources(self):
- """List of extensions.ResourceExtension extension objects.
-
- Resources define new nouns, and are accessible through URLs.
-
- """
- resources = []
- return resources
-
- def get_actions(self):
- """List of extensions.ActionExtension extension objects.
-
- Actions are verbs callable from the API.
-
- """
- actions = []
- return actions
-
- def get_request_extensions(self):
- """List of extensions.RequestException extension objects.
-
- Request extensions are used to handle custom request data.
-
- """
- request_exts = []
- return request_exts
-
-
-class ActionExtensionController(object):
- def __init__(self, application):
- self.application = application
- self.action_handlers = {}
-
- def add_action(self, action_name, handler):
- self.action_handlers[action_name] = handler
-
- def action(self, req, id, body):
- for action_name, handler in self.action_handlers.iteritems():
- if action_name in body:
- return handler(body, req, id)
- # no action handler found (bump to downstream application)
- res = self.application
- return res
-
-
-class ActionExtensionResource(wsgi.Resource):
-
- def __init__(self, application):
- controller = ActionExtensionController(application)
- wsgi.Resource.__init__(self, controller)
-
- def add_action(self, action_name, handler):
- self.controller.add_action(action_name, handler)
-
-
-class RequestExtensionController(object):
-
- def __init__(self, application):
- self.application = application
- self.handlers = []
-
- def add_handler(self, handler):
- self.handlers.append(handler)
-
- def process(self, req, *args, **kwargs):
- res = req.get_response(self.application)
- # currently request handlers are un-ordered
- for handler in self.handlers:
- res = handler(req, res)
- return res
-
-
-class RequestExtensionResource(wsgi.Resource):
-
- def __init__(self, application):
- controller = RequestExtensionController(application)
- wsgi.Resource.__init__(self, controller)
-
- def add_handler(self, handler):
- self.controller.add_handler(handler)
-
-
-class ExtensionsResource(wsgi.Resource):
-
- def __init__(self, extension_manager):
- self.extension_manager = extension_manager
- body_serializers = {'application/xml': ExtensionsXMLSerializer()}
- serializer = wsgi.ResponseSerializer(body_serializers=body_serializers)
- super(ExtensionsResource, self).__init__(self, None, serializer)
-
- def _translate(self, ext):
- ext_data = {}
- ext_data['name'] = ext.get_name()
- ext_data['alias'] = ext.get_alias()
- ext_data['description'] = ext.get_description()
- ext_data['namespace'] = ext.get_namespace()
- ext_data['updated'] = ext.get_updated()
- ext_data['links'] = [] # TODO(dprince): implement extension links
- return ext_data
-
- def index(self, req):
- extensions = []
- for _alias, ext in self.extension_manager.extensions.iteritems():
- extensions.append(self._translate(ext))
- return dict(extensions=extensions)
-
- def show(self, req, id):
- # NOTE(dprince): the extensions alias is used as the 'id' for show
- ext = self.extension_manager.extensions.get(id, None)
- if not ext:
- raise webob.exc.HTTPNotFound(
- _("Extension with alias %s does not exist") % id)
-
- return dict(extension=self._translate(ext))
-
- def delete(self, req, id):
- raise webob.exc.HTTPNotFound()
-
- def create(self, req):
- raise webob.exc.HTTPNotFound()
-
-
-class ExtensionMiddleware(wsgi.Middleware):
- """Extensions middleware for WSGI."""
-
- @classmethod
- def factory(cls, global_config, **local_config):
- """Paste factory."""
- def _factory(app):
- return cls(app, global_config, **local_config)
- return _factory
-
- def _action_ext_resources(self, application, ext_mgr, mapper):
- """Return a dict of ActionExtensionResource-s by collection."""
- action_resources = {}
- for action in ext_mgr.get_actions():
- if not action.collection in action_resources.keys():
- resource = ActionExtensionResource(application)
- mapper.connect("/%s/:(id)/action.:(format)" %
- action.collection,
- action='action',
- controller=resource,
- conditions=dict(method=['POST']))
- mapper.connect("/%s/:(id)/action" %
- action.collection,
- action='action',
- controller=resource,
- conditions=dict(method=['POST']))
- action_resources[action.collection] = resource
-
- return action_resources
-
- def _request_ext_resources(self, application, ext_mgr, mapper):
- """Returns a dict of RequestExtensionResource-s by collection."""
- request_ext_resources = {}
- for req_ext in ext_mgr.get_request_extensions():
- if not req_ext.key in request_ext_resources.keys():
- resource = RequestExtensionResource(application)
- mapper.connect(req_ext.url_route + '.:(format)',
- action='process',
- controller=resource,
- conditions=req_ext.conditions)
-
- mapper.connect(req_ext.url_route,
- action='process',
- controller=resource,
- conditions=req_ext.conditions)
- request_ext_resources[req_ext.key] = resource
-
- return request_ext_resources
-
- def __init__(self, application, config, ext_mgr=None):
- ext_mgr = ext_mgr or ExtensionManager(config['api_extensions_path'])
- mapper = routes.Mapper()
-
- # extended resources
- for resource_ext in ext_mgr.get_resources():
- LOG.debug(_('Extended resource: %s'), resource_ext.collection)
- controller_resource = wsgi.Resource(resource_ext.controller,
- resource_ext.deserializer,
- resource_ext.serializer)
- self._map_custom_collection_actions(resource_ext, mapper,
- controller_resource)
- kargs = dict(controller=controller_resource,
- collection=resource_ext.collection_actions,
- member=resource_ext.member_actions)
- if resource_ext.parent:
- kargs['parent_resource'] = resource_ext.parent
- mapper.resource(resource_ext.collection,
- resource_ext.collection, **kargs)
-
- # extended actions
- action_resources = self._action_ext_resources(application, ext_mgr,
- mapper)
- for action in ext_mgr.get_actions():
- LOG.debug(_('Extended action: %s'), action.action_name)
- resource = action_resources[action.collection]
- resource.add_action(action.action_name, action.handler)
-
- # extended requests
- req_controllers = self._request_ext_resources(application, ext_mgr,
- mapper)
- for request_ext in ext_mgr.get_request_extensions():
- LOG.debug(_('Extended request: %s'), request_ext.key)
- controller = req_controllers[request_ext.key]
- controller.add_handler(request_ext.handler)
-
- self._router = routes.middleware.RoutesMiddleware(self._dispatch,
- mapper)
-
- super(ExtensionMiddleware, self).__init__(application)
-
- def _map_custom_collection_actions(self, resource_ext, mapper,
- controller_resource):
- for action, method in resource_ext.collection_actions.iteritems():
- parent = resource_ext.parent
- conditions = dict(method=[method])
- path = "/%s/%s" % (resource_ext.collection, action)
-
- path_prefix = ""
- if parent:
- path_prefix = "/%s/{%s_id}" % (parent["collection_name"],
- parent["member_name"])
-
- with mapper.submapper(controller=controller_resource,
- action=action,
- path_prefix=path_prefix,
- conditions=conditions) as submap:
- submap.connect(path)
- submap.connect("%s.:(format)" % path)
-
- @webob.dec.wsgify(RequestClass=wsgi.Request)
- def __call__(self, req):
- """Route the incoming request with router."""
- req.environ['extended.app'] = self.application
- return self._router
-
- @staticmethod
- @webob.dec.wsgify(RequestClass=wsgi.Request)
- def _dispatch(req):
- """Dispatch the request.
-
- Returns the routed WSGI app's response or defers to the extended
- application.
-
- """
- match = req.environ['wsgiorg.routing_args'][1]
- if not match:
- return req.environ['extended.app']
- app = match['controller']
- return app
-
-
-class ExtensionManager(object):
- """Load extensions from the configured extension path.
-
- See nova/tests/api/openstack/extensions/foxinsocks/extension.py for an
- example extension implementation.
-
- """
-
- def __init__(self, path):
- LOG.debug(_('Initializing extension manager.'))
-
- self.path = path
- self.extensions = {}
- self._load_all_extensions()
-
- def get_resources(self):
- """Returns a list of ResourceExtension objects."""
- resources = []
- extension_resource = ExtensionsResource(self)
- res_ext = ResourceExtension('extensions',
- extension_resource,
- serializer=extension_resource.serializer)
- resources.append(res_ext)
- for alias, ext in self.extensions.iteritems():
- try:
- resources.extend(ext.get_resources())
- except AttributeError:
- # NOTE(dprince): Extension aren't required to have resource
- # extensions
- pass
- return resources
-
- def get_actions(self):
- """Returns a list of ActionExtension objects."""
- actions = []
- for alias, ext in self.extensions.iteritems():
- try:
- actions.extend(ext.get_actions())
- except AttributeError:
- # NOTE(dprince): Extension aren't required to have action
- # extensions
- pass
- return actions
-
- def get_request_extensions(self):
- """Returns a list of RequestExtension objects."""
- request_exts = []
- for alias, ext in self.extensions.iteritems():
- try:
- request_exts.extend(ext.get_request_extensions())
- except AttributeError:
- # NOTE(dprince): Extension aren't required to have request
- # extensions
- pass
- return request_exts
-
- def _check_extension(self, extension):
- """Checks for required methods in extension objects."""
- try:
- LOG.debug(_('Ext name: %s'), extension.get_name())
- LOG.debug(_('Ext alias: %s'), extension.get_alias())
- LOG.debug(_('Ext description: %s'), extension.get_description())
- LOG.debug(_('Ext namespace: %s'), extension.get_namespace())
- LOG.debug(_('Ext updated: %s'), extension.get_updated())
- except AttributeError as ex:
- LOG.exception(_("Exception loading extension: %s"), unicode(ex))
- return False
- return True
-
- def _load_all_extensions(self):
- """Load extensions from the configured path.
-
- Load extensions from the configured path. The extension name is
- constructed from the module_name. If your extension module was named
- widgets.py the extension class within that module should be
- 'Widgets'.
-
- In addition, extensions are loaded from the 'contrib' directory.
-
- See nova/tests/api/openstack/extensions/foxinsocks.py for an example
- extension implementation.
-
- """
- if os.path.exists(self.path):
- self._load_all_extensions_from_path(self.path)
-
- contrib_path = os.path.join(os.path.dirname(__file__), "contrib")
- if os.path.exists(contrib_path):
- self._load_all_extensions_from_path(contrib_path)
-
- def _load_all_extensions_from_path(self, path):
- for f in os.listdir(path):
- LOG.debug(_('Loading extension file: %s'), f)
- mod_name, file_ext = os.path.splitext(os.path.split(f)[-1])
- ext_path = os.path.join(path, f)
- if file_ext.lower() == '.py' and not mod_name.startswith('_'):
- mod = imp.load_source(mod_name, ext_path)
- ext_name = mod_name[0].upper() + mod_name[1:]
- new_ext_class = getattr(mod, ext_name, None)
- if not new_ext_class:
- LOG.warn(_('Did not find expected name '
- '"%(ext_name)s" in %(file)s'),
- {'ext_name': ext_name,
- 'file': ext_path})
- continue
- new_ext = new_ext_class()
- self.add_extension(new_ext)
-
- def add_extension(self, ext):
- # Do nothing if the extension doesn't check out
- if not self._check_extension(ext):
- return
-
- alias = ext.get_alias()
- LOG.debug(_('Loaded extension: %s'), alias)
-
- if alias in self.extensions:
- raise exception.Error("Found duplicate extension: %s" % alias)
- self.extensions[alias] = ext
-
-
-class RequestExtension(object):
- """Extend requests and responses of core nova OpenStack API resources.
-
- Provide a way to add data to responses and handle custom request data
- that is sent to core nova OpenStack API controllers.
-
- """
- def __init__(self, method, url_route, handler):
- self.url_route = url_route
- self.handler = handler
- self.conditions = dict(method=[method])
- self.key = "%s-%s" % (method, url_route)
-
-
-class ActionExtension(object):
- """Add custom actions to core nova OpenStack API resources."""
-
- def __init__(self, collection, action_name, handler):
- self.collection = collection
- self.action_name = action_name
- self.handler = handler
-
-
-class ResourceExtension(object):
- """Add top level resources to the OpenStack API in nova."""
-
- def __init__(self, collection, controller, parent=None,
- collection_actions=None, member_actions=None,
- deserializer=None, serializer=None):
- if not collection_actions:
- collection_actions = {}
- if not member_actions:
- member_actions = {}
- self.collection = collection
- self.controller = controller
- self.parent = parent
- self.collection_actions = collection_actions
- self.member_actions = member_actions
- self.deserializer = deserializer
- self.serializer = serializer
-
-
-class ExtensionsXMLSerializer(wsgi.XMLDictSerializer):
-
- def __init__(self):
- self.nsmap = {None: DEFAULT_XMLNS, 'atom': XMLNS_ATOM}
-
- def show(self, ext_dict):
- ext = etree.Element('extension', nsmap=self.nsmap)
- self._populate_ext(ext, ext_dict['extension'])
- return self._to_xml(ext)
-
- def index(self, exts_dict):
- exts = etree.Element('extensions', nsmap=self.nsmap)
- for ext_dict in exts_dict['extensions']:
- ext = etree.SubElement(exts, 'extension')
- self._populate_ext(ext, ext_dict)
- return self._to_xml(exts)
-
- def _populate_ext(self, ext_elem, ext_dict):
- """Populate an extension xml element from a dict."""
-
- ext_elem.set('name', ext_dict['name'])
- ext_elem.set('namespace', ext_dict['namespace'])
- ext_elem.set('alias', ext_dict['alias'])
- ext_elem.set('updated', ext_dict['updated'])
- desc = etree.Element('description')
- desc.text = ext_dict['description']
- ext_elem.append(desc)
- for link in ext_dict.get('links', []):
- elem = etree.SubElement(ext_elem, '{%s}link' % XMLNS_ATOM)
- elem.set('rel', link['rel'])
- elem.set('href', link['href'])
- elem.set('type', link['type'])
- return ext_elem
-
- def _to_xml(self, root):
- """Convert the xml object to an xml string."""
-
- return etree.tostring(root, encoding='UTF-8')