Exemple #1
0
def _with_auth_context(auth_ctx, func, *args, **kw):
    """Runs the given function with the specified auth context.

    :param auth_ctx: Authentication context.
    :param func: Function to run with the specified auth context.
    :param args: Function positional arguments.
    :param kw: Function keyword arguments.
    :return: Function result.
    """
    old_auth_ctx = context.ctx() if context.has_ctx() else None

    context.set_ctx(auth_ctx)

    try:
        return func(*args, **kw)
    except Exception as e:
        # Note (rakhmerov): In case of "Too many connections" error from the
        # database it doesn't get wrapped with a SQLAlchemy exception for some
        # reason so we have to check the exception message explicitly.
        if isinstance(e, _RETRY_ERRORS) or 'Too many connections' in str(e):
            LOG.exception("DB error detected, operation will be retried: %s",
                          func)

        raise
    finally:
        context.set_ctx(old_auth_ctx)
Exemple #2
0
def schedule_call(factory_method_path, target_method_name,
                  run_after, serializers=None, **method_args):
    """Schedules call and lately invokes target_method.

    Add this call specification to DB, and then after run_after
    seconds service CallScheduler invokes the target_method.

    :param factory_method_path: Full python-specific path to
    factory method for target object construction.
    :param target_method_name: Name of target object method which
    will be invoked.
    :param run_after: Value in seconds.
    param serializers: map of argument names and their serializer class paths.
     Use when an argument is an object of specific type, and needs to be
      serialized. Example:
      { "result": "mistral.utils.serializer.ResultSerializer"}
      Serializer for the object type must implement serializer interface
       in mistral/utils/serializer.py
    :param method_args: Target method keyword arguments.
    """
    ctx_serializer = context.RpcContextSerializer(
        context.JsonPayloadSerializer()
    )

    ctx = (
        ctx_serializer.serialize_context(context.ctx())
        if context.has_ctx() else {}
    )

    execution_time = (datetime.datetime.now() +
                      datetime.timedelta(seconds=run_after))

    if serializers:
        for arg_name, serializer_path in serializers.items():
            if arg_name not in method_args:
                raise exc.MistralException(
                    "Serializable method argument %s"
                    " not found in method_args=%s"
                    % (arg_name, method_args))
            try:
                serializer = importutils.import_class(serializer_path)()
            except ImportError as e:
                raise ImportError("Cannot import class %s: %s"
                                  % (serializer_path, e))

            method_args[arg_name] = serializer.serialize(
                method_args[arg_name]
            )

    values = {
        'factory_method_path': factory_method_path,
        'target_method_name': target_method_name,
        'execution_time': execution_time,
        'auth_context': ctx,
        'serializers': serializers,
        'method_arguments': method_args,
        'processing': False
    }

    db_api.create_delayed_call(values)
    def decorate(*args, **kw):
        _prepare()

        try:
            res = func(*args, **kw)

            queues = _get_queues()

            tx_queue = queues[0]
            non_tx_queue = queues[1]

            if not tx_queue and not non_tx_queue:
                return res

            auth_ctx = context.ctx() if context.has_ctx() else None

            def _within_new_thread():
                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    if tx_queue:
                        _process_tx_queue(tx_queue)

                    if non_tx_queue:
                        _process_non_tx_queue(non_tx_queue)
                finally:
                    context.set_ctx(old_auth_ctx)

            eventlet.spawn(_within_new_thread)
        finally:
            _clear()

        return res
def schedule_call(factory_method_path, target_method_name,
                  run_after, serializers=None, key=None, **method_args):
    """Schedules call and lately invokes target_method.

    Add this call specification to DB, and then after run_after
    seconds service CallScheduler invokes the target_method.

    :param factory_method_path: Full python-specific path to
        factory method that creates a target object that the call will be
        made against.
    :param target_method_name: Name of a method which will be invoked.
    :param run_after: Value in seconds.
    :param serializers: map of argument names and their serializer class
        paths. Use when an argument is an object of specific type, and needs
        to be serialized. Example:
        { "result": "mistral.utils.serializer.ResultSerializer"}
        Serializer for the object type must implement serializer interface
        in mistral/utils/serializer.py
    :param key: Key which can potentially be used for squashing similar
        delayed calls.
    :param method_args: Target method keyword arguments.
    """
    ctx_serializer = context.RpcContextSerializer()

    ctx = (
        ctx_serializer.serialize_context(context.ctx())
        if context.has_ctx() else {}
    )

    execution_time = (datetime.datetime.now() +
                      datetime.timedelta(seconds=run_after))

    if serializers:
        for arg_name, serializer_path in serializers.items():
            if arg_name not in method_args:
                raise exc.MistralException(
                    "Serializable method argument %s"
                    " not found in method_args=%s"
                    % (arg_name, method_args))
            try:
                serializer = importutils.import_class(serializer_path)()
            except ImportError as e:
                raise ImportError(
                    "Cannot import class %s: %s" % (serializer_path, e)
                )

            method_args[arg_name] = serializer.serialize(method_args[arg_name])

    values = {
        'factory_method_path': factory_method_path,
        'target_method_name': target_method_name,
        'execution_time': execution_time,
        'auth_context': ctx,
        'serializers': serializers,
        'key': key,
        'method_arguments': method_args,
        'processing': False
    }

    db_api.create_delayed_call(values)
Exemple #5
0
    def decorate(*args, **kw):
        _prepare()

        try:
            res = func(*args, **kw)

            queues = _get_queues()

            tx_queue = queues[0]
            non_tx_queue = queues[1]

            if not tx_queue and not non_tx_queue:
                return res

            auth_ctx = context.ctx() if context.has_ctx() else None

            def _within_new_thread():
                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    if tx_queue:
                        _process_tx_queue(tx_queue)

                    if non_tx_queue:
                        _process_non_tx_queue(non_tx_queue)
                finally:
                    context.set_ctx(old_auth_ctx)

            eventlet.spawn(_within_new_thread)
        finally:
            _clear()

        return res
Exemple #6
0
    def decorate(*args, **kw):
        _prepare()

        try:
            res = func(*args, **kw)

            queue = _get_queue()
            auth_ctx = context.ctx() if context.has_ctx() else None

            # NOTE(rakhmerov): Since we make RPC calls to the engine itself
            # we need to process the action queue asynchronously in a new
            # thread. Otherwise, if we have one engine process the engine
            # will may send a request to itself while already processing
            # another one. In conjunction with blocking RPC it will lead
            # to a deadlock (and RPC timeout).
            def _within_new_thread():
                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    _process_queue(queue)
                finally:
                    context.set_ctx(old_auth_ctx)

            eventlet.spawn(_within_new_thread)
        finally:
            _clear()

        return res
Exemple #7
0
            def _within_new_thread():
                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    _process_queue(queue)
                finally:
                    context.set_ctx(old_auth_ctx)
Exemple #8
0
    def decorate(*args, **kw):
        # Retrying library decorator might potentially run a decorated
        # function within a new thread so it's safer not to apply the
        # decorator directly to a target method/function because we can
        # lose an authentication context.
        # The solution is to create one more function and explicitly set
        # auth context before calling it (potentially in a new thread).
        auth_ctx = context.ctx() if context.has_ctx() else None

        return retry.call(_with_auth_context, auth_ctx, func, *args, **kw)
Exemple #9
0
    def decorate(*args, **kw):
        # Retrying library decorator might potentially run a decorated
        # function within a new thread so it's safer not to apply the
        # decorator directly to a target method/function because we can
        # lose an authentication context.
        # The solution is to create one more function and explicitly set
        # auth context before calling it (potentially in a new thread).
        auth_ctx = context.ctx() if context.has_ctx() else None

        return retry.call(_with_auth_context, auth_ctx, func, *args, **kw)
Exemple #10
0
    def decorate(*args, **kw):
        # We can't use RetryDecorator from oslo_service directly because
        # it runs a decorated function in a different thread and hence
        # the function doesn't have access to authentication context
        # set as a thread local variable.
        # The solution is to reuse RetryDecorator but explicitly set
        # auth context in the new thread that RetryDecorator spawns.
        # In order to do that we need an additional helper function.

        auth_ctx = ctx.ctx() if ctx.has_ctx() else None

        return _with_auth_context(auth_ctx, func, *args, **kw)
Exemple #11
0
    def decorate(*args, **kw):
        # We can't use RetryDecorator from oslo_service directly because
        # it runs a decorated function in a different thread and hence
        # the function doesn't have access to authentication context
        # set as a thread local variable.
        # The solution is to reuse RetryDecorator but explicitly set
        # auth context in the new thread that RetryDecorator spawns.
        # In order to do that we need an additional helper function.

        auth_ctx = ctx.ctx() if ctx.has_ctx() else None

        return _with_auth_context(auth_ctx, func, *args, **kw)
Exemple #12
0
            def _within_new_thread():
                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    if tx_queue:
                        _process_tx_queue(tx_queue)

                    if non_tx_queue:
                        _process_non_tx_queue(non_tx_queue)
                finally:
                    context.set_ctx(old_auth_ctx)
Exemple #13
0
def schedule_call(factory_method_path,
                  target_method_name,
                  run_after,
                  serializers=None,
                  **method_args):
    """Add this call specification to DB, and then after run_after
    seconds service CallScheduler invokes the target_method.

    :param factory_method_path: Full python-specific path to
    factory method for target object construction.
    :param target_method_name: Name of target object method which
    will be invoked.
    :param run_after: Value in seconds.
    param serializers: map of argument names and their serializer class paths.
     Use when an argument is an object of specific type, and needs to be
      serialized. Example:
      { "result": "mistral.utils.serializer.ResultSerializer"}
      Serializer for the object type must implement serializer interface
       in mistral/utils/serializer.py
    :param method_args: Target method keyword arguments.
    """
    ctx = context.ctx().to_dict() if context.has_ctx() else {}

    execution_time = (datetime.datetime.now() +
                      datetime.timedelta(seconds=run_after))

    if serializers:
        for arg_name, serializer_path in serializers.items():
            if arg_name not in method_args:
                raise exc.MistralException("Serializable method argument %s"
                                           " not found in method_args=%s" %
                                           (arg_name, method_args))
            try:
                serializer = importutils.import_class(serializer_path)()
            except ImportError as e:
                raise ImportError("Cannot import class %s: %s" %
                                  (serializer_path, e))

            method_args[arg_name] = serializer.serialize(method_args[arg_name])

    values = {
        'factory_method_path': factory_method_path,
        'target_method_name': target_method_name,
        'execution_time': execution_time,
        'auth_context': ctx,
        'serializers': serializers,
        'method_arguments': method_args
    }

    db_api.create_delayed_call(values)
Exemple #14
0
def delete_trust(trust_id=None):
    if not trust_id:
        # Try to retrieve trust from context.
        if auth_ctx.has_ctx():
            trust_id = auth_ctx.ctx().trust_id

    if not trust_id:
        return

    keystone_client = keystone.client_for_trusts(trust_id)

    try:
        keystone_client.trusts.delete(trust_id)
    except Exception as e:
        LOG.warning("Failed to delete trust [id=%s]: %s", trust_id, e)
Exemple #15
0
def delete_trust(trust_id=None):
    if not trust_id:
        # Try to retrieve trust from context.
        if auth_ctx.has_ctx():
            trust_id = auth_ctx.ctx().trust_id

    if not trust_id:
        return

    keystone_client = keystone.client_for_trusts(trust_id)

    try:
        keystone_client.trusts.delete(trust_id)
    except Exception as e:
        LOG.warning("Failed to delete trust [id=%s]: %s", trust_id, e)
Exemple #16
0
            def _within_new_thread():
                # This is a new thread so we need to init a profiler again.
                if cfg.CONF.profiler.enabled:
                    profiler.init(cfg.CONF.profiler.hmac_keys)

                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    if tx_queue:
                        _process_tx_queue(tx_queue)

                    if non_tx_queue:
                        _process_non_tx_queue(non_tx_queue)
                finally:
                    context.set_ctx(old_auth_ctx)
    def _persist_job(job):
        ctx_serializer = context.RpcContextSerializer()

        ctx = (
            ctx_serializer.serialize_context(context.ctx())
            if context.has_ctx() else {}
        )

        execute_at = (utils.utc_now_sec() +
                      datetime.timedelta(seconds=job.run_after))

        args = job.func_args
        arg_serializers = job.func_arg_serializers

        if arg_serializers:
            for arg_name, serializer_path in arg_serializers.items():
                if arg_name not in args:
                    raise exc.MistralException(
                        "Serializable function argument %s"
                        " not found in func_args=%s"
                        % (arg_name, args))
                try:
                    serializer = importutils.import_class(serializer_path)()
                except ImportError as e:
                    raise ImportError(
                        "Cannot import class %s: %s" % (serializer_path, e)
                    )

                args[arg_name] = serializer.serialize(args[arg_name])

        values = {
            'run_after': job.run_after,
            'target_factory_func_name': job.target_factory_func_name,
            'func_name': job.func_name,
            'func_args': args,
            'func_arg_serializers': arg_serializers,
            'auth_ctx': ctx,
            'execute_at': execute_at,
            'captured_at': None,
            'key': job.key
        }

        return db_api.create_scheduled_job(values)
    def _persist_job(cls, job):
        ctx_serializer = context.RpcContextSerializer()

        ctx = (
            ctx_serializer.serialize_context(context.ctx())
            if context.has_ctx() else {}
        )

        execute_at = (utils.utc_now_sec() +
                      datetime.timedelta(seconds=job.run_after))

        args = job.func_args
        arg_serializers = job.func_arg_serializers

        if arg_serializers:
            for arg_name, serializer_path in arg_serializers.items():
                if arg_name not in args:
                    raise exc.MistralException(
                        "Serializable function argument %s"
                        " not found in func_args=%s"
                        % (arg_name, args))
                try:
                    serializer = importutils.import_class(serializer_path)()
                except ImportError as e:
                    raise ImportError(
                        "Cannot import class %s: %s" % (serializer_path, e)
                    )

                args[arg_name] = serializer.serialize(args[arg_name])

        values = {
            'run_after': job.run_after,
            'target_factory_func_name': job.target_factory_func_name,
            'func_name': job.func_name,
            'func_args': args,
            'func_arg_serializers': arg_serializers,
            'auth_ctx': ctx,
            'execute_at': execute_at,
            'captured_at': None
        }

        return db_api.create_scheduled_job(values)
Exemple #19
0
def _with_auth_context(auth_ctx, func, *args, **kw):
    """Runs the given function with the specified auth context.

    :param auth_ctx: Authentication context.
    :param func: Function to run with the specified auth context.
    :param args: Function positional arguments.
    :param kw: Function keyword arguments.
    :return: Function result.
    """
    old_auth_ctx = context.ctx() if context.has_ctx() else None

    context.set_ctx(auth_ctx)

    try:
        return func(*args, **kw)
    except _RETRY_ERRORS:
        LOG.exception("DB error detected, operation will be retried: %s", func)

        raise
    finally:
        context.set_ctx(old_auth_ctx)
Exemple #20
0
    def decorate(*args, **kw):
        _prepare()

        try:
            res = func(*args, **kw)

            queues = _get_queues()

            tx_queue = queues[0]
            non_tx_queue = queues[1]

            if not tx_queue and not non_tx_queue:
                return res

            auth_ctx = context.ctx() if context.has_ctx() else None

            def _within_new_thread():
                # This is a new thread so we need to init a profiler again.
                if cfg.CONF.profiler.enabled:
                    profiler.init(cfg.CONF.profiler.hmac_keys)

                old_auth_ctx = context.ctx() if context.has_ctx() else None

                context.set_ctx(auth_ctx)

                try:
                    if tx_queue:
                        _process_tx_queue(tx_queue)

                    if non_tx_queue:
                        _process_non_tx_queue(non_tx_queue)
                finally:
                    context.set_ctx(old_auth_ctx)

            eventlet.spawn(_within_new_thread)
        finally:
            _clear()

        return res
Exemple #21
0
def _with_auth_context(auth_ctx, func, *args, **kw):
    """Runs the given function with the specified auth context.

    :param auth_ctx: Authentication context.
    :param func: Function to run with the specified auth context.
    :param args: Function positional arguments.
    :param kw: Function keywork arguments.
    :return: Function result.
    """
    old_auth_ctx = ctx.ctx() if ctx.has_ctx() else None

    ctx.set_ctx(auth_ctx)

    try:
        return func(*args, **kw)
    except db_exc.DBDeadlock as e:
        LOG.exception("DB deadlock detected, operation will be retried: %s",
                      func)

        raise e
    finally:
        ctx.set_ctx(old_auth_ctx)
Exemple #22
0
def _with_auth_context(auth_ctx, func, *args, **kw):
    """Runs the given function with the specified auth context.

    :param auth_ctx: Authentication context.
    :param func: Function to run with the specified auth context.
    :param args: Function positional arguments.
    :param kw: Function keywork arguments.
    :return: Function result.
    """
    old_auth_ctx = ctx.ctx() if ctx.has_ctx() else None

    ctx.set_ctx(auth_ctx)

    try:
        return func(*args, **kw)
    except db_exc.DBDeadlock as e:
        LOG.exception(
            "DB deadlock detected, operation will be retried: %s", func
        )

        raise e
    finally:
        ctx.set_ctx(old_auth_ctx)
Exemple #23
0
def _with_auth_context(auth_ctx, func, *args, **kw):
    """Runs the given function with the specified auth context.

    :param auth_ctx: Authentication context.
    :param func: Function to run with the specified auth context.
    :param args: Function positional arguments.
    :param kw: Function keyword arguments.
    :return: Function result.
    """
    old_auth_ctx = context.ctx() if context.has_ctx() else None

    context.set_ctx(auth_ctx)

    try:
        return func(*args, **kw)
    except _RETRY_ERRORS:
        LOG.exception(
            "DB error detected, operation will be retried: %s", func
        )

        raise
    finally:
        context.set_ctx(old_auth_ctx)
Exemple #24
0
def get_project_id():
    if CONF.pecan.auth_enable and auth_ctx.has_ctx():
        return auth_ctx.ctx().project_id
    else:
        return DEFAULT_PROJECT_ID
Exemple #25
0
def get_project_id():
    if CONF.pecan.auth_enable and auth_ctx.has_ctx():
        return auth_ctx.ctx().project_id
    else:
        return DEFAULT_PROJECT_ID
Exemple #26
0
def schedule_call(factory_method_path,
                  target_method_name,
                  run_after,
                  serializers=None,
                  unique_key=None,
                  **method_args):
    """Schedules call and lately invokes target_method.

    Add this call specification to DB, and then after run_after
    seconds service CallScheduler invokes the target_method.

    :param factory_method_path: Full python-specific path to
        factory method that creates a target object that the call will be
        made against.
    :param target_method_name: Name of a method which will be invoked.
    :param run_after: Value in seconds.
    :param serializers: map of argument names and their serializer class
        paths. Use when an argument is an object of specific type, and needs
        to be serialized. Example:
        { "result": "mistral.utils.serializer.ResultSerializer"}
        Serializer for the object type must implement serializer interface
        in mistral/utils/serializer.py
    :param unique_key: Unique key which in combination with 'processing'
        flag restricts a number of delayed calls if it's passed. For example,
        if we schedule two calls but pass the same unique key for them then
        we won't get two of them in DB if both have same value of 'processing'
        flag.
    :param method_args: Target method keyword arguments.
    """
    ctx_serializer = context.RpcContextSerializer(
        context.JsonPayloadSerializer())

    ctx = (ctx_serializer.serialize_context(context.ctx())
           if context.has_ctx() else {})

    execution_time = (datetime.datetime.now() +
                      datetime.timedelta(seconds=run_after))

    if serializers:
        for arg_name, serializer_path in serializers.items():
            if arg_name not in method_args:
                raise exc.MistralException("Serializable method argument %s"
                                           " not found in method_args=%s" %
                                           (arg_name, method_args))
            try:
                serializer = importutils.import_class(serializer_path)()
            except ImportError as e:
                raise ImportError("Cannot import class %s: %s" %
                                  (serializer_path, e))

            method_args[arg_name] = serializer.serialize(method_args[arg_name])

    values = {
        'factory_method_path': factory_method_path,
        'target_method_name': target_method_name,
        'execution_time': execution_time,
        'auth_context': ctx,
        'serializers': serializers,
        'unique_key': unique_key,
        'method_arguments': method_args,
        'processing': False
    }

    db_api.insert_or_ignore_delayed_call(values)