From e3d9084cd9fccb1f99ac44f04da7db4e7cb0cb7a Mon Sep 17 00:00:00 2001 From: Warren Usui Date: Thu, 11 Jul 2013 20:24:09 -0700 Subject: [PATCH] Created tasktest to test sequential and parallel tasks. Added sequential task and parallel task. Changed _run_one_task to run_one_task (now called by new tasks too). Fix #4969 Signed-off-by: Warren Usui --- teuthology/run_tasks.py | 4 +-- teuthology/task/parallel.py | 40 +++++++++++++++++++++++++++++ teuthology/task/sequential.py | 37 +++++++++++++++++++++++++++ teuthology/task/tasktest.py | 48 +++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 teuthology/task/parallel.py create mode 100644 teuthology/task/sequential.py create mode 100644 teuthology/task/tasktest.py diff --git a/teuthology/run_tasks.py b/teuthology/run_tasks.py index d121bd4821..8193839a6a 100644 --- a/teuthology/run_tasks.py +++ b/teuthology/run_tasks.py @@ -3,7 +3,7 @@ import logging log = logging.getLogger(__name__) -def _run_one_task(taskname, **kwargs): +def run_one_task(taskname, **kwargs): submod = taskname subtask = 'task' if '.' in taskname: @@ -22,7 +22,7 @@ def run_tasks(tasks, ctx): except ValueError: raise RuntimeError('Invalid task definition: %s' % taskdict) log.info('Running task %s...', taskname) - manager = _run_one_task(taskname, ctx=ctx, config=config) + manager = run_one_task(taskname, ctx=ctx, config=config) if hasattr(manager, '__enter__'): manager.__enter__() stack.append(manager) diff --git a/teuthology/task/parallel.py b/teuthology/task/parallel.py new file mode 100644 index 0000000000..d8fe1409bb --- /dev/null +++ b/teuthology/task/parallel.py @@ -0,0 +1,40 @@ +import sys +import logging +import contextlib + +from teuthology import run_tasks +from teuthology import parallel +from ..orchestra import run + +log = logging.getLogger(__name__) + +def task(ctx, config): + """ + Run a group of tasks in parallel. + + example: + - parallel: + - tasktest: + - tasktest: + + Sequential task and Parallel tasks can be nested. + """ + + log.info('starting parallel...') + with parallel.parallel() as p: + for entry in config: + ((taskname, confg),) = entry.iteritems() + p.spawn(_run_spawned, ctx, confg, taskname) + +def _run_spawned(ctx,config,taskname): + mgr = {} + try: + log.info('In parallel, running task %s...' % taskname) + mgr = run_tasks.run_one_task(taskname, ctx=ctx, config=config) + if hasattr(mgr, '__enter__'): + mgr.__enter__() + finally: + exc_info = sys.exc_info() + if hasattr(mgr, '__exit__'): + mgr.__exit__(*exc_info) + del exc_info diff --git a/teuthology/task/sequential.py b/teuthology/task/sequential.py new file mode 100644 index 0000000000..ebcafcf8b8 --- /dev/null +++ b/teuthology/task/sequential.py @@ -0,0 +1,37 @@ +import sys +import logging +import contextlib + +from teuthology import run_tasks +from ..orchestra import run + +log = logging.getLogger(__name__) + +def task(ctx, config): + """ + Sequentialize a group of tasks into one executable block + + example: + - sequential: + - tasktest: + - tasktest: + + Sequential task and Parallel tasks can be nested. + """ + stack = [] + try: + for entry in config: + ((taskname, confg),) = entry.iteritems() + log.info('In sequential, running task %s...' % taskname) + mgr = run_tasks.run_one_task(taskname, ctx=ctx, config=confg) + if hasattr(mgr, '__enter__'): + mgr.__enter__() + stack.append(mgr) + finally: + try: + exc_info = sys.exc_info() + while stack: + mgr = stack.pop() + endr = mgr.__exit__(*exc_info) + finally: + del exc_info diff --git a/teuthology/task/tasktest.py b/teuthology/task/tasktest.py new file mode 100644 index 0000000000..abfb5415e2 --- /dev/null +++ b/teuthology/task/tasktest.py @@ -0,0 +1,48 @@ +import logging +import contextlib +import time + +from ..orchestra import run + +log = logging.getLogger(__name__) + +@contextlib.contextmanager +def task(ctx, config): + """ + Task that just displays information when it is create and when it is + destroyed/cleaned up. This task was used to test parallel and + sequential task options. + + example: + + tasks: + - sequential: + - tasktest: + - id: 'foo' + - tasktest: + - id: 'bar' + - delay:5 + - tasktest: + + The above yaml will sequentially start a test task named foo and a test + task named bar. Bar will take 5 seconds to complete. After foo and bar + have finished, an unidentified tasktest task will run. + """ + try: + delay = config.get('delay', 0) + id = config.get('id', 'UNKNOWN') + except AttributeError: + delay = 0 + id = 'UNKNOWN' + try: + log.info('**************************************************') + log.info('Started task test -- %s' % id) + log.info('**************************************************') + time.sleep(delay) + yield + + finally: + log.info('**************************************************') + log.info('Task test is being cleaned up -- %s' % id) + log.info('**************************************************') + -- 2.39.5