Ejemplo n.º 1
0
            def register_event_callbacks(self):
                # NOTE(morganfainberg): A provider who has an implicit
                # dependency on other providers may utilize the event callback
                # mechanism to react to any changes in those providers. This is
                # performed at the .provider() mechanism so that we can ensure
                # that the callback is only ever called once and guaranteed
                # to be on the properly configured and instantiated backend.
                if not hasattr(self, 'event_callbacks'):
                    return

                if not isinstance(self.event_callbacks, dict):
                    msg = _('event_callbacks must be a dict')
                    raise ValueError(msg)

                for event in self.event_callbacks:
                    if not isinstance(self.event_callbacks[event], dict):
                        msg = _('event_callbacks[%s] must be a dict') % event
                        raise ValueError(msg)
                    for resource_type in self.event_callbacks[event]:
                        # Make sure we register the provider for each event it
                        # cares to call back.
                        callbacks = self.event_callbacks[event][resource_type]
                        if not callbacks:
                            continue
                        if not hasattr(callbacks, '__iter__'):
                            # ensure the callback information is a list
                            # allowing multiple callbacks to exist
                            callbacks = [callbacks]
                        notifications.register_event_callback(event,
                                                              resource_type,
                                                              callbacks)
Ejemplo n.º 2
0
 def wrapper(*args, **kwargs):
     try:
         return method(*args, **kwargs)
     except db_exception.DBDuplicateEntry as e:
         # LOG the exception for debug purposes, do not send the
         # exception details out with the raised Conflict exception
         # as it can contain raw SQL.
         LOG.debug(_conflict_msg, {
             'conflict_type': conflict_type,
             'details': six.text_type(e)
         })
         raise exception.Conflict(type=conflict_type,
                                  details=_('Duplicate Entry'))
     except db_exception.DBError as e:
         # TODO(blk-u): inspecting inner_exception breaks encapsulation;
         # oslo_db should provide exception we need.
         if isinstance(e.inner_exception, IntegrityError):
             # LOG the exception for debug purposes, do not send the
             # exception details out with the raised Conflict exception
             # as it can contain raw SQL.
             LOG.debug(
                 _conflict_msg, {
                     'conflict_type': conflict_type,
                     'details': six.text_type(e)
                 })
             # NOTE(morganfainberg): This is really a case where the SQL
             # failed to store the data. This is not something that the
             # user has done wrong. Example would be a ForeignKey is
             # missing; the code that is executed before reaching the
             # SQL writing to the DB should catch the issue.
             raise exception.UnexpectedError(
                 _('An unexpected error occurred when trying to '
                   'store %s') % conflict_type)
         raise
Ejemplo n.º 3
0
class UnexpectedError(SecurityError):
    """Avoids exposing details of failures, unless in debug mode."""
    _message_format = _("An unexpected error prevented the server "
                        "from fulfilling your request.")

    debug_message_format = _("An unexpected error prevented the server "
                             "from fulfilling your request: %(exception)s")

    @property
    def message_format(self):
        """Return the generic message format string unless debug is enabled."""
        if CONF.debug:
            return self.debug_message_format
        return self._message_format

    def _build_message(self, message, **kwargs):
        if CONF.debug and 'exception' not in kwargs:
            # Ensure that exception has a value to be extra defensive for
            # substitutions and make sure the exception doesn't raise an
            # exception.
            kwargs['exception'] = ''
        return super(UnexpectedError, self)._build_message(message, **kwargs)

    code = 500
    title = 'Internal Server Error'
Ejemplo n.º 4
0
def check_length(property_name, value, min_length=1, max_length=64):
    if len(value) < min_length:
        if min_length == 1:
            msg = _("%s cannot be empty.") % property_name
        else:
            msg = (_("%(property_name)s cannot be less than "
                     "%(min_length)s characters.") %
                   dict(property_name=property_name, min_length=min_length))
        raise exception.ValidationError(msg)
    if len(value) > max_length:
        msg = (_("%(property_name)s should not be greater than "
                 "%(max_length)s characters.") %
               dict(property_name=property_name, max_length=max_length))

        raise exception.ValidationError(msg)
Ejemplo n.º 5
0
 def _ssl_cert_req_type(self, req_type):
     try:
         import ssl
     except ImportError:
         raise exception.ValidationError(_('no ssl support available'))
     req_type = req_type.upper()
     try:
         return {
             'NONE': ssl.CERT_NONE,
             'OPTIONAL': ssl.CERT_OPTIONAL,
             'REQUIRED': ssl.CERT_REQUIRED
         }[req_type]
     except KeyError:
         msg = _('Invalid ssl_cert_reqs value of %s, must be one of '
                 '"NONE", "OPTIONAL", "REQUIRED"') % (req_type)
         raise exception.ValidationError(message=msg)
Ejemplo n.º 6
0
class ValidationTimeStampError(Error):
    message_format = _("Timestamp not in expected format."
                       " The server could not comply with the request"
                       " since it is either malformed or otherwise"
                       " incorrect. The client is assumed to be in error.")
    code = 400
    title = 'Bad Request'
Ejemplo n.º 7
0
class ValidationError(Error):
    message_format = _("Expecting to find %(attribute)s in %(target)s -"
                       " the server could not comply with the request"
                       " since it is either malformed or otherwise"
                       " incorrect. The client is assumed to be in error.")
    code = 400
    title = 'Bad Request'
Ejemplo n.º 8
0
def check_type(property_name, value, expected_type, display_expected_type):
    if not isinstance(value, expected_type):
        msg = (_("%(property_name)s is not a "
                 "%(display_expected_type)s") %
               dict(property_name=property_name,
                    display_expected_type=display_expected_type))
        raise exception.ValidationError(msg)
Ejemplo n.º 9
0
 def __init__(self, mod_name, path):
     super(MigrationNotProvided, self).__init__(
         _("%(mod_name)s doesn't provide database migrations. The migration"
           " repository path at %(path)s doesn't exist or isn't a directory."
           ) % {
               'mod_name': mod_name,
               'path': path
           })
Ejemplo n.º 10
0
    def _require_attribute(self, ref, attribute):
        """Ensures the reference contains the specified attribute.

        Raise a ValidationError if the given attribute is not present
        """
        if self._attribute_is_empty(ref, attribute):
            msg = _('%s field is required and cannot be empty') % attribute
            raise exception.ValidationError(message=msg)
Ejemplo n.º 11
0
class ValidationSizeError(Error):
    message_format = _("Request attribute %(attribute)s must be"
                       " less than or equal to %(size)i. The server"
                       " could not comply with the request because"
                       " the attribute size is invalid (too large)."
                       " The client is assumed to be in error.")
    code = 400
    title = 'Bad Request'
Ejemplo n.º 12
0
 def _build_message(self, message, **kwargs):
     """Only returns detailed messages in debug mode."""
     if CONF.debug:
         return _('%(message)s %(amendment)s') % {
             'message': message or self.message_format % kwargs,
             'amendment': self.amendment
         }
     else:
         return self.message_format % kwargs
Ejemplo n.º 13
0
def get_blob_from_credential(credential):
    try:
        blob = jsonutils.loads(credential.blob)
    except (ValueError, TypeError):
        raise exception.ValidationError(
            message=_('Invalid blob in credential'))
    if not blob or not isinstance(blob, dict):
        raise exception.ValidationError(attribute='blob', target='credential')
    return blob
Ejemplo n.º 14
0
    def _require_attributes(self, ref, attrs):
        """Ensures the reference contains the specified attributes.

        Raise a ValidationError if any of the given attributes is not present
        """
        missing_attrs = [attribute for attribute in attrs
                         if self._attribute_is_empty(ref, attribute)]

        if missing_attrs:
            msg = _('%s field(s) cannot be empty') % ', '.join(missing_attrs)
            raise exception.ValidationError(message=msg)
Ejemplo n.º 15
0
    def update_resource_data(cls, resource_data, status):
        if status is cls.STABLE:
            # We currently do not add a status if the resource is stable, the
            # absence of the status property can be taken as meaning that the
            # resource is stable.
            return
        if status is cls.DEPRECATED or status is cls.EXPERIMENTAL:
            resource_data['hints'] = {'status': status}
            return

        raise exception.Error(message=_(
            'Unexpected status requested for JSON Home response, %s') % status)
Ejemplo n.º 16
0
def get_db_version(extension=None):
    if not extension:
        return migration.db_version(sql.get_engine(), find_migrate_repo(),
                                    migrate_repo.DB_INIT_VERSION)

    try:
        package_name = '.'.join((contrib.__name__, extension))
        package = importutils.import_module(package_name)
    except ImportError:
        raise ImportError(_("%s extension does not exist.") % package_name)

    return migration.db_version(sql.get_engine(), find_migrate_repo(package),
                                0)
Ejemplo n.º 17
0
def base64_is_padded(text, pad='='):
    """Test if the text is base64 padded.

    The input text must be in a base64 alphabet. The pad must be a
    single character. If the text has been percent-encoded (e.g. pad
    is the string '%3D') you must convert the text back to a base64
    alphabet (e.g. if percent-encoded use the function
    base64url_percent_decode()).

    :param text: text containing ONLY characters in a base64 alphabet
    :type text: string
    :param pad: pad character (must be single character) (default: '=')
    :type pad: string
    :returns: bool -- True if padded, False otherwise
    :raises: ValueError, InvalidBase64Error
    """

    _check_padding_length(pad)

    text_len = len(text)
    if text_len > 0 and text_len % 4 == 0:
        pad_index = text.find(pad)
        if pad_index >= 0 and pad_index < text_len - 2:
            raise InvalidBase64Error(
                _('text is multiple of 4, '
                  'but pad "%s" occurs before '
                  '2nd to last char') % pad)
        if pad_index == text_len - 2 and text[-1] != pad:
            raise InvalidBase64Error(
                _('text is multiple of 4, '
                  'but pad "%s" occurs before '
                  'non-pad last char') % pad)
        return True

    if text.find(pad) >= 0:
        raise InvalidBase64Error(
            _('text is not a multiple of 4, '
              'but contains pad "%s"') % pad)
    return False
Ejemplo n.º 18
0
class SecurityError(Error):
    """Avoids exposing details of security failures, unless in debug mode."""
    amendment = _('(Disable debug mode to suppress these details.)')

    def _build_message(self, message, **kwargs):
        """Only returns detailed messages in debug mode."""
        if CONF.debug:
            return _('%(message)s %(amendment)s') % {
                'message': message or self.message_format % kwargs,
                'amendment': self.amendment
            }
        else:
            return self.message_format % kwargs
Ejemplo n.º 19
0
def register_event_callback(event, resource_type, callbacks):
    """Register each callback with the event.

    :param event: Action being registered
    :type event: sidserver.notifications.ACTIONS
    :param resource_type: Type of resource being operated on
    :type resource_type: str
    :param callbacks: Callback items to be registered with event
    :type callbacks: list
    :raises ValueError: If event is not a valid ACTION
    :raises TypeError: If callback is not callable
    """
    if event not in ACTIONS:
        raise ValueError(
            _('%(event)s is not a valid notification event, must '
              'be one of: %(actions)s') % {
                  'event': event,
                  'actions': ', '.join(ACTIONS)
              })

    if not hasattr(callbacks, '__iter__'):
        callbacks = [callbacks]

    for callback in callbacks:
        if not callable(callback):
            msg = _('Method not callable: %s') % callback
            LOG.error(msg)
            raise TypeError(msg)
        _SUBSCRIBERS.setdefault(event, {}).setdefault(resource_type, set())
        _SUBSCRIBERS[event][resource_type].add(callback)

        if LOG.logger.getEffectiveLevel() <= logging.DEBUG:
            # Do this only if its going to appear in the logs.
            msg = 'Callback: `%(callback)s` subscribed to event `%(event)s`.'
            callback_info = _get_callback_info(callback)
            callback_str = '.'.join(i for i in callback_info if i is not None)
            event_str = '.'.join(['identity', resource_type, event])
            LOG.debug(msg, {'callback': callback_str, 'event': event_str})
Ejemplo n.º 20
0
def _sync_extension_repo(extension, version):
    init_version = 0
    engine = sql.get_engine()

    try:
        package_name = '.'.join((contrib.__name__, extension))
        package = importutils.import_module(package_name)
    except ImportError:
        raise ImportError(_("%s extension does not exist.") % package_name)
    try:
        abs_path = find_migrate_repo(package)
        try:
            migration.db_version_control(sql.get_engine(), abs_path)
        # Register the repo with the version control API
        # If it already knows about the repo, it will throw
        # an exception that we can safely ignore
        except exceptions.DatabaseAlreadyControlledError:
            pass
    except exception.MigrationNotProvided as e:
        print(e)
        sys.exit(1)

    _assert_not_schema_downgrade(extension=extension, version=version)

    try:
        migration.db_sync(engine,
                          abs_path,
                          version=version,
                          init_version=init_version)
    except ValueError:
        # NOTE(marco-fargetta): ValueError is raised from the sanity check (
        # verifies that tables are utf8 under mysql). The federation_protocol,
        # identity_provider and mapping tables were not initially built with
        # InnoDB and utf8 as part of the table arguments when the migration
        # was initially created. Bug #1426334 is a scenario where the deployer
        # can get wedged, unable to upgrade or downgrade.
        # This is a workaround to "fix" those tables if we're under MySQL and
        # the version is before the 6 because before the tables were introduced
        # before and patched when migration 5 was available
        if engine.name == 'mysql' and \
           int(six.text_type(get_db_version(extension))) < 6:
            _fix_federation_tables(engine)
            # The migration is applied again after the fix
            migration.db_sync(engine,
                              abs_path,
                              version=version,
                              init_version=init_version)
        else:
            raise
Ejemplo n.º 21
0
 def pem_type(self, pem_type):
     if pem_type is None:
         self._pem_type = None
         self._pem_header = None
     else:
         pem_header = PEM_TYPE_TO_HEADER.get(pem_type)
         if pem_header is None:
             raise ValueError(
                 _('unknown pem_type "%(pem_type)s", '
                   'valid types are: %(valid_pem_types)s') % {
                       'pem_type': pem_type,
                       'valid_pem_types': ', '.join(pem_types)
                   })
         self._pem_type = pem_type
         self._pem_header = pem_header
Ejemplo n.º 22
0
def serve(*servers):
    logging.warning(
        _('Running sidserver via eventlet is deprecated as of Kilo '
          'in favor of running in a WSGI server (e.g. mod_wsgi). '
          'Support for sidserver under eventlet will be removed in '
          'the "M"-Release.'))
    if max([server[1].workers for server in servers]) > 1:
        launcher = service.ProcessLauncher()
    else:
        launcher = service.ServiceLauncher()

    for name, server in servers:
        try:
            server.launch_with(launcher)
        except socket.error:
            logging.exception(
                _('Failed to start the %(name)s server') % {'name': name})
            raise

    # notify calling process we are ready to serve
    systemd.notify_once()

    for name, server in servers:
        launcher.wait()
Ejemplo n.º 23
0
    def _dispatch(req):
        """Dispatch the request to the appropriate controller.

        Called by self._router after matching the incoming request to a route
        and putting the information into req.environ.  Either returns 404
        or the routed WSGI app's response.

        """
        match = req.environ['wsgiorg.routing_args'][1]
        if not match:
            msg = _('The resource could not be found.')
            return render_exception(exception.NotFound(msg),
                                    request=req,
                                    user_locale=best_match_language(req))
        app = match['controller']
        return app
Ejemplo n.º 24
0
def configure_cache_region(region):
    """Configure a cache region.

    :param region: optional CacheRegion object, if not provided a new region
                   will be instantiated
    :raises: exception.ValidationError
    :returns: dogpile.cache.CacheRegion
    """
    if not isinstance(region, dogpile.cache.CacheRegion):
        raise exception.ValidationError(
            _('region not type dogpile.cache.CacheRegion'))

    if not region.is_configured:
        # NOTE(morganfainberg): this is how you tell if a region is configured.
        # There is a request logged with dogpile.cache upstream to make this
        # easier / less ugly.

        config_dict = build_cache_config()
        region.configure_from_config(config_dict,
                                     '%s.' % CONF.cache.config_prefix)

        if CONF.cache.debug_cache_backend:
            region.wrap(DebugProxy)

        # NOTE(morganfainberg): if the backend requests the use of a
        # key_mangler, we should respect that key_mangler function.  If a
        # key_mangler is not defined by the backend, use the sha1_mangle_key
        # mangler provided by dogpile.cache. This ensures we always use a fixed
        # size cache-key.
        if region.key_mangler is None:
            region.key_mangler = util.sha1_mangle_key

        for class_path in CONF.cache.proxies:
            # NOTE(morganfainberg): if we have any proxy wrappers, we should
            # ensure they are added to the cache region's backend.  Since
            # configure_from_config doesn't handle the wrap argument, we need
            # to manually add the Proxies. For information on how the
            # ProxyBackends work, see the dogpile.cache documents on
            # "changing-backend-behavior"
            cls = importutils.import_class(class_path)
            LOG.debug("Adding cache-proxy '%s' to backend.", class_path)
            region.wrap(cls)

    return region
Ejemplo n.º 25
0
    def pem_header(self, pem_header):
        if pem_header is None:
            self._pem_type = None
            self._pem_header = None
        else:
            pem_type = PEM_HEADER_TO_TYPE.get(pem_header)
            if pem_type is None:
                raise ValueError(
                    _('unknown pem header "%(pem_header)s", '
                      'valid headers are: '
                      '%(valid_pem_headers)s') % {
                          'pem_header':
                          pem_header,
                          'valid_pem_headers':
                          ', '.join("'%s'" % [x for x in pem_headers])
                      })

            self._pem_type = pem_type
            self._pem_header = pem_header
Ejemplo n.º 26
0
def base64url_percent_encode(text):
    """Percent-encode base64url padding.

    The input text should only contain base64url alphabet
    characters. Any non-base64url alphabet characters will also be
    subject to percent-encoding.

    :param text: text containing ONLY characters in the base64url alphabet
    :type text: string
    :returns: string -- percent-encoded base64url text
    :raises: InvalidBase64Error
    """

    if len(text) % 4 != 0:
        raise InvalidBase64Error(
            _('padded base64url text must be '
              'multiple of 4 characters'))

    return urllib.parse.quote(text)
Ejemplo n.º 27
0
def base64url_percent_decode(text):
    """Percent-decode base64url padding.

    The input text should only contain base64url alphabet
    characters and the percent-encoded pad character. Any other
    percent-encoded characters will be subject to percent-decoding.

    :param text: base64url alphabet text
    :type text: string
    :returns: string -- percent-decoded base64url text
    """

    decoded_text = urllib.parse.unquote(text)

    if len(decoded_text) % 4 != 0:
        raise InvalidBase64Error(
            _('padded base64url text must be '
              'multiple of 4 characters'))

    return decoded_text
Ejemplo n.º 28
0
 def acquire(self):
     self._debug_logger('Acquiring connection')
     try:
         conn = self.get(timeout=self._connection_get_timeout)
     except queue.Empty:
         raise exception.UnexpectedError(
             _('Unable to get a connection from pool id %(id)s after '
               '%(seconds)s seconds.') %
             {'id': id(self), 'seconds': self._connection_get_timeout})
     self._debug_logger('Acquired connection %s', id(conn))
     try:
         yield conn
     finally:
         self._debug_logger('Releasing connection %s', id(conn))
         self._drop_expired_connections()
         try:
             # super() cannot be used here because Queue in stdlib is an
             # old-style class
             queue.Queue.put(self, conn, block=False)
         except queue.Full:
             self._debug_logger('Reaping exceeding connection %s', id(conn))
             self._destroy_connection(conn)
Ejemplo n.º 29
0
    def wrapper(self, hints, *args, **kwargs):
        if not hasattr(hints, 'limit'):
            raise exception.UnexpectedError(
                _('Cannot truncate a driver call without hints list as '
                  'first parameter after self '))

        if hints.limit is None:
            return f(self, hints, *args, **kwargs)

        # A limit is set, so ask for one more entry than we need
        list_limit = hints.limit['limit']
        hints.set_limit(list_limit + 1)
        ref_list = f(self, hints, *args, **kwargs)

        # If we got more than the original limit then trim back the list and
        # mark it truncated.  In both cases, make sure we set the limit back
        # to its original value.
        if len(ref_list) > list_limit:
            hints.set_limit(list_limit, truncated=True)
            return ref_list[:list_limit]
        else:
            hints.set_limit(list_limit)
            return ref_list
Ejemplo n.º 30
0
 def __init__(self, name, targets):
     msg = _('Unregistered dependency: %(name)s for %(targets)s') % {
         'name': name, 'targets': targets}
     super(UnresolvableDependencyException, self).__init__(msg)