Run a command on the remote host.

        The command is run on the remote host, if there is a redirected host
        then the command will be run on that redirected host. See __init__.

        :param cmd: the command to run
        :type cmd: str
        :param sudo: True if the command should be run with sudo, this parameter
        disable the use of environment files.
        :type sudo: str
        :param success_status: the list of the possible success status
        :type success_status: list
        :param error_callback: if provided, the callback to call in case of
        a failure. it will be called with two args, the output of the command
        and the returned error code.
        :return: the tuple (output of the command, returned code)
        :rtype: tuple
        :param custom_log: a optional string to record in the log instead of the command.
        This is useful for example if you want to hide a password.
        :type custom_log: str

def run(self, cmd, sudo=False, ignore_error=False, success_status=(0,),
            error_callback=None, custom_log=None, retry=0):
        """Run a command on the remote host.

        The command is run on the remote host, if there is a redirected host
        then the command will be run on that redirected host. See __init__.

        :param cmd: the command to run
        :type cmd: str
        :param sudo: True if the command should be run with sudo, this parameter
        disable the use of environment files.
        :type sudo: str
        :param success_status: the list of the possible success status
        :type success_status: list
        :param error_callback: if provided, the callback to call in case of
        a failure. it will be called with two args, the output of the command
        and the returned error code.
        :return: the tuple (output of the command, returned code)
        :rtype: tuple
        :param custom_log: a optional string to record in the log instead of the command.
        This is useful for example if you want to hide a password.
        :type custom_log: str
        """
        self._check_started()
        cmd_output = io.StringIO()
        channel = self._get_channel()
        cmd = self._prepare_cmd(cmd, sudo=sudo)

        if not custom_log:
            custom_log = cmd
        LOG.info("%s run '%s'" % (self.description, custom_log))
        channel.exec_command(cmd)

        while True:
            received = None
            rl, _, _ = select.select([channel], [], [], 30)
            if rl:
                received = channel.recv(1024).decode('UTF-8', 'ignore').strip()
                if received:
                    LOG.debug(received)
                    cmd_output.write(received)
            if channel.exit_status_ready() and not received:
                break
        cmd_output = cmd_output.getvalue()
        exit_status = channel.exit_status
        try:
            return self._evaluate_run_result(
                exit_status, cmd_output, ignore_error=ignore_error,
                success_status=success_status, error_callback=error_callback,
                custom_log=custom_log)
        except (paramiko.ssh_exception.SSHException, socket.error) as e:
            if not retry:
                raise e
            else:
                return self.run(
                    cmd, sudo=sudo, ignore_error=ignore_error,
                    success_status=success_status,
                    error_callback=error_callback, custom_log=custom_log,
                    retry=(retry - 1))