1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-09-03 20:02:39 +01:00

Skeleton job execution

This commit is contained in:
Sergei Trofimov
2017-03-09 14:44:26 +00:00
parent 6eb5c3681d
commit 011fd684bd
14 changed files with 714 additions and 92 deletions

View File

@@ -57,6 +57,8 @@ from wa.framework.exception import (WAError, ConfigError, TimeoutError,
from wa.framework.plugin import Artifact
from wa.framework.resource import ResourceResolver
from wa.framework.target.info import TargetInfo
from wa.framework.target.manager import TargetManager
from wa.utils import log
from wa.utils.misc import (ensure_directory_exists as _d,
get_traceback, format_duration)
from wa.utils.serializer import json
@@ -74,15 +76,70 @@ REBOOT_DELAY = 3
class ExecutionContext(object):
@property
def previous_job(self):
if not self.job_queue:
return None
return self.job_queue[0]
@property
def next_job(self):
if not self.completed_jobs:
return None
return self.completed_jobs[-1]
@property
def spec_changed(self):
if self.previous_job is None and self.current_job is not None: # Start of run
return True
if self.previous_job is not None and self.current_job is None: # End of run
return True
return self.current_job.spec.id != self.previous_job.spec.id
@property
def spec_will_change(self):
if self.current_job is None and self.next_job is not None: # Start of run
return True
if self.current_job is not None and self.next_job is None: # End of run
return True
return self.current_job.spec.id != self.next_job.spec.id
def __init__(self, cm, tm, output):
self.logger = logging.getLogger('ExecContext')
self.logger = logging.getLogger('context')
self.cm = cm
self.tm = tm
self.output = output
self.logger.debug('Loading resource discoverers')
self.resolver = ResourceResolver(cm)
self.resolver.load()
self.job_queue = None
self.completed_jobs = None
self.current_job = None
def start_run(self):
self.output.info.start_time = datetime.now()
self.output.write_info()
self.job_queue = copy(self.cm.jobs)
self.completed_jobs = []
def end_run(self):
self.output.info.end_time = datetime.now()
self.output.info.duration = self.output.info.end_time -\
self.output.info.start_time
self.output.write_info()
def start_job(self):
if not self.job_queue:
raise RuntimeError('No jobs to run')
self.current_job = self.job_queue.pop(0)
return self.current_job
def end_job(self):
if not self.current_job:
raise RuntimeError('No jobs in progress')
self.completed_jobs.append(self.current_job)
self.current_job = None
class OldExecutionContext(object):
@@ -147,22 +204,6 @@ class OldExecutionContext(object):
self.job_iteration_counts = defaultdict(int)
self.aborted = False
self.runner = None
if config.agenda.filepath:
self.run_artifacts.append(Artifact('agenda',
os.path.join(self.host_working_directory,
os.path.basename(config.agenda.filepath)),
'meta',
mandatory=True,
description='Agenda for this run.'))
for i, filepath in enumerate(settings.config_paths, 1):
name = 'config_{}'.format(i)
path = os.path.join(self.host_working_directory,
name + os.path.splitext(filepath)[1])
self.run_artifacts.append(Artifact(name,
path,
kind='meta',
mandatory=True,
description='Config file used for the run.'))
def initialize(self):
if not os.path.isdir(self.run_output_directory):
@@ -228,30 +269,6 @@ def _check_artifact_path(path, rootpath):
return full_path
class FakeTargetManager(object):
# TODO: this is a FAKE
def __init__(self, name, config):
self.device_name = name
self.device_config = config
from devlib import LocalLinuxTarget
self.target = LocalLinuxTarget({'unrooted': True})
def get_target_info(self):
return TargetInfo(self.target)
def validate_runtime_parameters(self, params):
pass
def merge_runtime_parameters(self, params):
pass
def init_target_manager(config):
return FakeTargetManager(config.device, config.device_config)
class Executor(object):
"""
The ``Executor``'s job is to set up the execution context and pass to a
@@ -268,7 +285,7 @@ class Executor(object):
# pylint: disable=R0915
def __init__(self):
self.logger = logging.getLogger('Executor')
self.logger = logging.getLogger('executor')
self.error_logged = False
self.warning_logged = False
pluginloader = None
@@ -297,7 +314,8 @@ class Executor(object):
output.write_config(config)
self.logger.info('Connecting to target')
target_manager = init_target_manager(config.run_config)
target_manager = TargetManager(config.run_config.device,
config.run_config.device_config)
output.write_target_info(target_manager.get_target_info())
self.logger.info('Initializing execution conetext')
@@ -312,6 +330,11 @@ class Executor(object):
instrumentation.install(instrument)
instrumentation.validate()
self.logger.info('Starting run')
runner = Runner(context)
runner.run()
def execute_postamble(self):
"""
@@ -370,6 +393,92 @@ class Runner(object):
"""
def __init__(self, context):
self.logger = logging.getLogger('runner')
self.context = context
self.output = self.context.output
self.config = self.context.cm
def run(self):
self.send(signal.RUN_STARTED)
try:
self.initialize_run()
self.send(signal.RUN_INITIALIZED)
while self.context.job_queue:
with signal.wrap('JOB_EXECUTION', self):
self.run_next_job(self.context)
except Exception as e:
if (not getattr(e, 'logged', None) and
not isinstance(e, KeyboardInterrupt)):
log.log_error(e, self.logger)
e.logged = True
raise e
finally:
self.finalize_run()
self.send(signal.RUN_COMPLETED)
def initialize_run(self):
self.logger.info('Initializing run')
self.context.start_run()
log.indent()
for job in self.context.job_queue:
job.initialize(self.context)
log.dedent()
def finalize_run(self):
self.logger.info('Finalizing run')
self.context.end_run()
def run_next_job(self, context):
job = context.start_job()
self.logger.info('Running job {}'.format(job.id))
job.status = JobStatus.RUNNING
log.indent()
self.send(signal.JOB_STARTED)
with signal.wrap('JOB_TARGET_CONFIG', self):
job.configure_target(context)
with signal.wrap('JOB_SETUP', self):
job.setup(context)
try:
with signal.wrap('JOB_EXECUTION', self):
job.run(context)
try:
with signal.wrap('JOB_OUTPUT_PROCESSED', self):
job.run(context)
except Exception:
job.status = JobStatus.PARTIAL
raise
except KeyboardInterrupt:
job.status = JobStatus.ABORTED
raise
except Exception as e:
job.status = JobStatus.FAILED
if not getattr(e, 'logged', None):
log.log_error(e, self.logger)
e.logged = True
raise e
finally:
# If setup was successfully completed, teardown must
# run even if the job failed
with signal.wrap('JOB_TEARDOWN', self):
job.teardown(context)
log.dedent()
self.logger.info('Completing job {}'.format(job.id))
self.send(signal.JOB_COMPLETED)
context.end_job()
def send(self, s):
signal.send(s, self, self.context)
def __str__(self):
return 'runner'
class RunnerJob(object):
"""