Execute a reaction by invoking the proper wrapper func

def run(self, low):
        '''
        Execute a reaction by invoking the proper wrapper func
        '''
        self.populate_client_cache(low)
        try:
            l_fun = getattr(self, low['state'])
        except AttributeError:
            log.error(
                'ReactWrap is missing a wrapper function for \'%s\'',
                low['state']
            )

        try:
            wrap_call = salt.utils.args.format_call(l_fun, low)
            args = wrap_call.get('args', ())
            kwargs = wrap_call.get('kwargs', {})
            # TODO: Setting user doesn't seem to work for actual remote pubs
            if low['state'] in ('runner', 'wheel'):
                # Update called function's low data with event user to
                # segregate events fired by reactor and avoid reaction loops
                kwargs['__user__'] = self.event_user
                # Replace ``state`` kwarg which comes from high data compiler.
                # It breaks some runner functions and seems unnecessary.
                kwargs['__state__'] = kwargs.pop('state')
                # NOTE: if any additional keys are added here, they will also
                # need to be added to filter_kwargs()

            if 'args' in kwargs:
                # New configuration
                reactor_args = kwargs.pop('args')
                for item in ('arg', 'kwarg'):
                    if item in low:
                        log.warning(
                            'Reactor \'%s\' is ignoring \'%s\' param %s due to '
                            'presence of \'args\' param. Check the Reactor System '
                            'documentation for the correct argument format.',
                            low['__id__'], item, low[item]
                        )
                if low['state'] == 'caller' \
                        and isinstance(reactor_args, list) \
                        and not salt.utils.data.is_dictlist(reactor_args):
                    # Legacy 'caller' reactors were already using the 'args'
                    # param, but only supported a list of positional arguments.
                    # If low['args'] is a list but is *not* a dictlist, then
                    # this is actually using the legacy configuration. So, put
                    # the reactor args into kwarg['arg'] so that the wrapper
                    # interprets them as positional args.
                    kwargs['arg'] = reactor_args
                    kwargs['kwarg'] = {}
                else:
                    kwargs['arg'] = ()
                    kwargs['kwarg'] = reactor_args
                if not isinstance(kwargs['kwarg'], dict):
                    kwargs['kwarg'] = salt.utils.data.repack_dictlist(kwargs['kwarg'])
                    if not kwargs['kwarg']:
                        log.error(
                            'Reactor \'%s\' failed to execute %s \'%s\': '
                            'Incorrect argument format, check the Reactor System '
                            'documentation for the correct format.',
                            low['__id__'], low['state'], low['fun']
                        )
                        return
            else:
                # Legacy configuration
                react_call = {}
                if low['state'] in ('runner', 'wheel'):
                    if 'arg' not in kwargs or 'kwarg' not in kwargs:
                        # Runner/wheel execute on the master, so we can use
                        # format_call to get the functions args/kwargs
                        react_fun = self.client_cache[low['state']].functions.get(low['fun'])
                        if react_fun is None:
                            log.error(
                                'Reactor \'%s\' failed to execute %s \'%s\': '
                                'function not available',
                                low['__id__'], low['state'], low['fun']
                            )
                            return

                        react_call = salt.utils.args.format_call(
                            react_fun,
                            low,
                            expected_extra_kws=REACTOR_INTERNAL_KEYWORDS
                        )

                if 'arg' not in kwargs:
                    kwargs['arg'] = react_call.get('args', ())
                if 'kwarg' not in kwargs:
                    kwargs['kwarg'] = react_call.get('kwargs', {})

            # Execute the wrapper with the proper args/kwargs. kwargs['arg']
            # and kwargs['kwarg'] contain the positional and keyword arguments
            # that will be passed to the client interface to execute the
            # desired runner/wheel/remote-exec/etc. function.
            ret = l_fun(*args, **kwargs)

            if ret is False:
                log.error('Reactor \'%s\' failed  to execute %s \'%s\': '
                            'TaskPool queue is full!'
                            ' Consider tuning reactor_worker_threads and/or'
                            ' reactor_worker_hwm',
                            low['__id__'], low['state'], low['fun']
                )

        except SystemExit:
            log.warning(
                'Reactor \'%s\' attempted to exit. Ignored.', low['__id__']
            )
        except Exception:
            log.error(
                'Reactor \'%s\' failed to execute %s \'%s\'',
                low['__id__'], low['state'], low['fun'], exc_info=True
            )