diff options
author | Tiancong Wang <tcwang@google.com> | 2020-02-13 21:08:49 +0000 |
---|---|---|
committer | Tiancong Wang <tcwang@google.com> | 2020-02-13 21:08:49 +0000 |
commit | b75f321fc8978b92ce3db6886ccb966768f0c7a8 (patch) | |
tree | 35fa0fbaeaaddd9cc2a126a05eee3527b51e83a8 /deprecated/automation/common/job.py | |
parent | cddd960b0ba2eb62c372c0d3176c75f0bd05d5e8 (diff) | |
parent | e617e3393dd24003aa976ece5050bb291070041c (diff) | |
download | toolchain-utils-android11-mainline-tethering-release.tar.gz |
Merging 18 commit(s) from Chromium's toolchain-utils am: 0ae38c8498 am: 2a19d36a82 am: e617e3393dr_aml_301500702android-mainline-12.0.0_r55android-mainline-11.0.0_r9android-mainline-11.0.0_r8android-mainline-11.0.0_r7android-mainline-11.0.0_r6android-mainline-11.0.0_r5android-mainline-11.0.0_r45android-mainline-11.0.0_r44android-mainline-11.0.0_r43android-mainline-11.0.0_r42android-mainline-11.0.0_r41android-mainline-11.0.0_r40android-mainline-11.0.0_r4android-mainline-11.0.0_r39android-mainline-11.0.0_r38android-mainline-11.0.0_r37android-mainline-11.0.0_r36android-mainline-11.0.0_r35android-mainline-11.0.0_r34android-mainline-11.0.0_r33android-mainline-11.0.0_r32android-mainline-11.0.0_r31android-mainline-11.0.0_r30android-mainline-11.0.0_r3android-mainline-11.0.0_r29android-mainline-11.0.0_r28android-mainline-11.0.0_r27android-mainline-11.0.0_r26android-mainline-11.0.0_r25android-mainline-11.0.0_r24android-mainline-11.0.0_r23android-mainline-11.0.0_r22android-mainline-11.0.0_r21android-mainline-11.0.0_r20android-mainline-11.0.0_r2android-mainline-11.0.0_r19android-mainline-11.0.0_r18android-mainline-11.0.0_r17android-mainline-11.0.0_r16android-mainline-11.0.0_r15android-mainline-11.0.0_r14android-mainline-11.0.0_r13android-mainline-11.0.0_r12android-mainline-11.0.0_r10android-mainline-11.0.0_r1android-11.0.0_r48android-11.0.0_r47android-11.0.0_r46android-11.0.0_r45android-11.0.0_r44android-11.0.0_r43android-11.0.0_r42android-11.0.0_r41android-11.0.0_r40android-11.0.0_r39android-11.0.0_r38android-11.0.0_r37android-11.0.0_r36android-11.0.0_r35android-11.0.0_r34android-11.0.0_r33android-11.0.0_r32android-11.0.0_r31android-11.0.0_r30android-11.0.0_r29android-11.0.0_r28android-11.0.0_r27android-11.0.0_r26android-11.0.0_r24android-11.0.0_r23android-11.0.0_r22android-11.0.0_r21android-11.0.0_r20android-11.0.0_r19android-11.0.0_r18android-11.0.0_r16android11-qpr3-s1-releaseandroid11-qpr3-releaseandroid11-qpr2-releaseandroid11-qpr1-s2-releaseandroid11-qpr1-s1-releaseandroid11-qpr1-releaseandroid11-qpr1-d-s1-releaseandroid11-qpr1-d-releaseandroid11-qpr1-c-releaseandroid11-mainline-tethering-releaseandroid11-mainline-sparse-2021-jan-releaseandroid11-mainline-sparse-2020-dec-releaseandroid11-mainline-releaseandroid11-mainline-permission-releaseandroid11-mainline-os-statsd-releaseandroid11-mainline-networkstack-releaseandroid11-mainline-media-swcodec-releaseandroid11-mainline-media-releaseandroid11-mainline-extservices-releaseandroid11-mainline-documentsui-releaseandroid11-mainline-conscrypt-releaseandroid11-mainline-cellbroadcast-releaseandroid11-mainline-captiveportallogin-releaseandroid11-devandroid11-d2-releaseandroid11-d1-b-release
Change-Id: I3f25c7ee034b2e20e37ed941b8eae24eec7043eb
Diffstat (limited to 'deprecated/automation/common/job.py')
-rw-r--r-- | deprecated/automation/common/job.py | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/deprecated/automation/common/job.py b/deprecated/automation/common/job.py new file mode 100644 index 00000000..e845ab25 --- /dev/null +++ b/deprecated/automation/common/job.py @@ -0,0 +1,178 @@ +# Copyright 2010 Google Inc. All Rights Reserved. +# +"""A module for a job in the infrastructure.""" + +__author__ = 'raymes@google.com (Raymes Khoury)' + +import os.path + +from automation.common import state_machine + +STATUS_NOT_EXECUTED = 'NOT_EXECUTED' +STATUS_SETUP = 'SETUP' +STATUS_COPYING = 'COPYING' +STATUS_RUNNING = 'RUNNING' +STATUS_SUCCEEDED = 'SUCCEEDED' +STATUS_FAILED = 'FAILED' + + +class FolderDependency(object): + + def __init__(self, job, src, dest=None): + if not dest: + dest = src + + # TODO(kbaclawski): rename to producer + self.job = job + self.src = src + self.dest = dest + + @property + def read_only(self): + return self.dest == self.src + + +class JobStateMachine(state_machine.BasicStateMachine): + state_machine = { + STATUS_NOT_EXECUTED: [STATUS_SETUP], + STATUS_SETUP: [STATUS_COPYING, STATUS_FAILED], + STATUS_COPYING: [STATUS_RUNNING, STATUS_FAILED], + STATUS_RUNNING: [STATUS_SUCCEEDED, STATUS_FAILED] + } + + final_states = [STATUS_SUCCEEDED, STATUS_FAILED] + + +class JobFailure(Exception): + + def __init__(self, message, exit_code): + Exception.__init__(self, message) + self.exit_code = exit_code + + +class Job(object): + """A class representing a job whose commands will be executed.""" + + WORKDIR_PREFIX = '/usr/local/google/tmp/automation' + + def __init__(self, label, command, timeout=4 * 60 * 60): + self._state = JobStateMachine(STATUS_NOT_EXECUTED) + self.predecessors = set() + self.successors = set() + self.machine_dependencies = [] + self.folder_dependencies = [] + self.id = 0 + self.machines = [] + self.command = command + self._has_primary_machine_spec = False + self.group = None + self.dry_run = None + self.label = label + self.timeout = timeout + + def _StateGet(self): + return self._state + + def _StateSet(self, new_state): + self._state.Change(new_state) + + status = property(_StateGet, _StateSet) + + @property + def timeline(self): + return self._state.timeline + + def __repr__(self): + return '{%s: %s}' % (self.__class__.__name__, self.id) + + def __str__(self): + res = [] + res.append('%d' % self.id) + res.append('Predecessors:') + res.extend(['%d' % pred.id for pred in self.predecessors]) + res.append('Successors:') + res.extend(['%d' % succ.id for succ in self.successors]) + res.append('Machines:') + res.extend(['%s' % machine for machine in self.machines]) + res.append(self.PrettyFormatCommand()) + res.append('%s' % self.status) + res.append(self.timeline.GetTransitionEventReport()) + return '\n'.join(res) + + @staticmethod + def _FormatCommand(cmd, substitutions): + for pattern, replacement in substitutions: + cmd = cmd.replace(pattern, replacement) + + return cmd + + def GetCommand(self): + substitutions = [ + ('$JOB_ID', str(self.id)), ('$JOB_TMP', self.work_dir), + ('$JOB_HOME', self.home_dir), + ('$PRIMARY_MACHINE', self.primary_machine.hostname) + ] + + if len(self.machines) > 1: + for num, machine in enumerate(self.machines[1:]): + substitutions.append(('$SECONDARY_MACHINES[%d]' % num, machine.hostname + )) + + return self._FormatCommand(str(self.command), substitutions) + + def PrettyFormatCommand(self): + # TODO(kbaclawski): This method doesn't belong here, but rather to + # non existing Command class. If one is created then PrettyFormatCommand + # shall become its method. + return self._FormatCommand(self.GetCommand(), [ + ('\{ ', ''), ('; \}', ''), ('\} ', '\n'), ('\s*&&\s*', '\n') + ]) + + def DependsOnFolder(self, dependency): + self.folder_dependencies.append(dependency) + self.DependsOn(dependency.job) + + @property + def results_dir(self): + return os.path.join(self.work_dir, 'results') + + @property + def logs_dir(self): + return os.path.join(self.home_dir, 'logs') + + @property + def log_filename_prefix(self): + return 'job-%d.log' % self.id + + @property + def work_dir(self): + return os.path.join(self.WORKDIR_PREFIX, 'job-%d' % self.id) + + @property + def home_dir(self): + return os.path.join(self.group.home_dir, 'job-%d' % self.id) + + @property + def primary_machine(self): + return self.machines[0] + + def DependsOn(self, job): + """Specifies Jobs to be finished before this job can be launched.""" + self.predecessors.add(job) + job.successors.add(self) + + @property + def is_ready(self): + """Check that all our dependencies have been executed.""" + return all(pred.status == STATUS_SUCCEEDED for pred in self.predecessors) + + def DependsOnMachine(self, machine_spec, primary=True): + # Job will run on arbitrarily chosen machine specified by + # MachineSpecification class instances passed to this method. + if primary: + if self._has_primary_machine_spec: + raise RuntimeError('Only one primary machine specification allowed.') + self._has_primary_machine_spec = True + self.machine_dependencies.insert(0, machine_spec) + else: + self.machine_dependencies.append(machine_spec) |