aboutsummaryrefslogtreecommitdiff
path: root/deprecated/automation/common/job.py
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-02-14 03:08:18 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-02-14 03:08:18 +0000
commitdb729d703a0bf8fc92f011d160abd063c338b2f3 (patch)
tree35fa0fbaeaaddd9cc2a126a05eee3527b51e83a8 /deprecated/automation/common/job.py
parentdddbf2c6f79f2334de6d41b86d63698714ba1124 (diff)
parentb75f321fc8978b92ce3db6886ccb966768f0c7a8 (diff)
downloadtoolchain-utils-db729d703a0bf8fc92f011d160abd063c338b2f3.tar.gz
Snap for 6206568 from b75f321fc8978b92ce3db6886ccb966768f0c7a8 to rvc-releaseandroid-vts-11.0_r9android-vts-11.0_r8android-vts-11.0_r7android-vts-11.0_r6android-vts-11.0_r5android-vts-11.0_r4android-vts-11.0_r3android-vts-11.0_r2android-vts-11.0_r16android-vts-11.0_r15android-vts-11.0_r14android-vts-11.0_r13android-vts-11.0_r12android-vts-11.0_r11android-vts-11.0_r10android-vts-11.0_r1android-security-11.0.0_r76android-security-11.0.0_r75android-security-11.0.0_r74android-security-11.0.0_r73android-security-11.0.0_r72android-security-11.0.0_r71android-security-11.0.0_r70android-security-11.0.0_r69android-security-11.0.0_r68android-security-11.0.0_r67android-security-11.0.0_r66android-security-11.0.0_r65android-security-11.0.0_r64android-security-11.0.0_r63android-security-11.0.0_r62android-security-11.0.0_r61android-security-11.0.0_r60android-security-11.0.0_r59android-security-11.0.0_r58android-security-11.0.0_r57android-security-11.0.0_r56android-security-11.0.0_r55android-security-11.0.0_r54android-security-11.0.0_r53android-security-11.0.0_r52android-security-11.0.0_r51android-security-11.0.0_r50android-security-11.0.0_r49android-security-11.0.0_r1android-platform-11.0.0_r9android-platform-11.0.0_r8android-platform-11.0.0_r7android-platform-11.0.0_r6android-platform-11.0.0_r5android-platform-11.0.0_r4android-platform-11.0.0_r3android-platform-11.0.0_r2android-platform-11.0.0_r13android-platform-11.0.0_r12android-platform-11.0.0_r11android-platform-11.0.0_r10android-platform-11.0.0_r1android-cts-11.0_r9android-cts-11.0_r8android-cts-11.0_r7android-cts-11.0_r6android-cts-11.0_r5android-cts-11.0_r4android-cts-11.0_r3android-cts-11.0_r2android-cts-11.0_r16android-cts-11.0_r15android-cts-11.0_r14android-cts-11.0_r13android-cts-11.0_r12android-cts-11.0_r11android-cts-11.0_r10android-cts-11.0_r1android-11.0.0_r6android-11.0.0_r5android-11.0.0_r4android-11.0.0_r3android-11.0.0_r25android-11.0.0_r2android-11.0.0_r17android-11.0.0_r1android11-tests-releaseandroid11-security-releaseandroid11-s1-releaseandroid11-releaseandroid11-platform-releaseandroid11-gsi
Change-Id: I997cf91dd612b5e50d502271baf665232843c30a
Diffstat (limited to 'deprecated/automation/common/job.py')
-rw-r--r--deprecated/automation/common/job.py178
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)