Beispiel #1
0
class ClientWrapper():

    EventFeedListeners = []

    def __init__(self):
        self.SaltClient = APIClient()

    def auth(self, username, password, eauth='pam'):
        '''Authenticates a user against external auth and returns a token.'''
        try:
            token = self.SaltClient.create_token({
                'username': username,
                'password': password,
                'eauth': eauth
            })
        except:
            token = {
                'error': 'Invalid credentials',
                'details': 'Authentication failed with provided credentials.'
            }

        return token

    def get_event(self, tag=''):
        self.SaltClient.get_event(tag)

    def cmd(self, cmdmesg):
        cdict = {
            'mode': 'async'
        }
        # TODO: async?
        cdict['fun'] = cmdmesg['method']
        cdict['tgt'] = cmdmesg['pattern']
        cdict['expr_form'] = cmdmesg.get('pattern_type', 'glob')
        cdict['kwarg'] = cmdmesg.get('kwargs', {})
        cdict['arg'] = cmdmesg.get('args', [])
        cdict['token'] = cmdmesg['token']
        retval = self.SaltClient.run(cdict)
        return retval
 def runner_manage_present_async(self):
     '''
     Make a call to runner.manage.present and
     test against returned SSE data
     '''
     self.app.post_json('/run',
                        dict(client='master',
                             fun='runner.manage.present',
                             kwarg={}),
                        headers=self.headers)
     keep_looping = True
     client = APIClient()
     sse = None
     while keep_looping:
         sse = client.get_event(wait=5, tag='salt/', full=True)
         keep_looping = False
     self.assertNotEqual(sse, None)
 def runner_manage_present_datastructure(self):
     '''
     Make a call to runner.manage.present and
     test data structure integrity
     '''
     resp = self.app.post_json('/run',
                               dict(client='master',
                                    fun='runner.manage.present',
                                    kwarg={}),
                               headers=self.headers)
     tag = resp.json_body['return'][0]['tag']
     client = APIClient()
     data = None
     while not data:
         sse = client.get_event(wait=0.01, tag='salt/', full=True)
         if sse['tag'] == '%s/ret' % tag:
             data = sse['data']['return']
     self.assertNotEqual(data, None)
Beispiel #4
0
class MultiJob(object):

    def __init__(self):
        """
        MultiJob constructor

        """
        self._jobs = {}
        self.client = APIClient(opts=MASTER_OPTIONS)
        self.handler = Handler()

    def add(self, job):
        """
        Adds a job to be tracked. The job is published with the salt
        apiclient. The resulting dict containing the job id and the minions
        associated with the job id are stored for later use.

        @param salt_job - SaltCommand object containing a dictionary defining
            parameters of the salt job to be published
        @return - Boolean True for successful publish, Boolean False otherwise

        """
        pub_data = self.client.run(job.kwargs)
        job.set_pub_data(pub_data)
        self._jobs[job.jid] = job

    def is_finished(self):
        """
        Checks to see if all jobs are finished.

        @return - Boolean true for finished, Boolean false otherwise

        """
        return all([job.is_finished() for job in self._jobs.itervalues()])

    def should_process_event(self, event):
        """
        Checks whether or not we need to process an event.
        Events should have a jid and a return.
        The jid should be a job belonging to this MultiJob
        The job should not be finished yet.

        @param event - Dictionary representing an event.
        @return Boolean True for yes, False otherwise.

        """
        jid = event.get('jid')
        ret = event.get('return')
        if jid is None or ret is None:
            return False

        if jid not in self._jobs:
            return False

        job = self._jobs[jid]
        if job.is_finished():
            return False
        return True

    def wait(self, timeout):
        """
        Waits for all jobs so far to be finished. If a job finishes that is
        part of a sequence of jobs, the next job in the sequenced is
        published.

        @param timeout - Float or int describing number of seconds to wait
            in total before returning.
        @return dict - Dictionary of responses

        """
        start = time.time()
        timeout_at = start + timeout
        while True:

            # Break on timeout
            if time.time() > timeout_at:
                break

            # Listen for all events with tag set to ''.
            # Need to be able to listen for multiple jobs.
            event = self.client.get_event(tag='', wait=0.25)

            # Check for no event received
            if event is None:
                continue

            if self.should_process_event(event):
                job = self._jobs[event.get('jid')]
                job.add_minion_return(event)
                if job.is_finished():
                    self.handler.handle_finish(job)
                    if job.chain:
                        self.add(job.chain)

            # Break on all jobs finished
            if self.is_finished():
                break

        errors = []
        # Validate our jobs
        for jid, job in self._jobs.iteritems():
            try:
                job.validate()
            except (UnfinishedException,
                    UnsuccessfulException,
                    RetcodeException,
                    FailedStateSlsException) as e:
                errors.append(e)
        if errors:
            raise MultiJobException(errors)

        resp = {jid: job.ret for jid, job in self._jobs.iteritems()}
        return resp