def load_extension(self, ext_factory): """Execute an extension factory. Loads an extension. The 'ext_factory' is the name of a callable that will be imported and called with one argument--the extension manager. The factory callable is expected to call the register() method at least once. """ LOG.debug("Loading extension %s", ext_factory) if isinstance(ext_factory, six.string_types): if ext_factory.startswith('fastrunner.api.openstack.compute.contrib'): LOG.warn(_LW("The legacy v2 API module already moved into" "'fastrunner.api.openstack.compute.legacy_v2.contrib'. " "Use new path instead of old path %s"), ext_factory) ext_factory = ext_factory.replace('contrib', 'legacy_v2.contrib') # Load the factory factory = importutils.import_class(ext_factory) else: factory = ext_factory # Call it LOG.debug("Calling extension factory %s", ext_factory) factory(self)
def _register_controllers(self, ext): """Register controllers defined by the extensions Extensions define what resources they want to add through a get_controller_extensions function """ handler = ext.obj LOG.debug("Running _register_controllers on %s", ext.obj) for extension in handler.get_controller_extensions(): ext_name = extension.extension.name collection = extension.collection controller = extension.controller if collection not in self.resources: LOG.warning( _LW('Extension %(ext_name)s: Cannot extend ' 'resource %(collection)s: No such resource'), { 'ext_name': ext_name, 'collection': collection }) continue LOG.debug( 'Extension %(ext_name)s extending resource: ' '%(collection)s', { 'ext_name': ext_name, 'collection': collection }) resource = self.resources[collection] resource.register_actions(controller) resource.register_extensions(controller)
def _load_extensions(self): """Load extensions specified on the command line.""" extensions = list(self.cls_list) for ext_factory in extensions: try: self.load_extension(ext_factory) except Exception as exc: LOG.warning(_LW('Failed to load extension %(ext_factory)s: ' '%(exc)s'), {'ext_factory': ext_factory, 'exc': exc})
def _setup_extensions(self, ext_mgr): for extension in ext_mgr.get_controller_extensions(): collection = extension.collection controller = extension.controller msg_format_dict = { 'collection': collection, 'ext_name': extension.extension.name } if collection not in self.resources: LOG.warning( _LW('Extension %(ext_name)s: Cannot extend ' 'resource %(collection)s: No such resource'), msg_format_dict) continue LOG.debug( 'Extension %(ext_name)s extended resource: ' '%(collection)s', msg_format_dict) resource = self.resources[collection] resource.register_actions(controller) resource.register_extensions(controller)
def load_standard_extensions(ext_mgr, logger, path, package, ext_list=None): """Registers all standard API extensions.""" # Walk through all the modules in our directory... our_dir = path[0] for dirpath, dirnames, filenames in os.walk(our_dir): # Compute the relative package name from the dirpath relpath = os.path.relpath(dirpath, our_dir) if relpath == '.': relpkg = '' else: relpkg = '.%s' % '.'.join(relpath.split(os.sep)) # Now, consider each file in turn, only considering .py files for fname in filenames: root, ext = os.path.splitext(fname) # Skip __init__ and anything that's not .py if ext != '.py' or root == '__init__': continue # Try loading it classname = "%s%s" % (root[0].upper(), root[1:]) classpath = ("%s%s.%s.%s" % (package, relpkg, root, classname)) if ext_list is not None and classname not in ext_list: logger.debug("Skipping extension: %s" % classpath) continue try: ext_mgr.load_extension(classpath) except Exception as exc: logger.warn(_LW('Failed to load extension %(classpath)s: ' '%(exc)s'), {'classpath': classpath, 'exc': exc}) # Now, let's consider any subdirectories we may have... subdirs = [] for dname in dirnames: # Skip it if it does not have __init__.py if not os.path.exists(os.path.join(dirpath, dname, '__init__.py')): continue # If it has extension(), delegate... ext_name = "%s%s.%s.extension" % (package, relpkg, dname) try: ext = importutils.import_class(ext_name) except ImportError: # extension() doesn't exist on it, so we'll explore # the directory for ourselves subdirs.append(dname) else: try: ext(ext_mgr) except Exception as exc: logger.warn(_LW('Failed to load extension %(ext_name)s:' '%(exc)s'), {'ext_name': ext_name, 'exc': exc}) # Update the list of directories we'll explore... # using os.walk 'the caller can modify the dirnames list in-place, # and walk() will only recurse into the subdirectories whose names # remain in dirnames' # https://docs.python.org/2/library/os.html#os.walk dirnames[:] = subdirs
def __init__(self, init_only=None, v3mode=False): # TODO(cyeoh): bp v3-api-extension-framework. Currently load # all extensions but eventually should be able to exclude # based on a config file # TODO(oomichi): We can remove v3mode argument after moving all v3 APIs # to v2.1. def _check_load_extension(ext): if (self.init_only is None or ext.obj.alias in self.init_only) and isinstance( ext.obj, extensions.V21APIExtensionBase): return self._register_extension(ext) return False if not CONF.osapi_v21.enabled: LOG.info(_LI("V2.1 API has been disabled by configuration")) LOG.warning(_LW("In the M release you must run the v2.1 API.")) return if (CONF.osapi_v21.extensions_blacklist or CONF.osapi_v21.extensions_whitelist): LOG.warning( _LW('In the M release you must run all of the API. ' 'The concept of API extensions will be removed from ' 'the codebase to ensure there is a single Compute API.')) self.init_only = init_only LOG.debug("v21 API Extension Blacklist: %s", CONF.osapi_v21.extensions_blacklist) LOG.debug("v21 API Extension Whitelist: %s", CONF.osapi_v21.extensions_whitelist) in_blacklist_and_whitelist = set( CONF.osapi_v21.extensions_whitelist).intersection( CONF.osapi_v21.extensions_blacklist) if len(in_blacklist_and_whitelist) != 0: LOG.warning(_LW("Extensions in both blacklist and whitelist: %s"), list(in_blacklist_and_whitelist)) self.api_extension_manager = stevedore.enabled.EnabledExtensionManager( namespace=self.api_extension_namespace(), check_func=_check_load_extension, invoke_on_load=True, invoke_kwds={"extension_info": self.loaded_extension_info}) if v3mode: mapper = PlainMapper() else: mapper = ProjectMapper() self.resources = {} # NOTE(cyeoh) Core API support is rewritten as extensions # but conceptually still have core if list(self.api_extension_manager): # NOTE(cyeoh): Stevedore raises an exception if there are # no plugins detected. I wonder if this is a bug. self._register_resources_check_inherits(mapper) self.api_extension_manager.map(self._register_controllers) missing_core_extensions = self.get_missing_core_extensions( self.loaded_extension_info.get_extensions().keys()) #if not self.init_only and missing_core_extensions: # LOG.critical(_LC("Missing core API extensions: %s"), # missing_core_extensions) # raise exception.CoreAPIMissing( # missing_apis=missing_core_extensions) LOG.info(_LI("Loaded extensions: %s"), sorted(self.loaded_extension_info.get_extensions().keys())) super(APIRouterV21, self).__init__(mapper)
def __init__(self, user_id=None, project_id=None, is_admin=None, read_deleted="no", roles=None, remote_address=None, timestamp=None, request_id=None, auth_token=None, overwrite=True, quota_class=None, user_name=None, project_name=None, service_catalog=None, instance_lock_checked=False, user_auth_plugin=None, **kwargs): """:param read_deleted: 'no' indicates deleted records are hidden, 'yes' indicates deleted records are visible, 'only' indicates that *only* deleted records are visible. :param overwrite: Set to False to ensure that the greenthread local copy of the index is not overwritten. :param user_auth_plugin: The auth plugin for the current request's authentication data. :param kwargs: Extra arguments that might be present, but we ignore because they possibly came in from older rpc messages. """ user = kwargs.pop('user', None) tenant = kwargs.pop('tenant', None) super(RequestContext, self).__init__(auth_token=auth_token, user=user_id or user, tenant=project_id or tenant, domain=kwargs.pop('domain', None), user_domain=kwargs.pop('user_domain', None), project_domain=kwargs.pop('project_domain', None), is_admin=is_admin, read_only=kwargs.pop('read_only', False), show_deleted=kwargs.pop('show_deleted', False), request_id=request_id, resource_uuid=kwargs.pop('resource_uuid', None), overwrite=overwrite) # oslo_context's RequestContext.to_dict() generates this field, we can # safely ignore this as we don't use it. kwargs.pop('user_identity', None) if kwargs: LOG.warning(_LW('Arguments dropped when creating context: %s'), str(kwargs)) # FIXME(dims): user_id and project_id duplicate information that is # already present in the oslo_context's RequestContext. We need to # get rid of them. self.user_id = user_id self.project_id = project_id self.roles = roles or [] self.read_deleted = read_deleted self.remote_address = remote_address if not timestamp: timestamp = timeutils.utcnow() if isinstance(timestamp, six.string_types): timestamp = timeutils.parse_strtime(timestamp) self.timestamp = timestamp if service_catalog: # Only include required parts of service_catalog self.service_catalog = [ s for s in service_catalog if s.get('type') in ('volume', 'volumev2', 'key-manager') ] else: # if list is empty or none self.service_catalog = [] self.instance_lock_checked = instance_lock_checked # NOTE(markmc): this attribute is currently only used by the # rs_limits turnstile pre-processor. # See https://lists.launchpad.net/openstack/msg12200.html self.quota_class = quota_class self.user_name = user_name self.project_name = project_name self.is_admin = is_admin # NOTE(dheeraj): The following attribute is used by cellsv2 to store # connection information for connecting to the target cell. # It is only manipulated using the target_cell contextmanager # provided by this module self.db_connection = None self.user_auth_plugin = user_auth_plugin if self.is_admin is None: self.is_admin = policy.check_is_admin(self)