示例#1
0
文件: runner.py 项目: DaveQB/salt
    def _reformat_low(self, low):
        """
        Format the low data for RunnerClient()'s master_call() function

        The master_call function here has a different function signature than
        on WheelClient. So extract all the eauth keys and the fun key and
        assume everything else is a kwarg to pass along to the runner function
        to be called.
        """
        auth_creds = dict([(i, low.pop(i)) for i in ["username", "password", "eauth", "token", "client"] if i in low])
        fun = low.pop("fun")
        reformatted_low = {"fun": fun}
        reformatted_low.update(auth_creds)
        # Support old style calls where arguments could be specified in 'low' top level
        if not low.get("args") and not low.get("kwargs"):  # not specified or empty
            verify_fun(self.functions, fun)
            args, kwargs = salt.minion.load_args_and_kwargs(
                self.functions[fun], salt.utils.args.condition_input([], low), self.opts, ignore_invalid=True
            )
            low["args"] = args
            low["kwargs"] = kwargs
        if "kwargs" not in low:
            low["kwargs"] = {}
        if "args" not in low:
            low["args"] = []
        reformatted_low["kwarg"] = low
        return reformatted_low
示例#2
0
    def _reformat_low(self, low):
        '''
        Format the low data for RunnerClient()'s master_call() function

        The master_call function here has a different function signature than
        on WheelClient. So extract all the eauth keys and the fun key and
        assume everything else is a kwarg to pass along to the runner function
        to be called.
        '''
        auth_creds = dict([(i, low.pop(i)) for i in [
            'username', 'password', 'eauth', 'token', 'client', 'user', 'key'
        ] if i in low])
        fun = low.pop('fun')
        reformatted_low = {'fun': fun}
        reformatted_low.update(auth_creds)
        # Support old style calls where arguments could be specified in 'low' top level
        if not low.get('arg') and not low.get(
                'kwarg'):  # not specified or empty
            verify_fun(self.functions, fun)
            merged_args_kwargs = salt.utils.args.condition_input([], low)
            parsed_input = salt.utils.args.parse_input(merged_args_kwargs)
            args, kwargs = salt.minion.load_args_and_kwargs(
                self.functions[fun],
                parsed_input,
                self.opts,
                ignore_invalid=True)
            low['arg'] = args
            low['kwarg'] = kwargs
        if 'kwarg' not in low:
            low['kwarg'] = {}
        if 'arg' not in low:
            low['arg'] = []
        reformatted_low['kwarg'] = low
        return reformatted_low
示例#3
0
文件: runner.py 项目: bryson/salt
    def _reformat_low(self, low):
        '''
        Format the low data for RunnerClient()'s master_call() function

        The master_call function here has a different function signature than
        on WheelClient. So extract all the eauth keys and the fun key and
        assume everything else is a kwarg to pass along to the runner function
        to be called.
        '''
        auth_creds = dict([(i, low.pop(i)) for i in [
                'username', 'password', 'eauth', 'token', 'client', 'user', 'key'
            ] if i in low])
        fun = low.pop('fun')
        reformatted_low = {'fun': fun}
        reformatted_low.update(auth_creds)
        # Support old style calls where arguments could be specified in 'low' top level
        if not low.get('arg') and not low.get('kwarg'):  # not specified or empty
            verify_fun(self.functions, fun)
            merged_args_kwargs = salt.utils.args.condition_input([], low)
            parsed_input = salt.utils.args.parse_input(merged_args_kwargs)
            args, kwargs = salt.minion.load_args_and_kwargs(
                self.functions[fun],
                parsed_input,
                self.opts,
                ignore_invalid=True
            )
            low['arg'] = args
            low['kwarg'] = kwargs
        if 'kwarg' not in low:
            low['kwarg'] = {}
        if 'arg' not in low:
            low['arg'] = []
        reformatted_low['kwarg'] = low
        return reformatted_low
示例#4
0
文件: runner.py 项目: yy721746/salt
    def _reformat_low(self, low):
        '''
        Format the low data for RunnerClient()'s master_call() function

        This also normalizes the following low data formats to a single, common
        low data structure.

        Old-style low: ``{'fun': 'jobs.lookup_jid', 'jid': '1234'}``
        New-style: ``{'fun': 'jobs.lookup_jid', 'kwarg': {'jid': '1234'}}``
        CLI-style: ``{'fun': 'jobs.lookup_jid', 'arg': ['jid="1234"']}``
        '''
        fun = low.pop(u'fun')
        verify_fun(self.functions, fun)

        eauth_creds = dict([(i, low.pop(i)) for i in [
            u'username',
            u'password',
            u'eauth',
            u'token',
            u'client',
            u'user',
            u'key',
        ] if i in low])

        # Run name=value args through parse_input. We don't need to run kwargs
        # through because there is no way to send name=value strings in the low
        # dict other than by including an `arg` array.
        _arg, _kwarg = salt.utils.args.parse_input(low.pop(u'arg', []),
                                                   condition=False)
        _kwarg.update(low.pop(u'kwarg', {}))

        # If anything hasn't been pop()'ed out of low by this point it must be
        # an old-style kwarg.
        _kwarg.update(low)

        # Finally, mung our kwargs to a format suitable for the byzantine
        # load_args_and_kwargs so that we can introspect the function being
        # called and fish for invalid kwargs.
        munged = []
        munged.extend(_arg)
        munged.append(dict(__kwarg__=True, **_kwarg))
        arg, kwarg = salt.minion.load_args_and_kwargs(self.functions[fun],
                                                      munged,
                                                      self.opts,
                                                      ignore_invalid=True)

        return dict(fun=fun,
                    kwarg={
                        u'kwarg': kwarg,
                        u'arg': arg
                    },
                    **eauth_creds)
示例#5
0
    def run(self):
        '''
        Execute the runner sequence
        '''
        ret, async_pub = {}, {}
        if self.opts.get('doc', False):
            self.print_docs()
        else:
            low = {'fun': self.opts['fun']}
            try:
                verify_fun(self.functions, low['fun'])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low['fun']],
                    salt.utils.args.parse_input(self.opts['arg']),
                    self.opts,
                )
                low['arg'] = args
                low['kwarg'] = kwargs

                user = salt.utils.get_specific_user()

                # Run the runner!
                if self.opts.get('async', False):
                    async_pub = self. async (self.opts['fun'], low, user=user)
                    # by default: info will be not enougth to be printed out !
                    log.warning(
                        'Running in async mode. Results of this execution may '
                        'be collected by attaching to the master event bus or '
                        'by examing the master job cache, if configured. '
                        'This execution is running under tag {tag}'.format(
                            **async_pub))
                    return async_pub['jid']  # return the jid

                # otherwise run it in the main process
                async_pub = self._gen_async_pub()
                ret = self._proc_function(self.opts['fun'],
                                          low,
                                          user,
                                          async_pub['tag'],
                                          async_pub['jid'],
                                          daemonize=False)
            except salt.exceptions.SaltException as exc:
                ret = '{0}'.format(exc)
                if not self.opts.get('quiet', False):
                    display_output(ret, 'nested', self.opts)
                return ret
            log.debug('Runner return: {0}'.format(ret))
            return ret
示例#6
0
    def run(self):
        '''
        Execute the runner sequence
        '''
        ret, async_pub = {}, {}
        if self.opts.get('doc', False):
            self.print_docs()
        else:
            low = {'fun': self.opts['fun']}
            try:
                verify_fun(self.functions, low['fun'])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low['fun']],
                    salt.utils.args.parse_input(self.opts['arg']),
                    self.opts,
                )
                low['args'] = args
                low['kwargs'] = kwargs

                user = salt.utils.get_specific_user()

                # Run the runner!
                if self.opts.get('async', False):
                    async_pub = self.async(self.opts['fun'], low, user=user)
                    # by default: info will be not enougth to be printed out !
                    log.warn('Running in async mode. Results of this execution may '
                             'be collected by attaching to the master event bus or '
                             'by examing the master job cache, if configured. '
                             'This execution is running under tag {tag}'.format(**async_pub))
                    return async_pub['jid']  # return the jid

                # otherwise run it in the main process
                async_pub = self._gen_async_pub()
                ret = self._proc_function(self.opts['fun'],
                                          low,
                                          user,
                                          async_pub['tag'],
                                          async_pub['jid'],
                                          False)  # Don't daemonize
            except salt.exceptions.SaltException as exc:
                ret = '{0}'.format(exc)
                if not self.opts.get('quiet', False):
                    salt.output.display_output(ret, 'nested', self.opts)
                return ret
            log.debug('Runner return: {0}'.format(ret))
            return ret
示例#7
0
    def _reformat_low(self, low):
        '''
        Format the low data for RunnerClient()'s master_call() function

        This also normalizes the following low data formats to a single, common
        low data structure.

        Old-style low: ``{'fun': 'jobs.lookup_jid', 'jid': '1234'}``
        New-style: ``{'fun': 'jobs.lookup_jid', 'kwarg': {'jid': '1234'}}``
        CLI-style: ``{'fun': 'jobs.lookup_jid', 'arg': ['jid="1234"']}``
        '''
        fun = low.pop('fun')
        verify_fun(self.functions, fun)

        reserved_kwargs = dict([(i, low.pop(i)) for i in [
            'username',
            'password',
            'eauth',
            'token',
            'client',
            'user',
            'key',
            '__current_eauth_groups',
            '__current_eauth_user',
        ] if i in low])

        # Run name=value args through parse_input. We don't need to run kwargs
        # through because there is no way to send name=value strings in the low
        # dict other than by including an `arg` array.
        arg, kwarg = salt.utils.args.parse_input(low.pop('arg', []),
                                                 condition=False,
                                                 no_parse=self.opts.get(
                                                     'no_parse', []))
        kwarg.update(low.pop('kwarg', {}))

        # If anything hasn't been pop()'ed out of low by this point it must be
        # an old-style kwarg.
        kwarg.update(low)

        return dict(fun=fun,
                    kwarg={
                        'kwarg': kwarg,
                        'arg': arg
                    },
                    **reserved_kwargs)
示例#8
0
文件: runner.py 项目: DaveQB/salt
    def run(self):
        """
        Execute the runner sequence
        """
        ret, async_pub = {}, {}
        if self.opts.get("doc", False):
            self.print_docs()
        else:
            low = {"fun": self.opts["fun"]}
            try:
                verify_fun(self.functions, low["fun"])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low["fun"]], salt.utils.args.parse_input(self.opts["arg"]), self.opts
                )
                low["args"] = args
                low["kwargs"] = kwargs

                user = salt.utils.get_specific_user()

                # Run the runner!
                if self.opts.get("async", False):
                    async_pub = self.async(self.opts["fun"], low, user=user)
                    # by default: info will be not enougth to be printed out !
                    log.warn(
                        "Running in async mode. Results of this execution may "
                        "be collected by attaching to the master event bus or "
                        "by examing the master job cache, if configured. "
                        "This execution is running under tag {tag}".format(**async_pub)
                    )
                    return async_pub["jid"]  # return the jid

                # otherwise run it in the main process
                async_pub = self._gen_async_pub()
                ret = self._proc_function(
                    self.opts["fun"], low, user, async_pub["tag"], async_pub["jid"], False
                )  # Don't daemonize
            except salt.exceptions.SaltException as exc:
                ret = "{0}".format(exc)
                if not self.opts.get("quiet", False):
                    display_output(ret, "nested", self.opts)
                return ret
            log.debug("Runner return: {0}".format(ret))
            return ret
示例#9
0
文件: runner.py 项目: kiall/salt-1
    def _reformat_low(self, low):
        '''
        Format the low data for RunnerClient()'s master_call() function

        This also normalizes the following low data formats to a single, common
        low data structure.

        Old-style low: ``{'fun': 'jobs.lookup_jid', 'jid': '1234'}``
        New-style: ``{'fun': 'jobs.lookup_jid', 'kwarg': {'jid': '1234'}}``
        CLI-style: ``{'fun': 'jobs.lookup_jid', 'arg': ['jid="1234"']}``
        '''
        fun = low.pop('fun')
        verify_fun(self.functions, fun)

        eauth_creds = dict([(i, low.pop(i)) for i in [
            'username',
            'password',
            'eauth',
            'token',
            'client',
            'user',
            'key',
        ] if i in low])

        # Separate the new-style args/kwargs.
        pre_arg = low.pop('arg', [])
        pre_kwarg = low.pop('kwarg', {})
        # Anything not pop'ed from low should hopefully be an old-style kwarg.
        low['__kwarg__'] = True
        pre_kwarg.update(low)

        # Normalize old- & new-style args in a format suitable for
        # load_args_and_kwargs
        old_new_normalized_input = []
        old_new_normalized_input.extend(pre_arg)
        old_new_normalized_input.append(pre_kwarg)

        arg, kwarg = salt.minion.load_args_and_kwargs(self.functions[fun],
                                                      old_new_normalized_input,
                                                      self.opts,
                                                      ignore_invalid=True)

        return dict(fun=fun, kwarg={'kwarg': kwarg, 'arg': arg}, **eauth_creds)
示例#10
0
    def _low(self, fun, low):
        '''
        Execute a function from low data
        Low data includes:
            required:
                - fun: the name of the function to run
            optional:
                - args: a list of args to pass to fun
                - kwargs: kwargs for fun
                - __user__: user who is running the command
                - __jid__: jid to run under
                - __tag__: tag to run under
        '''
        # fire the mminion loading (if not already done) here
        # this is not to clutter the output with the module loading
        # if we have a high debug level.
        self.mminion  # pylint: disable=W0104
        jid = low.get('__jid__', salt.utils.jid.gen_jid())
        tag = low.get('__tag__', tagify(jid, prefix=self.tag_prefix))

        data = {
            'fun': '{0}.{1}'.format(self.client, fun),
            'jid': jid,
            'user': low.get('__user__', 'UNKNOWN'),
        }

        event = salt.utils.event.get_event('master',
                                           self.opts['sock_dir'],
                                           self.opts['transport'],
                                           opts=self.opts,
                                           listen=False)

        namespaced_event = salt.utils.event.NamespacedEvent(
            event,
            tag,
            print_func=self.print_async_event if hasattr(
                self, 'print_async_event') else None)
        # TODO: document these, and test that they exist
        # TODO: Other things to inject??
        func_globals = {
            '__jid__': jid,
            '__user__': data['user'],
            '__tag__': tag,
            # weak ref to avoid the Exception in interpreter
            # teardown of event
            '__jid_event__': weakref.proxy(namespaced_event),
        }

        func_globals['__jid_event__'].fire_event(data, 'new')

        try:
            verify_fun(self.functions, fun)

            # Inject some useful globals to *all* the function's global
            # namespace only once per module-- not per func
            completed_funcs = []

            for mod_name in six.iterkeys(self.functions):
                if '.' not in mod_name:
                    continue
                mod, _ = mod_name.split('.', 1)
                if mod in completed_funcs:
                    continue
                completed_funcs.append(mod)
                for global_key, value in six.iteritems(func_globals):
                    self.functions[mod_name].__globals__[global_key] = value

            # There are some descrepencies of what a "low" structure is in the
            # publisher world it is a dict including stuff such as jid, fun,
            # arg (a list of args, with kwargs packed in). Historically this
            # particular one has had no "arg" and just has had all the kwargs
            # packed into the top level object. The plan is to move away from
            # that since the caller knows what is an arg vs a kwarg, but while
            # we make the transition we will load "kwargs" using format_call if
            # there are no kwargs in the low object passed in
            f_call = None
            if 'arg' not in low:
                f_call = salt.utils.format_call(
                    self.functions[fun],
                    low,
                    expected_extra_kws=CLIENT_INTERNAL_KEYWORDS)
                args = f_call.get('arg', ())
            else:
                args = low['arg']
            if 'kwarg' not in low:
                if f_call is None:
                    f_call = salt.utils.format_call(
                        self.functions[fun],
                        low,
                        expected_extra_kws=CLIENT_INTERNAL_KEYWORDS)
                kwargs = f_call.get('kwarg', {})

                # throw a warning for the badly formed low data if we found
                # kwargs using the old mechanism
                if kwargs:
                    salt.utils.warn_until(
                        'Carbon',
                        'kwargs must be passed inside the low under "kwargs"')
            else:
                kwargs = low['kwarg']

            # Initialize a context for executing the method.
            with tornado.stack_context.StackContext(
                    self.functions.context_dict.clone):
                data['return'] = self.functions[fun](*args, **kwargs)
                data['success'] = True
        except (Exception, SystemExit) as ex:
            if isinstance(ex, salt.exceptions.NotImplemented):
                data['return'] = str(ex)
            else:
                data['return'] = 'Exception occurred in {0} {1}: {2}'.format(
                    self.client,
                    fun,
                    traceback.format_exc(),
                )
            data['success'] = False

        namespaced_event.fire_event(data, 'ret')
        try:
            salt.utils.job.store_job(
                self.opts,
                {
                    'id': self.opts['id'],
                    'tgt': self.opts['id'],
                    'jid': data['jid'],
                    'return': data,
                },
                event=None,
                mminion=self.mminion,
            )
        except salt.exceptions.SaltCacheError:
            log.error(
                'Could not store job cache info. Job details for this run may be unavailable.'
            )
        # if we fired an event, make sure to delete the event object.
        # This will ensure that we call destroy, which will do the 0MQ linger
        log.info('Runner completed: {0}'.format(data['jid']))
        del event
        del namespaced_event
        return data['return']
示例#11
0
    def run(self):
        """
        Execute the runner sequence
        """
        import salt.minion

        ret = {}
        if self.opts.get("doc", False):
            self.print_docs()
        else:
            low = {"fun": self.opts["fun"]}
            try:
                # Allocate a jid
                async_pub = self._gen_async_pub()
                self.jid = async_pub["jid"]

                fun_args = salt.utils.args.parse_input(self.opts["arg"],
                                                       no_parse=self.opts.get(
                                                           "no_parse", []))

                verify_fun(self.functions, low["fun"])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low["fun"]], fun_args)
                low["arg"] = args
                low["kwarg"] = kwargs

                if self.opts.get("eauth"):
                    if "token" in self.opts:
                        try:
                            with salt.utils.files.fopen(
                                    os.path.join(self.opts["cachedir"],
                                                 ".root_key"), "r") as fp_:
                                low["key"] = salt.utils.stringutils.to_unicode(
                                    fp_.readline())
                        except IOError:
                            low["token"] = self.opts["token"]

                    # If using eauth and a token hasn't already been loaded into
                    # low, prompt the user to enter auth credentials
                    if "token" not in low and "key" not in low and self.opts[
                            "eauth"]:
                        # This is expensive. Don't do it unless we need to.
                        import salt.auth

                        resolver = salt.auth.Resolver(self.opts)
                        res = resolver.cli(self.opts["eauth"])
                        if self.opts["mktoken"] and res:
                            tok = resolver.token_cli(self.opts["eauth"], res)
                            if tok:
                                low["token"] = tok.get("token", "")
                        if not res:
                            log.error("Authentication failed")
                            return ret
                        low.update(res)
                        low["eauth"] = self.opts["eauth"]
                else:
                    user = salt.utils.user.get_specific_user()

                if low["fun"] in [
                        "state.orchestrate", "state.orch", "state.sls"
                ]:
                    low["kwarg"]["orchestration_jid"] = async_pub["jid"]

                # Run the runner!
                if self.opts.get("async", False):
                    if self.opts.get("eauth"):
                        async_pub = self.cmd_async(low)
                    else:
                        async_pub = self.asynchronous(self.opts["fun"],
                                                      low,
                                                      user=user,
                                                      pub=async_pub)
                    # by default: info will be not enougth to be printed out !
                    log.warning(
                        "Running in asynchronous mode. Results of this execution may "
                        "be collected by attaching to the master event bus or "
                        "by examing the master job cache, if configured. "
                        "This execution is running under tag %s",
                        async_pub["tag"],
                    )
                    return async_pub["jid"]  # return the jid

                # otherwise run it in the main process
                if self.opts.get("eauth"):
                    ret = self.cmd_sync(low)
                    if isinstance(ret,
                                  dict) and set(ret) == {"data", "outputter"}:
                        outputter = ret["outputter"]
                        ret = ret["data"]
                    else:
                        outputter = None
                    display_output(ret, outputter, self.opts)
                else:
                    ret = self._proc_function(
                        self.opts["fun"],
                        low,
                        user,
                        async_pub["tag"],
                        async_pub["jid"],
                        daemonize=False,
                    )
            except salt.exceptions.SaltException as exc:
                with salt.utils.event.get_event("master",
                                                opts=self.opts) as evt:
                    evt.fire_event(
                        {
                            "success": False,
                            "return": "{0}".format(exc),
                            "retcode": 254,
                            "fun": self.opts["fun"],
                            "fun_args": fun_args,
                            "jid": self.jid,
                        },
                        tag="salt/run/{0}/ret".format(self.jid),
                    )
                # Attempt to grab documentation
                if "fun" in low:
                    ret = self.get_docs("{0}*".format(low["fun"]))
                else:
                    ret = None

                # If we didn't get docs returned then
                # return the `not availble` message.
                if not ret:
                    ret = "{0}".format(exc)
                if not self.opts.get("quiet", False):
                    display_output(ret, "nested", self.opts)
            else:
                log.debug("Runner return: %s", ret)

            return ret
示例#12
0
    def run(self):
        '''
        Execute the runner sequence
        '''
        import salt.minion
        ret = {}
        if self.opts.get('doc', False):
            self.print_docs()
        else:
            low = {'fun': self.opts['fun']}
            try:
                verify_fun(self.functions, low['fun'])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low['fun']],
                    salt.utils.args.parse_input(self.opts['arg']),
                    self.opts,
                )
                low['arg'] = args
                low['kwarg'] = kwargs

                if self.opts.get('eauth'):
                    if 'token' in self.opts:
                        try:
                            with salt.utils.fopen(
                                    os.path.join(self.opts['cachedir'],
                                                 '.root_key'), 'r') as fp_:
                                low['key'] = fp_.readline()
                        except IOError:
                            low['token'] = self.opts['token']

                    # If using eauth and a token hasn't already been loaded into
                    # low, prompt the user to enter auth credentials
                    if 'token' not in low and 'key' not in low and self.opts[
                            'eauth']:
                        # This is expensive. Don't do it unless we need to.
                        import salt.auth
                        resolver = salt.auth.Resolver(self.opts)
                        res = resolver.cli(self.opts['eauth'])
                        if self.opts['mktoken'] and res:
                            tok = resolver.token_cli(self.opts['eauth'], res)
                            if tok:
                                low['token'] = tok.get('token', '')
                        if not res:
                            log.error('Authentication failed')
                            return ret
                        low.update(res)
                        low['eauth'] = self.opts['eauth']
                else:
                    user = salt.utils.get_specific_user()

                # Allocate a jid
                async_pub = self._gen_async_pub()
                self.jid = async_pub['jid']

                if low['fun'] == 'state.orchestrate':
                    low['kwarg']['orchestration_jid'] = async_pub['jid']

                # Run the runner!
                if self.opts.get('async', False):
                    if self.opts.get('eauth'):
                        async_pub = self.cmd_async(low)
                    else:
                        async_pub = self. async (self.opts['fun'],
                                                 low,
                                                 user=user,
                                                 pub=async_pub)
                    # by default: info will be not enougth to be printed out !
                    log.warning(
                        'Running in async mode. Results of this execution may '
                        'be collected by attaching to the master event bus or '
                        'by examing the master job cache, if configured. '
                        'This execution is running under tag {tag}'.format(
                            **async_pub))
                    return async_pub['jid']  # return the jid

                # otherwise run it in the main process
                if self.opts.get('eauth'):
                    ret = self.cmd_sync(low)
                    if isinstance(ret, dict) and set(ret) == set(
                        ('data', 'outputter')):
                        outputter = ret['outputter']
                        ret = ret['data']
                    else:
                        outputter = None
                    display_output(ret, outputter, self.opts)
                else:
                    ret = self._proc_function(self.opts['fun'],
                                              low,
                                              user,
                                              async_pub['tag'],
                                              async_pub['jid'],
                                              daemonize=False)
            except salt.exceptions.SaltException as exc:
                ret = '{0}'.format(exc)
                if not self.opts.get('quiet', False):
                    display_output(ret, 'nested', self.opts)
            else:
                log.debug('Runner return: {0}'.format(ret))

            return ret
示例#13
0
文件: runner.py 项目: MalloZup/salt-2
    def run(self):
        '''
        Execute the runner sequence
        '''
        import salt.minion
        ret = {}
        if self.opts.get('doc', False):
            self.print_docs()
        else:
            low = {'fun': self.opts['fun']}
            try:
                # Allocate a jid
                async_pub = self._gen_async_pub()
                self.jid = async_pub['jid']

                fun_args = salt.utils.args.parse_input(self.opts['arg'],
                                                       no_parse=self.opts.get(
                                                           'no_parse', []))

                verify_fun(self.functions, low['fun'])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low['fun']], fun_args)
                low['arg'] = args
                low['kwarg'] = kwargs

                if self.opts.get('eauth'):
                    if 'token' in self.opts:
                        try:
                            with salt.utils.files.fopen(
                                    os.path.join(self.opts['cachedir'],
                                                 '.root_key'), 'r') as fp_:
                                low['key'] = salt.utils.stringutils.to_unicode(
                                    fp_.readline())
                        except IOError:
                            low['token'] = self.opts['token']

                    # If using eauth and a token hasn't already been loaded into
                    # low, prompt the user to enter auth credentials
                    if 'token' not in low and 'key' not in low and self.opts[
                            'eauth']:
                        # This is expensive. Don't do it unless we need to.
                        import salt.auth
                        resolver = salt.auth.Resolver(self.opts)
                        res = resolver.cli(self.opts['eauth'])
                        if self.opts['mktoken'] and res:
                            tok = resolver.token_cli(self.opts['eauth'], res)
                            if tok:
                                low['token'] = tok.get('token', '')
                        if not res:
                            log.error('Authentication failed')
                            return ret
                        low.update(res)
                        low['eauth'] = self.opts['eauth']
                else:
                    user = salt.utils.user.get_specific_user()

                if low['fun'] in [
                        'state.orchestrate', 'state.orch', 'state.sls'
                ]:
                    low['kwarg']['orchestration_jid'] = async_pub['jid']

                # Run the runner!
                if self.opts.get('async', False):
                    if self.opts.get('eauth'):
                        async_pub = self.cmd_async(low)
                    else:
                        async_pub = self.asynchronous(self.opts['fun'],
                                                      low,
                                                      user=user,
                                                      pub=async_pub)
                    # by default: info will be not enougth to be printed out !
                    log.warning(
                        'Running in asynchronous mode. Results of this execution may '
                        'be collected by attaching to the master event bus or '
                        'by examing the master job cache, if configured. '
                        'This execution is running under tag %s',
                        async_pub['tag'])
                    return async_pub['jid']  # return the jid

                # otherwise run it in the main process
                if self.opts.get('eauth'):
                    ret = self.cmd_sync(low)
                    if isinstance(ret, dict) and set(ret) == set(
                        ('data', 'outputter')):
                        outputter = ret['outputter']
                        ret = ret['data']
                    else:
                        outputter = None
                    display_output(ret, outputter, self.opts)
                else:
                    ret = self._proc_function(self.opts['fun'],
                                              low,
                                              user,
                                              async_pub['tag'],
                                              async_pub['jid'],
                                              daemonize=False)
            except salt.exceptions.SaltException as exc:
                evt = salt.utils.event.get_event('master', opts=self.opts)
                evt.fire_event(
                    {
                        'success': False,
                        'return': '{0}'.format(exc),
                        'retcode': 254,
                        'fun': self.opts['fun'],
                        'fun_args': fun_args,
                        'jid': self.jid
                    },
                    tag='salt/run/{0}/ret'.format(self.jid))
                # Attempt to grab documentation
                if 'fun' in low:
                    ret = self.get_docs('{0}*'.format(low['fun']))
                else:
                    ret = None

                # If we didn't get docs returned then
                # return the `not availble` message.
                if not ret:
                    ret = '{0}'.format(exc)
                if not self.opts.get('quiet', False):
                    display_output(ret, 'nested', self.opts)
            else:
                log.debug('Runner return: %s', ret)

            return ret
示例#14
0
    def low(self, fun, low):
        '''
        Execute a function from low data
        Low data includes:
            required:
                - fun: the name of the function to run
            optional:
                - args: a list of args to pass to fun
                - kwargs: kwargs for fun
                - __user__: user who is running the command
                - __jid__: jid to run under
                - __tag__: tag to run under
        '''
        # fire the mminion loading (if not already done) here
        # this is not to clutter the output with the module loading
        # if we have a high debug level.
        self.mminion  # pylint: disable=W0104
        jid = low.get('__jid__', salt.utils.jid.gen_jid())
        tag = low.get('__tag__', tagify(jid, prefix=self.tag_prefix))

        data = {'fun': '{0}.{1}'.format(self.client, fun),
                'jid': jid,
                'user': low.get('__user__', 'UNKNOWN'),
                }

        event = salt.utils.event.get_event(
                'master',
                self.opts['sock_dir'],
                self.opts['transport'],
                opts=self.opts,
                listen=False)

        namespaced_event = salt.utils.event.NamespacedEvent(
            event,
            tag,
            print_func=self.print_async_event
                       if hasattr(self, 'print_async_event')
                       else None
        )
        # TODO: document these, and test that they exist
        # TODO: Other things to inject??
        func_globals = {'__jid__': jid,
                        '__user__': data['user'],
                        '__tag__': tag,
                        # weak ref to avoid the Exception in interpreter
                        # teardown of event
                        '__jid_event__': weakref.proxy(namespaced_event),
                        }

        func_globals['__jid_event__'].fire_event(data, 'new')

        try:
            verify_fun(self.functions, fun)

            # Inject some useful globals to *all* the funciton's global
            # namespace only once per module-- not per func
            completed_funcs = []
            for mod_name in six.iterkeys(self.functions):
                if '.' not in mod_name:
                    continue
                mod, _ = mod_name.split('.', 1)
                if mod in completed_funcs:
                    continue
                completed_funcs.append(mod)
                for global_key, value in six.iteritems(func_globals):
                    self.functions[mod_name].__globals__[global_key] = value

            # There are some descrepencies of what a "low" structure is in the
            # publisher world it is a dict including stuff such as jid, fun,
            # arg (a list of args, with kwargs packed in). Historically this
            # particular one has had no "arg" and just has had all the kwargs
            # packed into the top level object. The plan is to move away from
            # that since the caller knows what is an arg vs a kwarg, but while
            # we make the transition we will load "kwargs" using format_call if
            # there are no kwargs in the low object passed in
            f_call = None
            if 'args' not in low:
                f_call = salt.utils.format_call(
                    self.functions[fun],
                    low,
                    expected_extra_kws=CLIENT_INTERNAL_KEYWORDS
                )
                args = f_call.get('args', ())
            else:
                args = low['args']
            if 'kwargs' not in low:
                if f_call is None:
                    f_call = salt.utils.format_call(
                        self.functions[fun],
                        low,
                        expected_extra_kws=CLIENT_INTERNAL_KEYWORDS
                    )
                kwargs = f_call.get('kwargs', {})

                # throw a warning for the badly formed low data if we found
                # kwargs using the old mechanism
                if kwargs:
                    salt.utils.warn_until(
                        'Boron',
                        'kwargs must be passed inside the low under "kwargs"'
                    )
            else:
                kwargs = low['kwargs']

            data['return'] = self.functions[fun](*args, **kwargs)
            data['success'] = True
        except (Exception, SystemExit):
            data['return'] = 'Exception occurred in {0} {1}: {2}'.format(
                            self.client,
                            fun,
                            traceback.format_exc(),
                            )
            data['success'] = False

        namespaced_event.fire_event(data, 'ret')
        salt.utils.job.store_job(
            self.opts,
            {'id': self.opts['id'],
             'tgt': self.opts['id'],
             'jid': data['jid'],
             'return': data,
             },
            event=None,
            mminion=self.mminion,
            )
        # if we fired an event, make sure to delete the event object.
        # This will ensure that we call destroy, which will do the 0MQ linger
        log.info('Runner completed: {0}'.format(data['jid']))
        del event
        del namespaced_event
        return data['return']
示例#15
0
文件: runner.py 项目: bryson/salt
    def run(self):
        '''
        Execute the runner sequence
        '''
        import salt.minion
        ret = {}
        if self.opts.get('doc', False):
            self.print_docs()
        else:
            low = {'fun': self.opts['fun']}
            try:
                verify_fun(self.functions, low['fun'])
                args, kwargs = salt.minion.load_args_and_kwargs(
                    self.functions[low['fun']],
                    salt.utils.args.parse_input(self.opts['arg']),
                    self.opts,
                )
                low['arg'] = args
                low['kwarg'] = kwargs

                if self.opts.get('eauth'):
                    if 'token' in self.opts:
                        try:
                            with salt.utils.fopen(os.path.join(self.opts['cachedir'], '.root_key'), 'r') as fp_:
                                low['key'] = fp_.readline()
                        except IOError:
                            low['token'] = self.opts['token']

                    # If using eauth and a token hasn't already been loaded into
                    # low, prompt the user to enter auth credentials
                    if 'token' not in low and 'key' not in low and self.opts['eauth']:
                        # This is expensive. Don't do it unless we need to.
                        import salt.auth
                        resolver = salt.auth.Resolver(self.opts)
                        res = resolver.cli(self.opts['eauth'])
                        if self.opts['mktoken'] and res:
                            tok = resolver.token_cli(
                                    self.opts['eauth'],
                                    res
                                    )
                            if tok:
                                low['token'] = tok.get('token', '')
                        if not res:
                            log.error('Authentication failed')
                            return ret
                        low.update(res)
                        low['eauth'] = self.opts['eauth']
                else:
                    user = salt.utils.get_specific_user()

                # Allocate a jid
                async_pub = self._gen_async_pub()
                self.jid = async_pub['jid']

                if low['fun'] == 'state.orchestrate':
                    low['kwarg']['orchestration_jid'] = async_pub['jid']

                # Run the runner!
                if self.opts.get('async', False):
                    if self.opts.get('eauth'):
                        async_pub = self.cmd_async(low)
                    else:
                        async_pub = self.async(self.opts['fun'],
                                               low,
                                               user=user,
                                               pub=async_pub)
                    # by default: info will be not enougth to be printed out !
                    log.warning('Running in async mode. Results of this execution may '
                             'be collected by attaching to the master event bus or '
                             'by examing the master job cache, if configured. '
                             'This execution is running under tag {tag}'.format(**async_pub))
                    return async_pub['jid']  # return the jid

                # otherwise run it in the main process
                if self.opts.get('eauth'):
                    ret = self.cmd_sync(low)
                    if isinstance(ret, dict) and set(ret) == set(('data', 'outputter')):
                        outputter = ret['outputter']
                        ret = ret['data']
                    else:
                        outputter = None
                    display_output(ret, outputter, self.opts)
                else:
                    ret = self._proc_function(self.opts['fun'],
                                              low,
                                              user,
                                              async_pub['tag'],
                                              async_pub['jid'],
                                              daemonize=False)
            except salt.exceptions.SaltException as exc:
                ret = '{0}'.format(exc)
                if not self.opts.get('quiet', False):
                    display_output(ret, 'nested', self.opts)
            else:
                log.debug('Runner return: {0}'.format(ret))

            return ret