Ejemplo n.º 1
0
Archivo: ssh.py Proyecto: nuxeh/devlib
 def _execute_and_wait_for_prompt(self,
                                  command,
                                  timeout=None,
                                  as_root=False,
                                  strip_colors=True,
                                  log=True):
     self.conn.prompt(0.1)  # clear an existing prompt if there is one.
     if as_root:
         command = "sudo -- sh -c '{}'".format(
             escape_single_quotes(command))
         if log:
             logger.debug(command)
         self.conn.sendline(command)
         if self.password:
             index = self.conn.expect_exact([self.password_prompt, TIMEOUT],
                                            timeout=0.5)
             if index == 0:
                 self.conn.sendline(self.password)
     else:  # not as_root
         if log:
             logger.debug(command)
         self.conn.sendline(command)
     timed_out = self._wait_for_prompt(timeout)
     # the regex removes line breaks potential introduced when writing
     # command to shell.
     output = process_backspaces(self.conn.before)
     output = re.sub(r'\r([^\n])', r'\1', output)
     if '\r\n' in output:  # strip the echoed command
         output = output.split('\r\n', 1)[1]
     if timed_out:
         self.cancel_running_command()
         raise TimeoutError(command, output)
     if strip_colors:
         output = strip_bash_colors(output)
     return output
Ejemplo n.º 2
0
 def _scp(self, source, dest, timeout=30):
     # NOTE: the version of scp in Ubuntu 12.04 occasionally (and bizarrely)
     # fails to connect to a device if port is explicitly specified using -P
     # option, even if it is the default port, 22. To minimize this problem,
     # only specify -P for scp if the port is *not* the default.
     port_string = '-P {}'.format(quote(str(
         self.port))) if (self.port and self.port != 22) else ''
     keyfile_string = '-i {}'.format(quote(
         self.keyfile)) if self.keyfile else ''
     options = " ".join(
         ["-o{}={}".format(key, val) for key, val in self.options.items()])
     command = '{} {} -r {} {} {} {}'.format(scp, options, keyfile_string,
                                             port_string, quote(source),
                                             quote(dest))
     command_redacted = command
     logger.debug(command)
     if self.password:
         command, command_redacted = _give_password(self.password, command)
     try:
         check_output(command, timeout=timeout, shell=True)
     except subprocess.CalledProcessError as e:
         raise_from(
             HostError("Failed to copy file with '{}'. Output:\n{}".format(
                 command_redacted, e.output)), None)
     except TimeoutError as e:
         raise TimeoutError(command_redacted, e.output)
Ejemplo n.º 3
0
 def wait_for_device(self, timeout=30):
     """
     Wait for Gem5 to be ready for interation with a timeout.
     """
     for _ in attempts(timeout):
         if self.ready:
             return
         time.sleep(1)
     raise TimeoutError('Gem5 is not ready for interaction')
Ejemplo n.º 4
0
def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
    """This is a version of subprocess.check_output that adds a timeout parameter to kill
    the subprocess if it does not return within the specified time."""
    # pylint: disable=too-many-branches
    if ignore is None:
        ignore = []
    elif isinstance(ignore, int):
        ignore = [ignore]
    elif not isinstance(ignore, list) and ignore != 'all':
        message = 'Invalid value for ignore parameter: "{}"; must be an int or a list'
        raise ValueError(message.format(ignore))
    if 'stdout' in kwargs:
        raise ValueError('stdout argument not allowed, it will be overridden.')

    def callback(pid):
        try:
            check_output_logger.debug(
                '{} timed out; sending SIGKILL'.format(pid))
            os.killpg(pid, signal.SIGKILL)
        except OSError:
            pass  # process may have already terminated.

    with check_output_lock:
        process = subprocess.Popen(command,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   stdin=subprocess.PIPE,
                                   preexec_fn=preexec_function,
                                   **kwargs)

    if timeout:
        timer = threading.Timer(timeout, callback, [
            process.pid,
        ])
        timer.start()

    try:
        output, error = process.communicate(inputtext)
        if sys.version_info[0] == 3:
            # Currently errors=replace is needed as 0x8c throws an error
            output = output.decode(sys.stdout.encoding, "replace")
            error = error.decode(sys.stderr.encoding, "replace")
    finally:
        if timeout:
            timer.cancel()

    retcode = process.poll()
    if retcode:
        if retcode == -9:  # killed, assume due to timeout callback
            raise TimeoutError(command, output='\n'.join([output, error]))
        elif ignore != 'all' and retcode not in ignore:
            raise subprocess.CalledProcessError(retcode,
                                                command,
                                                output='\n'.join(
                                                    [str(output),
                                                     str(error)]))
    return output, error
Ejemplo n.º 5
0
def check_output(command,
                 timeout=None,
                 ignore=None,
                 inputtext=None,
                 combined_output=False,
                 **kwargs):
    """This is a version of subprocess.check_output that adds a timeout parameter to kill
    the subprocess if it does not return within the specified time."""
    # pylint: disable=too-many-branches
    if ignore is None:
        ignore = []
    elif isinstance(ignore, int):
        ignore = [ignore]
    elif not isinstance(ignore, list) and ignore != 'all':
        message = 'Invalid value for ignore parameter: "{}"; must be an int or a list'
        raise ValueError(message.format(ignore))
    if 'stdout' in kwargs:
        raise ValueError('stdout argument not allowed, it will be overridden.')

    with check_output_lock:
        stderr = subprocess.STDOUT if combined_output else subprocess.PIPE
        process = subprocess.Popen(command,
                                   stdout=subprocess.PIPE,
                                   stderr=stderr,
                                   stdin=subprocess.PIPE,
                                   preexec_fn=preexec_function,
                                   **kwargs)

    try:
        output, error = process.communicate(inputtext, timeout=timeout)
    except subprocess.TimeoutExpired as e:
        timeout_expired = e
    else:
        timeout_expired = None

    # Currently errors=replace is needed as 0x8c throws an error
    output = output.decode(sys.stdout.encoding or 'utf-8', "replace")
    if error:
        error = error.decode(sys.stderr.encoding or 'utf-8', "replace")

    if timeout_expired:
        raise TimeoutError(command,
                           output='\n'.join([output or '', error or '']))

    retcode = process.poll()
    if retcode and ignore != 'all' and retcode not in ignore:
        raise subprocess.CalledProcessError(retcode,
                                            command,
                                            output='\n'.join(
                                                [output or '', error or '']))
    return output, error
Ejemplo n.º 6
0
 def _scp(self, source, dest, timeout=30):
     # NOTE: the version of scp in Ubuntu 12.04 occasionally (and bizarrely)
     # fails to connect to a device if port is explicitly specified using -P
     # option, even if it is the default port, 22. To minimize this problem,
     # only specify -P for scp if the port is *not* the default.
     port_string = '-P {}'.format(self.port) if (self.port and self.port != 22) else ''
     keyfile_string = '-i {}'.format(self.keyfile) if self.keyfile else ''
     command = '{} -r {} {} {} {}'.format(scp, keyfile_string, port_string, source, dest)
     pass_string = ''
     logger.debug(command)
     if self.password:
         command = _give_password(self.password, command)
     try:
         check_output(command, timeout=timeout, shell=True)
     except subprocess.CalledProcessError as e:
         raise subprocess.CalledProcessError(e.returncode, e.cmd.replace(pass_string, ''), e.output)
     except TimeoutError as e:
         raise TimeoutError(e.command.replace(pass_string, ''), e.output)
Ejemplo n.º 7
0
 def _execute_and_wait_for_prompt(self,
                                  command,
                                  timeout=None,
                                  as_root=False,
                                  strip_colors=True,
                                  log=True):
     self.conn.prompt(0.1)  # clear an existing prompt if there is one.
     if self.username == 'root':
         # As we're already root, there is no need to use sudo.
         as_root = False
     if as_root:
         command = self.sudo_cmd.format(escape_single_quotes(command))
         if log:
             logger.debug(command)
         self.conn.sendline(command)
         if self.password:
             index = self.conn.expect_exact([self.password_prompt, TIMEOUT],
                                            timeout=0.5)
             if index == 0:
                 self.conn.sendline(self.password)
     else:  # not as_root
         if log:
             logger.debug(command)
         self.conn.sendline(command)
     timed_out = self._wait_for_prompt(timeout)
     # the regex removes line breaks potential introduced when writing
     # command to shell.
     if sys.version_info[0] == 3:
         output = process_backspaces(
             self.conn.before.decode(sys.stdout.encoding, 'replace'))
     else:
         output = process_backspaces(self.conn.before)
     output = re.sub(r'\r([^\n])', r'\1', output)
     if '\r\n' in output:  # strip the echoed command
         output = output.split('\r\n', 1)[1]
     if timed_out:
         self.cancel_running_command()
         raise TimeoutError(command, output)
     if strip_colors:
         output = strip_bash_colors(output)
     return output
Ejemplo n.º 8
0
    def _execute_and_wait_for_prompt(self,
                                     command,
                                     timeout=None,
                                     as_root=False,
                                     strip_colors=True,
                                     log=True):
        self.conn.prompt(0.1)  # clear an existing prompt if there is one.
        if as_root and self.connected_as_root:
            # As we're already root, there is no need to use sudo.
            as_root = False
        if as_root:
            command = self.sudo_cmd.format(quote(command))
            if log:
                logger.debug(command)
            self._sendline(command)
            if self.password:
                index = self.conn.expect_exact([self.password_prompt, TIMEOUT],
                                               timeout=0.5)
                if index == 0:
                    self._sendline(self.password)
        else:  # not as_root
            if log:
                logger.debug(command)
            self._sendline(command)
        timed_out = self._wait_for_prompt(timeout)
        if sys.version_info[0] == 3:
            output = process_backspaces(
                self.conn.before.decode(sys.stdout.encoding or 'utf-8',
                                        'replace'))
        else:
            output = process_backspaces(self.conn.before)

        if timed_out:
            self.cancel_running_command()
            raise TimeoutError(command, output)
        if strip_colors:
            output = strip_bash_colors(output)
        return output
Ejemplo n.º 9
0
def check_subprocess_output(process,
                            timeout=None,
                            ignore=None,
                            inputtext=None):
    output = None
    error = None
    # pylint: disable=too-many-branches
    if ignore is None:
        ignore = []
    elif isinstance(ignore, int):
        ignore = [ignore]
    elif not isinstance(ignore, list) and ignore != 'all':
        message = 'Invalid value for ignore parameter: "{}"; must be an int or a list'
        raise ValueError(message.format(ignore))

    try:
        output, error = process.communicate(inputtext, timeout=timeout)
    except subprocess.TimeoutExpired as e:
        timeout_expired = e
    else:
        timeout_expired = None

    # Currently errors=replace is needed as 0x8c throws an error
    output = output.decode(sys.stdout.encoding or 'utf-8',
                           "replace") if output else ''
    error = error.decode(sys.stderr.encoding or 'utf-8',
                         "replace") if error else ''

    if timeout_expired:
        raise TimeoutError(process.args, output='\n'.join([output, error]))

    retcode = process.poll()
    if retcode and ignore != 'all' and retcode not in ignore:
        raise subprocess.CalledProcessError(retcode,
                                            process.args,
                                            output='\n'.join([output, error]))

    return output, error