Beispiel #1
0
 def background(self,
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                as_root=False):
     try:
         port_string = '-p {}'.format(self.port) if self.port else ''
         keyfile_string = '-i {}'.format(
             self.keyfile) if self.keyfile else ''
         if as_root and not self.connected_as_root:
             command = self.sudo_cmd.format(command)
         options = " ".join([
             "-o {}={}".format(key, val)
             for key, val in self.options.items()
         ])
         command = '{} {} {} {} {}@{} {}'.format(ssh, options,
                                                 keyfile_string,
                                                 port_string, self.username,
                                                 self.host, command)
         logger.debug(command)
         if self.password:
             command, _ = _give_password(self.password, command)
         return subprocess.Popen(command,
                                 stdout=stdout,
                                 stderr=stderr,
                                 shell=True)
     except EOF:
         raise TargetNotRespondingError('Connection lost.')
Beispiel #2
0
 def _gem5_EOF_handler(self, gem5_simulation, gem5_out_dir, err):
     # If we have reached the "EOF", it typically means
     # that gem5 crashed and closed the connection. Let's
     # check and actually tell the user what happened here,
     # rather than spewing out pexpect errors.
     if gem5_simulation.poll():
         message = "The gem5 process has crashed with error code {}!\n\tPlease see {} for details."
         raise TargetNotRespondingError(
             message.format(gem5_simulation.poll(), gem5_out_dir))
     else:
         # Let's re-throw the exception in this case.
         raise err
Beispiel #3
0
 def execute(self,
             command,
             timeout=None,
             check_exit_code=True,
             as_root=False,
             strip_colors=True,
             will_succeed=False):  #pylint: disable=unused-argument
     if command == '':
         # Empty command is valid but the __devlib_ec stuff below will
         # produce a syntax error with bash. Treat as a special case.
         return ''
     try:
         with self.lock:
             _command = '({}); __devlib_ec=$?; echo; echo $__devlib_ec'.format(
                 command)
             full_output = self._execute_and_wait_for_prompt(
                 _command, timeout, as_root, strip_colors)
             split_output = full_output.rsplit('\r\n', 2)
             try:
                 output, exit_code_text, _ = split_output
             except ValueError as e:
                 raise TargetStableError(
                     "cannot split reply (target misconfiguration?):\n'{}'".
                     format(full_output))
             if check_exit_code:
                 try:
                     exit_code = int(exit_code_text)
                     if exit_code:
                         message = 'Got exit code {}\nfrom: {}\nOUTPUT: {}'
                         raise TargetStableError(
                             message.format(exit_code, command, output))
                 except (ValueError, IndexError):
                     logger.warning(
                         'Could not get exit code for "{}",\ngot: "{}"'\
                         .format(command, exit_code_text))
             return output
     except EOF:
         raise TargetNotRespondingError('Connection lost.')
     except TargetStableError as e:
         if will_succeed:
             raise TargetTransientError(e)
         else:
             raise
Beispiel #4
0
 def background(self,
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                as_root=False):
     try:
         port_string = '-p {}'.format(self.port) if self.port else ''
         keyfile_string = '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '
         if as_root and not self.connected_as_root:
             command = self.sudo_cmd.format(command)
         command = '{} {} {} {}@{} {}'.format(ssh, keyfile_string,
                                              port_string, self.username,
                                              self.host, command)
         logger.debug(command)
         if self.password:
             command, _ = _give_password(self.password, command)
         return subprocess.Popen(command,
                                 stdout=stdout,
                                 stderr=stderr,
                                 shell=True)
     except EOF:
         raise TargetNotRespondingError('Connection lost.')
Beispiel #5
0
 def background(self,
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                as_root=False):
     try:
         port_string = '-p {}'.format(self.port) if self.port else ''
         keyfile_string = '-i {}'.format(
             self.keyfile) if self.keyfile else ''
         if as_root:
             command = self.sudo_cmd.format(command)
         command = '{} {} {} {}@{} {}'.format(ssh, keyfile_string,
                                              port_string, self.username,
                                              self.host, command)
         logger.debug(command)
         if self.password:
             command = _give_password(self.password, command)
         return subprocess.Popen(command,
                                 stdout=stdout,
                                 stderr=stderr,
                                 shell=True)
     except EOF:
         raise TargetNotRespondingError('Connection lost.')
Beispiel #6
0
    def connect_gem5(self, port, gem5_simulation, gem5_interact_dir,
                     gem5_out_dir):
        """
        Connect to the telnet port of the gem5 simulation.

        We connect, and wait for the prompt to be found. We do not use a timeout
        for this, and wait for the prompt in a while loop as the gem5 simulation
        can take many hours to reach a prompt when booting the system. We also
        inject some newlines periodically to try and force gem5 to show a
        prompt. Once the prompt has been found, we replace it with a unique
        prompt to ensure that we are able to match it properly. We also disable
        the echo as this simplifies parsing the output when executing commands
        on the device.
        """
        host = socket.gethostname()
        gem5_logger.info(
            "Connecting to the gem5 simulation on port {}".format(port))

        # Check if there is no on-going connection yet
        lock_file_name = '{}{}_{}.LOCK'.format(self.lock_directory, host, port)
        if os.path.isfile(lock_file_name):
            # There is already a connection to this gem5 simulation
            raise TargetStableError(
                'There is already a connection to the gem5 '
                'simulation using port {} on {}!'.format(port, host))

        # Connect to the gem5 telnet port. Use a short timeout here.
        attempts = 0
        while attempts < 10:
            attempts += 1
            try:
                self.conn = TelnetPxssh(original_prompt=None)
                self.conn.login(host,
                                self.username,
                                port=port,
                                login_timeout=10,
                                auto_prompt_reset=False)
                break
            except pxssh.ExceptionPxssh:
                pass
            except EOF as err:
                self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
        else:
            gem5_simulation.kill()
            raise TargetNotRespondingError(
                "Failed to connect to the gem5 telnet session.")

        gem5_logger.info("Connected! Waiting for prompt...")

        # Create the lock file
        self.lock_file_name = lock_file_name
        open(self.lock_file_name, 'w').close()  # Similar to touch
        gem5_logger.info("Created lock file {} to prevent reconnecting to "
                         "same simulation".format(self.lock_file_name))

        # We need to find the prompt. It might be different if we are resuming
        # from a checkpoint. Therefore, we test multiple options here.
        prompt_found = False
        while not prompt_found:
            try:
                self._login_to_device()
            except TIMEOUT:
                pass
            except EOF as err:
                self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)

            try:
                # Try and force a prompt to be shown
                self.conn.send('\n')
                self.conn.expect([
                    r'# ', r'\$ ', self.conn.UNIQUE_PROMPT,
                    r'\[PEXPECT\][\\\$\#]+ '
                ],
                                 timeout=60)
                prompt_found = True
            except TIMEOUT:
                pass
            except EOF as err:
                self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)

        gem5_logger.info("Successfully logged in")
        gem5_logger.info("Setting unique prompt...")

        self.conn.set_unique_prompt()
        self.conn.prompt()
        gem5_logger.info("Prompt found and replaced with a unique string")

        # We check that the prompt is what we think it should be. If not, we
        # need to update the regex we use to match.
        self._find_prompt()

        self.conn.setecho(False)
        self._sync_gem5_shell()

        # Fully connected to gem5 simulation
        self.gem5_interact_dir = gem5_interact_dir
        self.gem5_out_dir = gem5_out_dir
        self.gem5simulation = gem5_simulation

        # Ready for interaction now
        self.ready = True
Beispiel #7
0
 def check_responsive(self):
     try:
         self.conn.execute('ls /', timeout=5)
     except (TimeoutError, subprocess.CalledProcessError):
         raise TargetNotRespondingError(self.conn.name)