Add a timeout for workflow stages
Change-Id: I9938a8bbd71ab131c8b6a2210e5d1a903ef21efd
This commit is contained in:
parent
ac9b3a44f3
commit
31a9a6e8e6
@ -160,6 +160,10 @@ subparsers:
|
|||||||
type: Value
|
type: Value
|
||||||
help: Python interpreter to be used for executing test cases
|
help: Python interpreter to be used for executing test cases
|
||||||
ansible_variable: tox_python
|
ansible_variable: tox_python
|
||||||
|
run-tests-timeout:
|
||||||
|
type: Value
|
||||||
|
help: Timeout (in seconds) to interrupt test cases execution
|
||||||
|
ansible_variable: tox_run_tests_timeout
|
||||||
test-report-dir:
|
test-report-dir:
|
||||||
type: Value
|
type: Value
|
||||||
help: directory where to store test report files
|
help: directory where to store test report files
|
||||||
|
@ -15,12 +15,15 @@ tox_step_index: 0
|
|||||||
tox_report_name:
|
tox_report_name:
|
||||||
"{{ test_report_name }}{% if tox_step_index %}_{{ '{:02d}'.format(tox_step_index | int) }}{% endif %}{% if tox_step_name %}_{{ tox_step_name }}{% endif %}{% if tox_envlist %}_{{ tox_envlist }}{% endif %}"
|
"{{ test_report_name }}{% if tox_step_index %}_{{ '{:02d}'.format(tox_step_index | int) }}{% endif %}{% if tox_step_name %}_{{ tox_step_name }}{% endif %}{% if tox_envlist %}_{{ tox_envlist }}{% endif %}"
|
||||||
|
|
||||||
|
tox_run_tests_timeout: 14400 # 4 hours
|
||||||
|
|
||||||
tox_constraints_file: '{{ remote_constraints_file }}'
|
tox_constraints_file: '{{ remote_constraints_file }}'
|
||||||
|
|
||||||
tox_constrain_env:
|
tox_constrain_env:
|
||||||
TOX_REPORT_DIR: '{{ tox_report_dir }}'
|
TOX_REPORT_DIR: '{{ tox_report_dir }}'
|
||||||
TOX_REPORT_NAME: '{{ tox_report_name }}'
|
TOX_REPORT_NAME: '{{ tox_report_name }}'
|
||||||
TOX_CONSTRAINTS_FILE: '{{ tox_constraints_file }}'
|
TOX_CONSTRAINTS_FILE: '{{ tox_constraints_file }}'
|
||||||
|
TOX_RUN_TESTS_TIMEOUT: '{{ tox_run_tests_timeout | float }}'
|
||||||
|
|
||||||
tox_succeeded_rc: 0
|
tox_succeeded_rc: 0
|
||||||
tox_failed_rc: 1
|
tox_failed_rc: 1
|
||||||
|
@ -4,5 +4,6 @@ coverage>=4.5.0 # Apache-2.0
|
|||||||
junitxml>=0.7.0 # LGPL-3
|
junitxml>=0.7.0 # LGPL-3
|
||||||
mock>=2.0.0 # BSD
|
mock>=2.0.0 # BSD
|
||||||
os-testr>=1.0.0 # Apache-2.0
|
os-testr>=1.0.0 # Apache-2.0
|
||||||
|
psutil>=5.7.2 # BSD
|
||||||
python-subunit>=1.4.0 # Apache-2.0
|
python-subunit>=1.4.0 # Apache-2.0
|
||||||
stestr>=3.0.0 # Apache-2.0
|
stestr>=3.0.0 # Apache-2.0
|
||||||
|
@ -15,10 +15,14 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import psutil
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TOP_DIR = os.path.dirname(os.path.dirname(__file__))
|
TOP_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
if TOP_DIR not in sys.path:
|
if TOP_DIR not in sys.path:
|
||||||
sys.path.insert(0, TOP_DIR)
|
sys.path.insert(0, TOP_DIR)
|
||||||
@ -47,6 +51,8 @@ TOX_REPORT_HTML = os.environ.get(
|
|||||||
TOX_REPORT_XML = os.environ.get(
|
TOX_REPORT_XML = os.environ.get(
|
||||||
'TOX_REPORT_XML', TOX_REPORT_PREFIX + '.xml')
|
'TOX_REPORT_XML', TOX_REPORT_PREFIX + '.xml')
|
||||||
|
|
||||||
|
TOX_RUN_TESTS_TIMEOUT = float(os.environ.get('TOX_RUN_TESTS_TIMEOUT') or 0.)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
common.setup_logging()
|
common.setup_logging()
|
||||||
@ -65,13 +71,17 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
def run_tests():
|
def run_tests():
|
||||||
|
setup_timeout()
|
||||||
cleanup_report_dir()
|
cleanup_report_dir()
|
||||||
log_environ()
|
log_environ()
|
||||||
|
|
||||||
succeeded = True
|
succeeded = True
|
||||||
try:
|
try:
|
||||||
run_test_cases()
|
run_test_cases()
|
||||||
except subprocess.CalledProcessError:
|
except (subprocess.CalledProcessError,
|
||||||
|
subprocess.TimeoutExpired,
|
||||||
|
ProcessLookupError) as ex:
|
||||||
|
LOG.error(f"Error while running test cases.\n{ex}")
|
||||||
succeeded = False
|
succeeded = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -91,6 +101,35 @@ def run_tests():
|
|||||||
return succeeded
|
return succeeded
|
||||||
|
|
||||||
|
|
||||||
|
def setup_timeout():
|
||||||
|
|
||||||
|
if TOX_RUN_TESTS_TIMEOUT > 0.:
|
||||||
|
|
||||||
|
def handle_timeout(_signum, _frame):
|
||||||
|
LOG.error(
|
||||||
|
f"run_tests.py timeout out after {TOX_RUN_TESTS_TIMEOUT} "
|
||||||
|
"seconds")
|
||||||
|
terminate_childs()
|
||||||
|
raise subprocess.TimeoutExpired("run_tests.py",
|
||||||
|
TOX_RUN_TESTS_TIMEOUT)
|
||||||
|
|
||||||
|
signal.setitimer(signal.ITIMER_REAL, TOX_RUN_TESTS_TIMEOUT)
|
||||||
|
signal.signal(signal.SIGALRM, handle_timeout)
|
||||||
|
LOG.debug(f'Run tests timeout set as {TOX_RUN_TESTS_TIMEOUT} seconds')
|
||||||
|
|
||||||
|
|
||||||
|
def terminate_childs():
|
||||||
|
current_process = psutil.Process()
|
||||||
|
children = current_process.children(recursive=False)
|
||||||
|
for child in children:
|
||||||
|
LOG.debug(f"Interrupt child process execution (pid={child.pid})")
|
||||||
|
os.kill(child.pid, signal.SIGINT)
|
||||||
|
for child in children:
|
||||||
|
LOG.debug("Wait for top-child process termination "
|
||||||
|
f"(pid={child.pid})...")
|
||||||
|
os.waitpid(child.pid, 0)
|
||||||
|
|
||||||
|
|
||||||
def cleanup_report_dir():
|
def cleanup_report_dir():
|
||||||
for report_file in [TOX_REPORT_LOG, TOX_REPORT_SUBUNIT, TOX_REPORT_HTML,
|
for report_file in [TOX_REPORT_LOG, TOX_REPORT_SUBUNIT, TOX_REPORT_HTML,
|
||||||
TOX_REPORT_XML]:
|
TOX_REPORT_XML]:
|
||||||
|
@ -70,8 +70,9 @@
|
|||||||
yaml: true
|
yaml: true
|
||||||
yml: true
|
yml: true
|
||||||
test_log_debug: true
|
test_log_debug: true
|
||||||
test_case_timeout: 1800
|
test_case_timeout: 1200
|
||||||
tobiko_dir: '/opt/stack/tobiko'
|
tobiko_dir: '/opt/stack/tobiko'
|
||||||
|
tox_run_tests_timeout: 3600
|
||||||
upper_constraints_file: '{{ ansible_user_dir }}/src/opendev.org/openstack/requirements/upper-constraints.txt'
|
upper_constraints_file: '{{ ansible_user_dir }}/src/opendev.org/openstack/requirements/upper-constraints.txt'
|
||||||
|
|
||||||
pre-run: playbooks/devstack/pre.yaml
|
pre-run: playbooks/devstack/pre.yaml
|
||||||
|
Loading…
x
Reference in New Issue
Block a user