Ejemplo n.º 1
0
    def _run_command(protocol_client, shell_id, command,
                     command_type=util.POWERSHELL,
                     upper_timeout=CONFIG.argus.upper_timeout):
        command_id = None
        bare_command = command
        thread_pool = pool.ThreadPool(processes=THREADS)

        command = util.get_command(command, command_type)

        try:
            command_id = protocol_client.run_command(shell_id, command)

            result = thread_pool.apply_async(
                protocol_client.get_command_output,
                args=(shell_id, command_id))
            stdout, stderr, exit_code = result.get(
                timeout=upper_timeout)
            if exit_code:
                output = "\n\n".join([out for out in (stdout, stderr) if out])
                raise exceptions.ArgusError(
                    "Executing command {command!r} with encoded Command"
                    "{encoded_command!r} failed with exit code {exit_code!r}"
                    " and output {output!r}."
                    .format(command=bare_command,
                            encoded_command=command,
                            exit_code=exit_code,
                            output=output))

            return util.sanitize_command_output(stdout), stderr, exit_code
        except multiprocessing.TimeoutError:
            raise exceptions.ArgusTimeoutError(
                "The command '{cmd}' has timed out.".format(cmd=bare_command))
        finally:
            thread_pool.terminate()
            protocol_client.cleanup_command(shell_id, command_id)
Ejemplo n.º 2
0
def exec_with_retry(action, retry_count, retry_count_interval):
    i = 0
    while True:
        try:
            return action()
        except Exception:
            if i < retry_count:
                i += 1
                time.sleep(retry_count_interval)
            else:
                raise exceptions.ArgusTimeoutError(
                    "{!r} failed too many times.".format(action))
Ejemplo n.º 3
0
    def run_command_until_condition(self, cmd, cond,
                                    retry_count=CONFIG.argus.retry_count,
                                    delay=CONFIG.argus.retry_delay,
                                    command_type=util.POWERSHELL,
                                    upper_timeout=CONFIG.argus.upper_timeout):
        """Run the given `cmd` until a condition `cond` occurs.

        :param cond:
            A callable which receives the standard output returned by
            executing the command. It should return a boolean value,
            which tells to this function to stop execution.
        :raises:
            `ArgusCLIError` if there is output found in the standard error.

        This method uses and behaves like `run_command_with_retry` but
        with an additional condition parameter.
        """

        # countdown normalization
        if not retry_count or retry_count < 0:
            retry_count = 0

        while True:
            try:
                stdout, stderr, exit_code = self.run_command(
                    cmd, command_type=command_type,
                    upper_timeout=upper_timeout)
            except Exception as exc:  # pylint: disable=broad-except
                LOG.debug("Command failed with %r.", exc)
            else:
                if stderr and exit_code:
                    raise exceptions.ArgusCLIError(
                        ("Executing command {!r} failed with {!r}"
                         " and exit code {}.")
                        .format(cmd, stderr, exit_code))
                elif cond(stdout):
                    return
                else:
                    LOG.debug("Condition not met, retrying...")

            if retry_count > 0:
                retry_count -= 1
                LOG.debug("Retrying '%s'", cmd)
                time.sleep(delay)
            else:
                raise exceptions.ArgusTimeoutError(
                    "Command {!r} failed too many times."
                    .format(cmd))
Ejemplo n.º 4
0
    def _run_cmd_until_condition(self,
                                 cmd,
                                 cond,
                                 retry_count=None,
                                 retry_count_interval=5):
        """Run the given `cmd` until a condition *cond* occurs.

        :param cmd:
            A string, representing a command which needs to
            be executed on the underlying remote client.
        :param cond:
            A callable which receives the stdout returned by
            executing the command. It should return a boolean value,
            which tells to this function to stop execution.
        :param retry_count:
            The number of retries which this function has.
            If the value is ``None``, then the function will run *forever*.
        :param retry_count_interval:
            The number of seconds to sleep when retrying a command.
        """
        count = 0
        while True:
            try:
                std_out, std_err = self._execute(cmd)
            except Exception:  # pylint: disable=broad-except
                LOG.debug("Command %r failed while waiting for condition", cmd)
                count += 1
                if retry_count and count >= retry_count:
                    raise exceptions.ArgusTimeoutError(
                        "Command {!r} failed too many times.".format(cmd))
                time.sleep(retry_count_interval)
            else:
                if std_err:
                    raise exceptions.ArgusCLIError(
                        "Executing command {!r} failed with {!r}".format(
                            cmd, std_err))
                elif cond(std_out):
                    break
                else:
                    time.sleep(retry_count_interval)
Ejemplo n.º 5
0
    def run_command_with_retry(self, cmd, count=CONFIG.argus.retry_count,
                               delay=CONFIG.argus.retry_delay,
                               command_type=util.POWERSHELL,
                               upper_timeout=CONFIG.argus.upper_timeout):
        """Run the given `cmd` until succeeds.

        :param cmd:
            A string, representing a command which needs to
            be executed on the underlying remote client.
        :param count:
            The number of retries which this function has.
            If the value is ``None``, then the function will retry *forever*.
        :param delay:
            The number of seconds to sleep when retrying a command.

        :rtype: tuple
        :returns: stdout, stderr, exit_code
        """

        # Countdown normalization.
        if not count or count < 0:
            count = 0

        while True:
            try:
                return self.run_command(cmd, command_type=command_type,
                                        upper_timeout=upper_timeout)
            except Exception as exc:  # pylint: disable=broad-except
                LOG.debug("Command failed with %r.", exc)
                # A negative `count` means no count at all.
                if count >= 0:
                    count -= 1
                if count == 0:
                    raise exceptions.ArgusTimeoutError(
                        "Command {!r} failed too many times."
                        .format(cmd))
                LOG.debug("Retrying '%s'", cmd)
                time.sleep(delay)