1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

LinuxTarget: fixing reboot sequence

When issuing a target.reboot(), the reset was immediately followed by a
boot() (for platforms that have it) and an attempt to connect. When
issuing a soft reset, it's possible the target is still shutting down
when the attempt to connect is made. This results in the connection
succeeding but being severed shortly thereafter.

This introduces a delay after the reset to the reboot sequence, giving
the target time to shutdown and improves the handling of EOF's that
result from failed reconnection attempts (while still being with the
allotted timeout period.
This commit is contained in:
Sergei Trofimov 2016-02-25 10:28:45 +00:00
parent 9c89ca0437
commit ebe3a8a0a8
2 changed files with 55 additions and 32 deletions

View File

@ -228,6 +228,13 @@ class Target(object):
'(in which case, a hard_reset module must be installed)' '(in which case, a hard_reset module must be installed)'
raise TargetError(message) raise TargetError(message)
self.reset() self.reset()
# Wait a fixed delay before starting polling to give the target time to
# shut down, otherwise, might create the connection while it's still shutting
# down resulting in subsequenct connection failing.
self.logger.debug('Waiting for target to power down...')
reset_delay = 20
time.sleep(reset_delay)
timeout = max(timeout - reset_delay, 10)
if self.has('boot'): if self.has('boot'):
self.boot() # pylint: disable=no-member self.boot() # pylint: disable=no-member
if connect: if connect:

View File

@ -22,6 +22,7 @@ import re
import threading import threading
import tempfile import tempfile
import shutil import shutil
import time
import pexpect import pexpect
from distutils.version import StrictVersion as V from distutils.version import StrictVersion as V
@ -44,19 +45,28 @@ logger = logging.getLogger('ssh')
def ssh_get_shell(host, username, password=None, keyfile=None, port=None, timeout=10, telnet=False): def ssh_get_shell(host, username, password=None, keyfile=None, port=None, timeout=10, telnet=False):
_check_env() _check_env()
start_time = time.time()
while True:
if telnet: if telnet:
if keyfile: if keyfile:
raise ValueError('keyfile may not be used with a telnet connection.') raise ValueError('keyfile may not be used with a telnet connection.')
conn = TelnetConnection() conn = TelnetConnection()
else: # ssh else: # ssh
conn = pxssh.pxssh() conn = pxssh.pxssh()
try: try:
if keyfile: if keyfile:
conn.login(host, username, ssh_key=keyfile, port=port, login_timeout=timeout) conn.login(host, username, ssh_key=keyfile, port=port, login_timeout=timeout)
else: else:
conn.login(host, username, password, port=port, login_timeout=timeout) conn.login(host, username, password, port=port, login_timeout=timeout)
break
except EOF: except EOF:
raise TargetError('Could not connect to {}; is the host name correct?'.format(host)) timeout -= time.time() - start_time
if timeout <= 0:
message = 'Could not connect to {}; is the host name correct?'
raise TargetError(message.format(host))
time.sleep(5)
conn.setwinsize(500,200) conn.setwinsize(500,200)
conn.sendline('') conn.sendline('')
conn.prompt() conn.prompt()
@ -151,6 +161,7 @@ class SshConnection(object):
return self._scp(source, dest, timeout) return self._scp(source, dest, timeout)
def execute(self, command, timeout=None, check_exit_code=True, as_root=False, strip_colors=True): def execute(self, command, timeout=None, check_exit_code=True, as_root=False, strip_colors=True):
try:
with self.lock: with self.lock:
output = self._execute_and_wait_for_prompt(command, timeout, as_root, strip_colors) output = self._execute_and_wait_for_prompt(command, timeout, as_root, strip_colors)
if check_exit_code: if check_exit_code:
@ -163,8 +174,11 @@ class SshConnection(object):
except (ValueError, IndexError): except (ValueError, IndexError):
logger.warning('Could not get exit code for "{}",\ngot: "{}"'.format(command, exit_code_text)) logger.warning('Could not get exit code for "{}",\ngot: "{}"'.format(command, exit_code_text))
return output return output
except EOF:
raise TargetError('Connection lost.')
def background(self, command, stdout=subprocess.PIPE, stderr=subprocess.PIPE): def background(self, command, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
try:
port_string = '-p {}'.format(self.port) if self.port else '' port_string = '-p {}'.format(self.port) if self.port else ''
keyfile_string = '-i {}'.format(self.keyfile) if self.keyfile else '' keyfile_string = '-i {}'.format(self.keyfile) if self.keyfile else ''
command = '{} {} {} {}@{} {}'.format(ssh, keyfile_string, port_string, self.username, self.host, command) command = '{} {} {} {}@{} {}'.format(ssh, keyfile_string, port_string, self.username, self.host, command)
@ -172,6 +186,8 @@ class SshConnection(object):
if self.password: if self.password:
command = _give_password(self.password, command) command = _give_password(self.password, command)
return subprocess.Popen(command, stdout=stdout, stderr=stderr, shell=True) return subprocess.Popen(command, stdout=stdout, stderr=stderr, shell=True)
except EOF:
raise TargetError('Connection lost.')
def close(self): def close(self):
logger.debug('Logging out {}@{}'.format(self.username, self.host)) logger.debug('Logging out {}@{}'.format(self.username, self.host))