'Decorator that adds worker DB rows for cleanable versioned  objects.
By default will take care of all cleanable objects, but we can limit
which objects we want by passing the name of the arguments we want
to be added.'

@staticmethod
def set_workers(*decorator_args):

    def _decorator(f):
        def wrapper(f, *args, **kwargs):
            if decorator_args:
                call_args = inspect.getcallargs(f, *args, **kwargs)
                candidates = [call_args[obj] for obj in decorator_args]
            else:
                candidates = list(args)
                candidates.extend(kwargs.values())
            cleanables = [cand for cand in candidates if (isinstance(cand, CinderCleanableObject) and cand.is_cleanable(pinned=False))]
            try:
                for cleanable in cleanables:
                    cleanable.set_worker()
                result = f(*args, **kwargs)
            finally:
                for cleanable in cleanables:
                    if (cleanable.worker and (cleanable.status != cleanable.worker.status)):
                        try:
                            cleanable.unset_worker()
                        except Exception:
                            pass
            return result
        return CinderCleanableObject.decorate(f, wrapper)
    if ((len(decorator_args) == 1) and callable(decorator_args[0])):
        function = decorator_args[0]
        decorator_args = None
        return _decorator(function)
    return _decorator
