Update get_exit_status for shell process classes.
Change-Id: Ic1d8940a152dfce165bfa3648686a2a499c0a28e
This commit is contained in:
parent
0e2a97cce4
commit
bec0cb0fd8
|
@ -106,24 +106,27 @@ class LocalShellProcessFixture(_process.ShellProcessFixture):
|
|||
def poll_exit_status(self):
|
||||
return self.process.poll()
|
||||
|
||||
def get_exit_status(self, timeout=None):
|
||||
exit_status = self.process.poll()
|
||||
while exit_status is None:
|
||||
timeout = self.check_timeout(timeout=timeout)
|
||||
LOG.debug("Waiting for remote command termination: "
|
||||
"timeout=%r, command=%r", timeout, self.command)
|
||||
if TimeoutExpired is None:
|
||||
# Workaround for old Python versions that don't accept timeout
|
||||
# as parameters for wait method
|
||||
if TimeoutExpired is None:
|
||||
# Workaround for old Python versions
|
||||
def _get_exit_status(self, time_left):
|
||||
start_time = now = time.time()
|
||||
end_time = start_time + time_left
|
||||
exit_status = self.poll_exit_status()
|
||||
while exit_status is None and now < end_time:
|
||||
time.sleep(0.1)
|
||||
exit_status = self.process.poll()
|
||||
exit_status = self.poll_exit_status()
|
||||
now = time.time()
|
||||
return exit_status
|
||||
else:
|
||||
def _get_exit_status(self, time_left):
|
||||
try:
|
||||
exit_status = self.process.wait(timeout=time_left)
|
||||
except TimeoutExpired:
|
||||
LOG.exception("Failed waiting for subprocess termination")
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
exit_status = self.process.wait(timeout=min(5., timeout))
|
||||
except TimeoutExpired:
|
||||
LOG.exception("Failed waiting for subprocess termination")
|
||||
|
||||
return exit_status
|
||||
assert exit_status is not None
|
||||
return exit_status
|
||||
|
||||
def kill(self):
|
||||
process = self.process
|
||||
|
|
|
@ -30,6 +30,9 @@ from tobiko.shell.sh import _io
|
|||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
MAX_TIMEOUT = 3600. # 1 hour
|
||||
|
||||
|
||||
def process(command=None, environment=None, timeout=None, shell=None,
|
||||
stdin=None, stdout=None, stderr=None, ssh_client=None, **kwargs):
|
||||
kwargs.update(command=command, environment=environment, timeout=timeout,
|
||||
|
@ -187,7 +190,7 @@ class ShellProcessFixture(tobiko.SharedFixture):
|
|||
self.close_stdout()
|
||||
self.close_stderr()
|
||||
try:
|
||||
exit_status = self.get_exit_status()
|
||||
exit_status = self.poll_exit_status()
|
||||
except Exception:
|
||||
LOG.exception('Error getting exit status')
|
||||
exit_status = None
|
||||
|
@ -210,6 +213,23 @@ class ShellProcessFixture(tobiko.SharedFixture):
|
|||
raise NotImplementedError
|
||||
|
||||
def get_exit_status(self, timeout=None):
|
||||
time_left, timeout = get_time_left([self.timeout, timeout])
|
||||
if time_left > 0.:
|
||||
exit_status = self._get_exit_status(time_left=time_left)
|
||||
if exit_status is not None:
|
||||
return exit_status
|
||||
|
||||
ex = _exception.ShellTimeoutExpired(
|
||||
command=str(self.command),
|
||||
timeout=timeout and timeout.timeout or None,
|
||||
stdin=str_from_stream(self.stdin),
|
||||
stdout=str_from_stream(self.stdout),
|
||||
stderr=str_from_stream(self.stderr))
|
||||
LOG.debug("Timed out while waiting for command termination:\n%s",
|
||||
self.command)
|
||||
raise ex
|
||||
|
||||
def _get_exit_status(self, time_left):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
|
@ -417,7 +437,7 @@ def shell_process_timeout(timeout):
|
|||
|
||||
def get_time_left(timeouts, now=None):
|
||||
now = now or time.time()
|
||||
min_time_left = float('inf')
|
||||
min_time_left = float(MAX_TIMEOUT)
|
||||
min_timeout = None
|
||||
for timeout in timeouts:
|
||||
if timeout is not None:
|
||||
|
@ -431,14 +451,13 @@ def get_time_left(timeouts, now=None):
|
|||
|
||||
class ShellProcessTimeout(object):
|
||||
|
||||
timeout = float('inf')
|
||||
timeout = MAX_TIMEOUT
|
||||
|
||||
def __init__(self, timeout=None, start_time=None):
|
||||
if timeout is None:
|
||||
timeout = float('inf')
|
||||
timeout = self.timeout
|
||||
else:
|
||||
timeout = float(timeout)
|
||||
self.timeout = timeout
|
||||
self.timeout = float(timeout)
|
||||
start_time = start_time and float(start_time) or time.time()
|
||||
self.start_time = start_time
|
||||
self.end_time = start_time + timeout
|
||||
|
|
|
@ -18,10 +18,10 @@ from __future__ import absolute_import
|
|||
from oslo_log import log
|
||||
import paramiko
|
||||
|
||||
from tobiko.shell.sh import _execute
|
||||
from tobiko.shell.sh import _io
|
||||
from tobiko.shell.sh import _local
|
||||
from tobiko.shell.sh import _process
|
||||
from tobiko.shell.sh import _execute
|
||||
from tobiko.shell import ssh
|
||||
|
||||
|
||||
|
@ -114,15 +114,18 @@ class SSHShellProcessFixture(_process.ShellProcessFixture):
|
|||
exit_status = None
|
||||
return exit_status
|
||||
|
||||
def get_exit_status(self, timeout=None):
|
||||
def _get_exit_status(self, time_left=None):
|
||||
process = self.process
|
||||
while not process.exit_status_ready():
|
||||
timeout = self.check_timeout(timeout=timeout)
|
||||
LOG.debug("Waiting for remote command termination: "
|
||||
"timeout=%r, command=%r", timeout, self.command)
|
||||
process.status_event.wait(timeout=min(timeout, 5.))
|
||||
if not process.exit_status_ready():
|
||||
LOG.debug('Waiting for command (%s) exit status', self.command)
|
||||
# recv_exit_status method doesn't accept timeout parameter
|
||||
if process.status_event.wait(timeout=time_left):
|
||||
assert process.exit_status_ready()
|
||||
else:
|
||||
assert not process.exit_status_ready()
|
||||
return None
|
||||
|
||||
assert process.status_event.is_set()
|
||||
assert process.exit_status is not None
|
||||
return process.exit_status
|
||||
|
||||
def kill(self):
|
||||
|
|
|
@ -116,7 +116,7 @@ class ExecuteTest(testtools.TestCase):
|
|||
stdin='some input\n',
|
||||
stdout='some input\n')
|
||||
|
||||
def test_timeout_expires(self, command='sleep 5', timeout=0.1, stdin=None,
|
||||
def test_timeout_expires(self, command='sleep 10', timeout=5., stdin=None,
|
||||
stdout=None, stderr=None, **kwargs):
|
||||
ex = self.assertRaises(sh.ShellTimeoutExpired,
|
||||
self.execute,
|
||||
|
|
Loading…
Reference in New Issue