Exemple #1
0
    def monitor(self, pk, min_interval=1, max_interval=30,
                timeout=None, outfile=sys.stdout, **kwargs):
        """Monitor a running job.

        Blocks further input until the job completes (whether successfully or
        unsuccessfully) and a final status can be given.
        """
        dots = itertools.cycle([0, 1, 2, 3])
        longest_string = 0
        interval = min_interval
        start = time.time()

        # Poll the Ansible Tower instance for status, and print the status
        # to the outfile (usually standard out).
        #
        # Note that this is one of the few places where we use `secho`
        # even though we're in a function that might theoretically be imported
        # and run in Python.  This seems fine; outfile can be set to /dev/null
        # and very much the normal use for this method should be CLI
        # monitoring.
        result = self.status(pk, detail=True)
        last_poll = time.time()
        timeout_check = 0
        while result['status'] != 'successful':
            # If the job has failed, we want to raise an Exception for that
            # so we get a non-zero response.
            if result['failed']:
                if is_tty(outfile) and not settings.verbose:
                    secho('\r' + ' ' * longest_string + '\n', file=outfile)
                raise exc.JobFailure('Job failed.')

            # Sanity check: Have we officially timed out?
            # The timeout check is incremented below, so this is checking
            # to see if we were timed out as of the previous iteration.
            # If we are timed out, abort.
            if timeout and timeout_check - start > timeout:
                raise exc.Timeout('Monitoring aborted due to timeout.')

            # If the outfile is a TTY, print the current status.
            output = '\rCurrent status: %s%s' % (result['status'],
                                                 '.' * next(dots))
            if longest_string > len(output):
                output += ' ' * (longest_string - len(output))
            else:
                longest_string = len(output)
            if is_tty(outfile) and not settings.verbose:
                secho(output, nl=False, file=outfile)

            # Put the process to sleep briefly.
            time.sleep(0.2)

            # Sanity check: Have we reached our timeout?
            # If we're about to time out, then we need to ensure that we
            # do one last check.
            #
            # Note that the actual timeout will be performed at the start
            # of the **next** iteration, so there's a chance for the job's
            # completion to be noted first.
            timeout_check = time.time()
            if timeout and timeout_check - start > timeout:
                last_poll -= interval

            # If enough time has elapsed, ask the server for a new status.
            #
            # Note that this doesn't actually do a status check every single
            # time; we want the "spinner" to spin even if we're not actively
            # doing a check.
            #
            # So, what happens is that we are "counting down" (actually up)
            # to the next time that we intend to do a check, and once that
            # time hits, we do the status check as part of the normal cycle.
            if time.time() - last_poll > interval:
                result = self.status(pk, detail=True)
                last_poll = time.time()
                interval = min(interval * 1.5, max_interval)

                # If the outfile is *not* a TTY, print a status update
                # when and only when we make an actual check to job status.
                if not is_tty(outfile) or settings.verbose:
                    click.echo('Current status: %s' % result['status'],
                               file=outfile)

            # Wipe out the previous output
            if is_tty(outfile) and not settings.verbose:
                secho('\r' + ' ' * longest_string, file=outfile, nl=False)
                secho('\r', file=outfile, nl=False)

        # Return the job ID and other response data
        answer = OrderedDict((
            ('changed', True),
            ('id', pk),
        ))
        answer.update(result)
        # Make sure to return ID of resource and not update number
        # relevant for project creation and update
        answer['id'] = pk
        return answer
Exemple #2
0
    def monitor(self,
                pk,
                min_interval=1,
                max_interval=30,
                timeout=None,
                outfile=sys.stdout,
                **kwargs):
        """Monitor a running job.

        Blocks further input until the job completes (whether successfully or
        unsuccessfully) and a final status can be given.
        """
        dots = itertools.cycle([0, 1, 2, 3])
        longest_string = 0
        interval = min_interval
        start = time.time()

        # Poll the Ansible Tower instance for status, and print the status
        # to the outfile (usually standard out).
        #
        # Note that this is one of the few places where we use `secho`
        # even though we're in a function that might theoretically be imported
        # and run in Python.  This seems fine; outfile can be set to /dev/null
        # and very much the normal use for this method should be CLI
        # monitoring.
        result = self.status(pk, detail=True)
        last_poll = time.time()
        timeout_check = 0
        while result['status'] != 'successful':
            # If the job has failed, we want to raise an Exception for that
            # so we get a non-zero response.
            if result['failed']:
                if is_tty(outfile) and not settings.verbose:
                    secho('\r' + ' ' * longest_string + '\n', file=outfile)
                raise exc.JobFailure('Job failed.')

            # Sanity check: Have we officially timed out?
            # The timeout check is incremented below, so this is checking
            # to see if we were timed out as of the previous iteration.
            # If we are timed out, abort.
            if timeout and timeout_check - start > timeout:
                raise exc.Timeout('Monitoring aborted due to timeout.')

            # If the outfile is a TTY, print the current status.
            output = '\rCurrent status: %s%s' % (result['status'],
                                                 '.' * next(dots))
            if longest_string > len(output):
                output += ' ' * (longest_string - len(output))
            else:
                longest_string = len(output)
            if is_tty(outfile) and not settings.verbose:
                secho(output, nl=False, file=outfile)

            # Put the process to sleep briefly.
            time.sleep(0.2)

            # Sanity check: Have we reached our timeout?
            # If we're about to time out, then we need to ensure that we
            # do one last check.
            #
            # Note that the actual timeout will be performed at the start
            # of the **next** iteration, so there's a chance for the job's
            # completion to be noted first.
            timeout_check = time.time()
            if timeout and timeout_check - start > timeout:
                last_poll -= interval

            # If enough time has elapsed, ask the server for a new status.
            #
            # Note that this doesn't actually do a status check every single
            # time; we want the "spinner" to spin even if we're not actively
            # doing a check.
            #
            # So, what happens is that we are "counting down" (actually up)
            # to the next time that we intend to do a check, and once that
            # time hits, we do the status check as part of the normal cycle.
            if time.time() - last_poll > interval:
                result = self.status(pk, detail=True)
                last_poll = time.time()
                interval = min(interval * 1.5, max_interval)

                # If the outfile is *not* a TTY, print a status update
                # when and only when we make an actual check to job status.
                if not is_tty(outfile) or settings.verbose:
                    click.echo('Current status: %s' % result['status'],
                               file=outfile)

            # Wipe out the previous output
            if is_tty(outfile) and not settings.verbose:
                secho('\r' + ' ' * longest_string, file=outfile, nl=False)
                secho('\r', file=outfile, nl=False)

        # Return the job ID and other response data
        answer = OrderedDict((
            ('changed', True),
            ('id', pk),
        ))
        answer.update(result)
        # Make sure to return ID of resource and not update number
        # relevant for project creation and update
        answer['id'] = pk
        return answer