def locked_detach_operation(f):
    "Lock decorator for volume detach operations.\n\n    Takes a named lock prior to executing the detach call.  The lock is named\n    with the operation executed and the id of the volume. This lock can then\n    be used by other operations to avoid operation conflicts on shared volumes.\n\n    This locking mechanism is only for detach calls.   We can't use the\n    locked_volume_operation, because detach requires an additional\n    attachment_id in the parameter list.\n    "

    def ldo_inner1(inst, context, volume_id, attachment_id=None, **kwargs):

        @utils.synchronized(('%s-%s' % (volume_id, f.__name__)), external=True)
        def ldo_inner2(*_args, **_kwargs):
            return f(*_args, **_kwargs)
        return ldo_inner2(inst, context, volume_id, attachment_id, **kwargs)
    return ldo_inner1
Lock decorator for volume detach operations.

Takes a named lock prior to executing the detach call.  The lock is named
with the operation executed and the id of the volume. This lock can then
be used by other operations to avoid operation conflicts on shared volumes.

This locking mechanism is only for detach calls.   We can't use the
locked_volume_operation, because detach requires an additional
attachment_id in the parameter list.
def locked_detach_operation(f):
    "Lock decorator for volume detach operations.\n\n    Takes a named lock prior to executing the detach call.  The lock is named\n    with the operation executed and the id of the volume. This lock can then\n    be used by other operations to avoid operation conflicts on shared volumes.\n\n    This locking mechanism is only for detach calls.   We can't use the\n    locked_volume_operation, because detach requires an additional\n    attachment_id in the parameter list.\n    "

    def ldo_inner1(inst, context, volume_id, attachment_id=None, **kwargs):

        @utils.synchronized(('%s-%s' % (volume_id, f.__name__)), external=True)
        def ldo_inner2(*_args, **_kwargs):
            return f(*_args, **_kwargs)
        return ldo_inner2(inst, context, volume_id, attachment_id, **kwargs)
    return ldo_inner1