示例#1
0
class ClimateException(Exception):
    """Base Climate Exception.

    To correctly use this class, inherit from it and define
    a 'msg_fmt' and 'code' properties.
    """
    msg_fmt = _("An unknown exception occurred")
    code = 500

    def __init__(self, message=None, **kwargs):
        self.kwargs = kwargs

        if 'code' not in self.kwargs:
            self.kwargs['code'] = self.code

        if not message:
            try:
                message = self.msg_fmt % kwargs
            except KeyError:
                # kwargs doesn't match a variable in the message
                # log the issue and the kwargs
                LOG.exception(_('Exception in string format operation'))
                for name, value in kwargs.iteritems():
                    LOG.error("%s: %s" % (name, value))

                message = self.msg_fmt

        super(ClimateException, self).__init__(message)
示例#2
0
def request_data():
    """Method called to process POST and PUT REST methods."""
    if hasattr(flask.request, 'parsed_data'):
        return flask.request.parsed_data

    if not flask.request.content_length > 0:
        LOG.debug("Empty body provided in request")
        return dict()

    if flask.request.file_upload:
        return flask.request.data

    deserializer = None
    content_type = flask.request.mimetype
    if not content_type or content_type in RT_JSON:
        deserializer = jsonutils
    else:
        abort_and_log(400,
                      _("Content type '%s' isn't supported") % content_type)
        return

    # parsed request data to avoid unwanted re-parsings
    parsed_data = deserializer.loads(flask.request.data)
    flask.request.parsed_data = parsed_data

    return flask.request.parsed_data
示例#3
0
    def _event(self):
        """Tries to commit event.

        If there is an event in Climate DB to be done, do it and change its
        status to 'DONE'.
        """
        LOG.debug('Trying to get event from DB.')
        event = db_api.event_get_first_sorted_by_filters(
            sort_key='time', sort_dir='asc', filters={'status': 'UNDONE'})

        if not event:
            return

        if event['time'] < datetime.datetime.utcnow():
            db_api.event_update(event['id'], {'status': 'IN_PROGRESS'})
            event_type = event['event_type']
            event_fn = getattr(self, event_type, None)
            if event_fn is None:
                raise exceptions.EventError(error='Event type %s is not '
                                            'supported' % event_type)
            try:
                eventlet.spawn_n(service_utils.with_empty_context(event_fn),
                                 event['lease_id'], event['id'])
                lease = db_api.lease_get(event['lease_id'])
                with trusts.create_ctx_from_trust(lease['trust_id']) as ctx:
                    self._send_notification(lease,
                                            ctx,
                                            events=['event.%s' % event_type])
            except Exception:
                db_api.event_update(event['id'], {'status': 'ERROR'})
                LOG.exception(_('Error occurred while event handling.'))
示例#4
0
def setup_db():
    try:
        engine = db_session.EngineFacade(cfg.CONF.database.connection,
                                         sqlite_fk=True).get_engine()
        models.Lease.metadata.create_all(engine)
    except sa.exc.OperationalError as e:
        LOG.error(_("Database registration exception: %s"), e)
        return False
    return True
示例#5
0
def abort_and_log(status_code, descr, exc=None):
    """Process occurred errors."""
    LOG.error(_("Request aborted with status code %(code)s and "
                "message '%(msg)s'"), {'code': status_code, 'msg': descr})

    if exc is not None:
        LOG.error(traceback.format_exc())

    flask.abort(status_code, description=descr)
示例#6
0
def drop_db():
    try:
        engine = db_session.EngineFacade(cfg.CONF.database.connection,
                                         sqlite_fk=True).get_engine()
        models.Lease.metadata.drop_all(engine)
    except Exception as e:
        LOG.error(_("Database shutdown exception: %s"), e)
        return False
    return True
示例#7
0
    def __init__(self):
        extensions = []

        self.extension_manager = enabled.EnabledExtensionManager(
            check_func=lambda ext: ext.name in CONF.api.api_v2_controllers,
            namespace='climate.api.v2.controllers.extensions',
            invoke_on_load=True)
        self._log_missing_plugins(CONF.api.api_v2_controllers)

        for ext in self.extension_manager.extensions:
            try:
                setattr(self, ext.obj.name, ext.obj)
            except TypeError:
                raise exceptions.ClimateException(
                    _("API name must be specified for "
                      "extension {0}").format(ext.name))
            self._routes.update(ext.obj.extra_routes)
            extensions.append(ext.obj.name)

        LOG.debug(_("Loaded extensions: {0}").format(extensions))
示例#8
0
def main():
    config = alembic_config.Config(
        os.path.join(os.path.dirname(__file__), 'alembic.ini'))
    config.climate_config = CONF

    CONF()
    db_options.set_defaults(CONF)
    if not CONF.database.connection:
        raise SystemExit(
            _("Provide a configuration file with DB connection information"))

    CONF.command.func(config, CONF.command.name)
示例#9
0
def do_upgrade_downgrade(config, cmd):
    if not CONF.command.revision and not CONF.command.delta:
        raise SystemExit(_('You must provide a revision or relative delta'))

    revision = CONF.command.revision

    if CONF.command.delta:
        sign = '+' if CONF.command.name == 'upgrade' else '-'
        revision = sign + str(CONF.command.delta)
    else:
        revision = CONF.command.revision

    do_alembic_command(config, cmd, revision, sql=CONF.command.sql)
示例#10
0
    def post(self, lease):
        """Creates a new lease.

        :param lease: a lease within the request body.
        """
        # FIXME(sbauza): DB exceptions are currently catched and return a lease
        #                equal to None instead of being sent to the API
        lease_dct = lease.as_dict()
        lease = pecan.request.rpcapi.create_lease(lease_dct)
        if lease is not None:
            return Lease.convert(lease)
        else:
            raise exceptions.ClimateException(_("Lease can't be created"))
示例#11
0
def internal_error(status_code, descr, exc=None):
    """Called if internal error occurred."""
    LOG.error(_("Request aborted with status code %(code)s "
                "and message '%(msg)s'"), {'code': status_code, 'msg': descr})

    if exc is not None:
        LOG.error(traceback.format_exc())

    error_code = "INTERNAL_SERVER_ERROR"
    if status_code == 501:
        error_code = "NOT_IMPLEMENTED_ERROR"

    return render_error_message(status_code, descr, error_code)
示例#12
0
    def post(self, host):
        """Creates a new host.

        :param host: a host within the request body.
        """
        # here API should go to Keystone API v3 and create trust
        host_dct = host.as_dict()
        # FIXME(sbauza): DB exceptions are currently catched and return a lease
        #                equal to None instead of being sent to the API
        host = pecan.request.hosts_rpcapi.create_computehost(host_dct)
        if host is not None:
            return Host.convert(host)
        else:
            raise exceptions.ClimateException(_("Host can't be created"))
示例#13
0
def render(result=None, response_type=None, status=None, **kwargs):
    """Render response to return."""
    if not result:
        result = {}
    if type(result) is dict:
        result.update(kwargs)
    elif kwargs:
        # can't merge kwargs into the non-dict res
        abort_and_log(500,
                      _("Non-dict and non-empty kwargs passed to render."))
        return

    status_code = getattr(flask.request, 'status_code', None)
    if status:
        status_code = status
    if not status_code:
        status_code = 200

    if not response_type:
        response_type = getattr(flask.request, 'resp_type', RT_JSON)

    serializer = None
    if "application/json" in response_type:
        response_type = RT_JSON
        serializer = jsonutils
    else:
        abort_and_log(400,
                      _("Content type '%s' isn't supported") % response_type)
        return

    body = serializer.dumps(result)

    response_type = str(response_type)

    return flask.Response(response=body, status=status_code,
                          mimetype=response_type)
示例#14
0
    def __getattr__(self, name):
        try:
            method = getattr(self.__endpoint, name)

            def run_method(__ctx, **kwargs):
                with context.ClimateContext(**__ctx):
                    return method(**kwargs)

            return run_method
        except AttributeError:
            LOG.error(
                _("No %(method)s method found implemented in "
                  "%(class)s class"), {
                      'method': name,
                      'class': self.__endpoint
                  })
示例#15
0
    def _route(self, args):
        """Overrides the default routing behavior.

        It allows to map controller URL with correct controller instance.
        By default, it maps with the same name.
        """

        try:
            route = self._routes.get(args[0], args[0])
            if route is None:
                # NOTE(sbauza): Route must map to a non-existing controller
                args[0] = 'http404-nonexistingcontroller'
            else:
                args[0] = route
        except IndexError:
            LOG.error(_("No args found on V2 controller"))
        return super(V2Controller, self)._route(args)
示例#16
0
    def __init__(self, message=None, **kwargs):
        self.kwargs = kwargs

        if 'code' not in self.kwargs:
            self.kwargs['code'] = self.code

        if not message:
            try:
                message = self.msg_fmt % kwargs
            except KeyError:
                # kwargs doesn't match a variable in the message
                # log the issue and the kwargs
                LOG.exception(_('Exception in string format operation'))
                for name, value in kwargs.iteritems():
                    LOG.error("%s: %s" % (name, value))

                message = self.msg_fmt

        super(ClimateException, self).__init__(message)
示例#17
0
 def replacement_start_response(status, headers, exc_info=None):
     """Overrides the default response to make errors parsable."""
     try:
         status_code = int(status.split(' ')[0])
     except (ValueError, TypeError):  # pragma: nocover
         raise exceptions.ClimateException(_(
             'Status {0} was unexpected').format(status))
     else:
         if status_code >= 400:
             # Remove some headers so we can replace them later
             # when we have the full error message and can
             # compute the length.
             headers = [(h, v)
                        for (h, v) in headers
                        if h.lower() != 'content-length'
                        ]
             # Save the headers as we need to modify them.
             state['status_code'] = status_code
             state['headers'] = headers
             state['exc_info'] = exc_info
         return start_response(status, headers, exc_info)
示例#18
0
class InvalidInput(ClimateException):
    code = 400
    msg_fmt = _("Expected a %(cls)s type but received %(value)s.")
示例#19
0
class Timeout(ClimateException):
    msg_fmt = _('Current task failed with timeout')
示例#20
0
class TaskFailed(ClimateException):
    msg_fmt = _('Current task failed')
示例#21
0
class ServiceClient(ClimateException):
    msg_fmt = _("Service %(service)s have some problems")
示例#22
0
class WrongFormat(ClimateException):
    msg_fmt = _("Unenxpectable object format")
示例#23
0
class ServiceCatalogNotFound(NotFound):
    msg_fmt = _("Could not find service catalog")
示例#24
0
class ConfigNotFound(ClimateException):
    msg_fmt = _("Could not find config at %(path)s")
示例#25
0
class PolicyNotAuthorized(NotAuthorized):
    msg_fmt = _("Policy doesn't allow %(action)s to be performed")
示例#26
0
class NotAuthorized(ClimateException):
    msg_fmt = _("Not authorized")
    code = 403
示例#27
0
class NotFound(ClimateException):
    """Object not found exception."""
    msg_fmt = _("Object with %(object)s not found")
    code = 404
示例#28
0
class MissingTrustId(exceptions.ClimateException):
    msg_fmt = _("A trust id is required")
示例#29
0
class CantAddExtraCapability(exceptions.ClimateException):
    code = 409
    msg_fmt = _("Can't add extracapabilities %(keys)s to Host %(host)s")
示例#30
0
 def _log_missing_plugins(self, names):
     for name in names:
         if name not in self.extension_manager.names():
             LOG.error(_("API Plugin %s was not loaded") % name)