blob: d8966e2933f941075d56b63ab0cb8c6e3bf23335 [file] [log] [blame]
Xixuan Wu0c76d5b2017-08-30 16:40:17 -07001# Copyright 2017 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Module for tasks triggered by suite scheduler."""
6# pylint: disable=g-bad-import-order
Xixuan Wu244e0ec2018-05-23 14:49:55 -07007# pylint: disable=dangerous-default-value
Xixuan Wu0c76d5b2017-08-30 16:40:17 -07008
9from distutils import version
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070010import logging
11
12import build_lib
Xinan Lin39dcca82019-07-26 18:55:51 -070013import re
Xixuan Wued878ea2019-03-18 15:32:16 -070014import skylab
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070015import task_executor
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070016import tot_manager
17
18# The max lifetime of a suite scheduled by suite scheduler
19_JOB_MAX_RUNTIME_MINS_DEFAULT = 72 * 60
20
21# One kind of formats for RO firmware spec.
22_RELEASE_RO_FIRMWARE_SPEC = 'released_ro_'
23
24
25class SchedulingError(Exception):
26 """Raised to indicate a failure in scheduling a task."""
27
28
29class Task(object):
30 """Represents an entry from the suite_scheduler config file.
31
32 Each entry from the suite_scheduler config file maps one-to-one to a
33 Task. Each instance has enough information to schedule itself.
34 """
35
Po-Hsien Wangdd833072018-08-16 18:09:20 -070036 def __init__(self, task_info, board_family_config={}, tot=None):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070037 """Initialize a task instance.
38
39 Args:
40 task_info: a config_reader.TaskInfo object, which includes:
41 name, name of this task, e.g. 'NightlyPower'
42 suite, the name of the suite to run, e.g. 'graphics_per-day'
43 branch_specs, a pre-vetted iterable of branch specifiers,
44 e.g. ['>=R18', 'factory']
45 pool, the pool of machines to schedule tasks. Default is None.
46 num, the number of devices to shard the test suite. It could
47 be an Integer or None. By default it's None.
Po-Hsien Wangdd833072018-08-16 18:09:20 -070048 board_families, a common separated list of board family to run this
49 task on. Boards belong to one of the board family in this list
50 would be added to task_info.boards.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070051 boards, a comma separated list of boards to run this task on. Default
Po-Hsien Wangdd833072018-08-16 18:09:20 -070052 is None, which allows this task to run on all boards. If same board
53 is specified in 'boards' and 'exclude_boards', we exclude this
54 board.
55 exclude_board_families, a common separated list of board family not to
56 run task on. Boards belong to one of the board family in this list
57 would be added to task_info.exclude_boards.
Po-Hsien Wang6d589732018-05-15 17:19:34 -070058 exclude_boards, a comma separated list of boards not to run this task
59 on. Default is None, which allows this task to run on all boards.
Po-Hsien Wangdd833072018-08-16 18:09:20 -070060 If same board is specified in 'boards' and 'exclude_boards', we
61 exclude this board.
Xixuan Wu89897182019-01-03 15:28:01 -080062 models, a comma separated list of models to run this task on. Default
63 is None, which allows this task to run on all models. If same model
64 is specified in 'models' and 'exclude_models', we exclude this
65 model.
66 exclude_models, a comma separated list of models not to run this task
67 on. Default is None, which allows this task to run on all models.
C Shapiro09108252019-08-01 14:52:52 -050068 any_model, set to True to not pass the model parameter and allow
69 a test suite to run any/all models available for testing.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070070 priority, the string name of a priority from constants.Priorities.
71 timeout, the max lifetime of the suite in hours.
72 cros_build_spec, spec used to determine the ChromeOS build to test
73 with a firmware build, e.g., tot, R41 etc.
74 firmware_rw_build_spec, spec used to determine the firmware RW build
75 test with a ChromeOS build.
76 firmware_ro_build_spec, spec used to determine the firmware RO build
77 test with a ChromeOS build.
78 test_source, the source of test code when firmware will be updated in
79 the test. The value can be 'firmware_rw', 'firmware_ro' or 'cros'.
80 job_retry, set to True to enable job-level retry. Default is False.
Xixuan Wu80531932017-10-12 17:26:51 -070081 no_delay, set to True to raise the priority of this task in task.
82 force, set to True to schedule this suite no matter whether there's
83 duplicate jobs before.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070084 queue, so the suite jobs can start running tests with no waiting.
85 hour, an integer specifying the hour that a nightly run should be
86 triggered, default is set to 21.
87 day, an integer specifying the day of a week that a weekly run should
88 be triggered, default is set to 5 (Saturday).
89 os_type, type of OS, e.g., cros, brillo, android. Default is cros.
90 The argument is required for android/brillo builds.
91 launch_control_branches, comma separated string of launch control
92 branches. The argument is required and only applicable for
93 android/brillo builds.
94 launch_control_targets, comma separated string of build targets for
95 launch control builds. The argument is required and only
96 applicable for android/brillo builds.
97 testbed_dut_count, number of duts to test when using a testbed.
Xixuan Wu83118dd2018-08-27 12:11:35 -070098 board_family_config: A board family dictionary mapping board_family name
99 to its corresponding boards.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700100 tot: The tot manager for checking ToT. If it's None, a new tot_manager
101 instance will be initialized.
102 """
Xixuan Wu5451a662017-10-17 10:57:40 -0700103 # Indicate whether there're suites get pushed into taskqueue for this task.
104 self.is_pushed = False
105
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700106 self.name = task_info.name
107 self.suite = task_info.suite
108 self.branch_specs = task_info.branch_specs
109 self.pool = task_info.pool
110 self.num = task_info.num
111 self.priority = task_info.priority
112 self.timeout = task_info.timeout
113 self.cros_build_spec = task_info.cros_build_spec
114 self.firmware_rw_build_spec = task_info.firmware_rw_build_spec
115 self.firmware_ro_build_spec = task_info.firmware_ro_build_spec
116 self.test_source = task_info.test_source
117 self.job_retry = task_info.job_retry
118 self.no_delay = task_info.no_delay
Xixuan Wu80531932017-10-12 17:26:51 -0700119 self.force = task_info.force
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700120 self.os_type = task_info.os_type
Xinan Lin3ba18a02019-08-13 15:44:55 -0700121 self.frontdoor = task_info.frontdoor
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700122 self.testbed_dut_count = task_info.testbed_dut_count
Xixuan Wu008ee832017-10-12 16:59:34 -0700123 self.hour = task_info.hour
124 self.day = task_info.day
Craig Bergstrom58263d32018-04-26 14:11:35 -0600125 self.only_hwtest_sanity_required = task_info.only_hwtest_sanity_required
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700126
127 if task_info.lc_branches:
128 self.launch_control_branches = [
129 t.strip() for t in task_info.lc_branches.split(',')]
130 else:
131 self.launch_control_branches = []
132
133 if task_info.lc_targets:
134 self.launch_control_targets = [
135 t.strip() for t in task_info.lc_targets.split(',')]
136 else:
137 self.launch_control_targets = []
138
139 if task_info.boards:
140 self.boards = [t.strip() for t in task_info.boards.split(',')]
141 else:
142 self.boards = []
143
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700144 if task_info.exclude_boards:
145 self.exclude_boards = [
146 t.strip() for t in task_info.exclude_boards.split(',')]
147 else:
148 self.exclude_boards = []
149
Xixuan Wu89897182019-01-03 15:28:01 -0800150 if task_info.models:
151 self.models = [t.strip() for t in task_info.models.split(',')]
152 else:
153 self.models = []
154
155 if task_info.exclude_models:
156 self.exclude_models = [
157 t.strip() for t in task_info.exclude_models.split(',')]
158 else:
159 self.exclude_models = []
160
C Shapiro09108252019-08-01 14:52:52 -0500161 self.any_model = task_info.any_model
162
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700163 if task_info.board_families:
164 # Finetune the allowed boards list with board_families & boards.
165 families = [family.strip()
166 for family in task_info.board_families.split(',')]
167 for family in families:
168 self.boards += board_family_config.get(family, [])
Xixuan Wu89897182019-01-03 15:28:01 -0800169
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700170 if task_info.exclude_board_families:
171 # Finetune the disallowed boards list with exclude_board_families
172 # & exclude_boards.
173 families = [family.strip()
174 for family in task_info.exclude_board_families.split(',')]
175 for family in families:
176 self.exclude_boards += board_family_config.get(family, [])
177
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700178 if tot is None:
179 self.tot_manager = tot_manager.TotMilestoneManager()
180 else:
181 self.tot_manager = tot
182
183 self._set_spec_compare_info()
184
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700185 def schedule(self, launch_control_builds, cros_builds_tuple, configs,
Xixuan Wuc6819012019-05-23 11:34:59 -0700186 build_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700187 """Schedule the task by its settings.
188
189 Args:
190 launch_control_builds: the build dict for Android boards, see
191 return value of |get_launch_control_builds|.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600192 cros_builds_tuple: the two-tuple of build dicts for ChromeOS boards,
193 see return value of |get_cros_builds|.
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700194 configs: a config_reader.Configs object.
Xixuan Wuc6819012019-05-23 11:34:59 -0700195 build_client: a rest_client.BuildBucketBigqueryClient object, to
196 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700197
198 Raises:
199 SchedulingError: if tasks that should be scheduled fail to schedule.
Xixuan Wu5451a662017-10-17 10:57:40 -0700200
201 Returns:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700202 A boolean indicator; true if there were any suites related to this
203 task which got pushed into the suites queue.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700204 """
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700205 assert configs.lab_config is not None
Xixuan Wu5451a662017-10-17 10:57:40 -0700206 self.is_pushed = False
207
Craig Bergstrom58263d32018-04-26 14:11:35 -0600208 branch_builds, relaxed_builds = cros_builds_tuple
209 builds_dict = branch_builds
210 if self.only_hwtest_sanity_required:
211 builds_dict = relaxed_builds
212
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700213 logging.info('######## Scheduling task %s ########', self.name)
214 if self.os_type == build_lib.OS_TYPE_CROS:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600215 if not builds_dict:
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700216 logging.info('No CrOS build to run, skip running.')
217 else:
Xixuan Wuc6819012019-05-23 11:34:59 -0700218 self._schedule_cros_builds(builds_dict, configs, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700219 else:
220 if not launch_control_builds:
221 logging.info('No Android build to run, skip running.')
222 else:
223 self._schedule_launch_control_builds(launch_control_builds)
224
Xixuan Wu5451a662017-10-17 10:57:40 -0700225 return self.is_pushed
226
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700227 def _set_spec_compare_info(self):
228 """Set branch spec compare info for task for further check."""
229 self._bare_branches = []
230 self._version_equal_constraint = False
231 self._version_gte_constraint = False
232 self._version_lte_constraint = False
233
234 if not self.branch_specs:
235 # Any milestone is OK.
236 self._numeric_constraint = version.LooseVersion('0')
237 else:
238 self._numeric_constraint = None
239 for spec in self.branch_specs:
240 if 'tot' in spec.lower():
241 # Convert spec >=tot-1 to >=RXX.
242 tot_str = spec[spec.index('tot'):]
243 spec = spec.replace(
244 tot_str, self.tot_manager.convert_tot_spec(tot_str))
245
246 if spec.startswith('>='):
247 self._numeric_constraint = version.LooseVersion(
248 spec.lstrip('>=R'))
249 self._version_gte_constraint = True
250 elif spec.startswith('<='):
251 self._numeric_constraint = version.LooseVersion(
252 spec.lstrip('<=R'))
253 self._version_lte_constraint = True
254 elif spec.startswith('=='):
255 self._version_equal_constraint = True
256 self._numeric_constraint = version.LooseVersion(
257 spec.lstrip('==R'))
258 else:
259 self._bare_branches.append(spec)
260
261 def _fits_spec(self, branch):
262 """Check if a branch is deemed OK by this task's branch specs.
263
264 Will return whether a branch 'fits' the specifications stored in this task.
265
266 Examples:
267 Assuming tot=R40
268 t = Task('Name', 'suite', ['factory', '>=tot-1'])
269 t._fits_spec('factory') # True
270 t._fits_spec('40') # True
271 t._fits_spec('38') # False
272 t._fits_spec('firmware') # False
273
274 Args:
275 branch: the branch to check.
276
277 Returns:
278 True if branch 'fits' with stored specs, False otherwise.
279 """
280 if branch in build_lib.BARE_BRANCHES:
281 return branch in self._bare_branches
282
283 if self._numeric_constraint:
284 if self._version_equal_constraint:
285 return version.LooseVersion(branch) == self._numeric_constraint
286 elif self._version_gte_constraint:
287 return version.LooseVersion(branch) >= self._numeric_constraint
288 elif self._version_lte_constraint:
289 return version.LooseVersion(branch) <= self._numeric_constraint
290 else:
291 return version.LooseVersion(branch) >= self._numeric_constraint
292 else:
293 return False
294
Xixuan Wu6ec23e32019-05-23 11:56:02 -0700295 def _get_latest_firmware_build(self, spec, board, build_client):
296 """Get the latest firmware build.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700297
298 Args:
299 spec: a string build spec for RO or RW firmware, eg. firmware,
300 cros. For RO firmware, the value can also be released_ro_X.
301 board: the board against which this task will run suite job.
Xixuan Wuc6819012019-05-23 11:34:59 -0700302 build_client: a rest_client.BuildBucketBigqueryClient object, to
303 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700304
305 Returns:
Xinan Lin39dcca82019-07-26 18:55:51 -0700306 A string the latest firmware build. This is the path for the
307 downstream systems to download the built firmware. For "cros"
308 build_type, it is "<board>-release/R<milestone>-<platform>".
309 For "firmware" type, it has the form of
310 "firmware-<board>-1234.56.A-firmwarebranch/RFoo-1.0.0-b123456/<board>".
311
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700312 """
313 build_type = 'release' if spec == 'cros' else spec
Xinan Lin39dcca82019-07-26 18:55:51 -0700314 suffix = ''
Xinan Lin318cf752019-07-19 14:50:23 -0700315 if build_type == 'firmware':
Xinan Lin39dcca82019-07-26 18:55:51 -0700316 artifact = build_client.get_latest_passed_builds_artifact_link_firmware(
317 board)
318 suffix = '/' + board
Xinan Lin318cf752019-07-19 14:50:23 -0700319 else:
Xinan Lin39dcca82019-07-26 18:55:51 -0700320 artifact = build_client.get_latest_passed_builds_artifact_link('%s-%s' %
321 (board, build_type))
322 if artifact is None:
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700323 return None
Xinan Lin39dcca82019-07-26 18:55:51 -0700324
325 ARTIFACT_PATTERN = r'gs://chromeos-image-archive/(?P<firmware_build>.+)'
326 match = re.match(ARTIFACT_PATTERN, artifact)
327 if not match:
328 raise ValueError('Artifact path of firmware is not valid: %s', artifact)
329
330 firmware_build = match.group('firmware_build') + suffix
331 logging.debug('latest firmware build for %s', firmware_build)
332 return firmware_build
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700333
334 def _get_latest_firmware_build_from_lab_config(self, spec, board,
335 lab_config):
336 """Get latest firmware from lab config file.
337
338 Args:
339 spec: a string build spec for RO or RW firmware, eg. firmware,
340 cros. For RO firmware, the value can also be released_ro_X.
341 board: a string board against which this task will run suite job.
342 lab_config: a config.LabConfig object, to read lab config file.
343
344 Returns:
345 A string latest firmware build.
346
347 Raises:
348 ValueError: if no firmware build list is found in lab config file.
349 """
350 index = int(spec[len(_RELEASE_RO_FIRMWARE_SPEC):])
351 released_ro_builds = lab_config.get_firmware_ro_build_list(
352 'RELEASED_RO_BUILDS_%s' % board).split(',')
353 if len(released_ro_builds) < index:
354 raise ValueError('No %dth ro_builds in the lab_config firmware '
355 'list %r' % (index, released_ro_builds))
356
357 logging.debug('Get ro_build: %s', released_ro_builds[index - 1])
358 return released_ro_builds[index - 1]
359
Xixuan Wuc6819012019-05-23 11:34:59 -0700360 def _get_firmware_build(self, spec, board, lab_config, build_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700361 """Get the firmware build name to test with ChromeOS build.
362
363 Args:
364 spec: a string build spec for RO or RW firmware, eg. firmware,
365 cros. For RO firmware, the value can also be released_ro_X.
366 board: a string board against which this task will run suite job.
367 lab_config: a config.LabConfig object, to read lab config file.
Xixuan Wuc6819012019-05-23 11:34:59 -0700368 build_client: a rest_client.BuildBucketBigqueryClient object, to
369 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700370
371 Returns:
372 A string firmware build name.
373
374 Raises:
375 ValueError: if failing to get firmware from lab config file;
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700376 """
377 if not spec or spec == 'stable':
378 # TODO(crbug.com/577316): Query stable RO firmware.
379 logging.debug('%s RO firmware build is not supported.', spec)
380 return None
381
382 try:
383 if spec.startswith(_RELEASE_RO_FIRMWARE_SPEC):
384 # For RO firmware whose value is released_ro_X, where X is the index of
385 # the list defined in lab config file:
386 # CROS/RELEASED_RO_BUILDS_[board].
387 # For example, for spec 'released_ro_2', and lab config file
388 # CROS/RELEASED_RO_BUILDS_veyron_jerry: build1,build2,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600389 # return firmware RO build should be 'build2'.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700390 return self._get_latest_firmware_build_from_lab_config(
391 spec, board, lab_config)
392 else:
Xixuan Wu6ec23e32019-05-23 11:56:02 -0700393 return self._get_latest_firmware_build(spec, board, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700394 except ValueError as e:
395 logging.warning('Failed to get firmware from lab config file'
396 'for spec %s, board %s: %s', spec, board, str(e))
397 return None
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700398
C Shapiro7f24a002017-12-05 14:25:09 -0700399 def _push_suite(
400 self,
401 board=None,
402 model=None,
403 cros_build=None,
404 firmware_rw_build=None,
405 firmware_ro_build=None,
406 test_source_build=None,
407 launch_control_build=None,
Xixuan Wubb74a372018-08-21 17:37:08 -0700408 run_prod_code=False,
Xixuan Wu028f6732019-04-11 14:47:42 -0700409 is_skylab=False,
Xinan Lin3ba18a02019-08-13 15:44:55 -0700410 is_frontdoor=False,
Xixuan Wu028f6732019-04-11 14:47:42 -0700411 override_pool='',
412 override_qs_account=''):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700413 """Schedule suite job for the task by pushing suites to SuiteQueue.
414
415 Args:
416 board: the board against which this suite job run.
C Shapiro7f24a002017-12-05 14:25:09 -0700417 model: the model name for unibuild.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700418 cros_build: the CrOS build of this suite job.
419 firmware_rw_build: Firmware RW build to run this suite job with.
420 firmware_ro_build: Firmware RO build to run this suite job with.
421 test_source_build: Test source build, used for server-side
422 packaging of this suite job.
423 launch_control_build: the launch control build of this suite job.
424 run_prod_code: If True, the suite will run the test code that lives
425 in prod aka the test code currently on the lab servers. If
426 False, the control files and test code for this suite run will
427 be retrieved from the build artifacts. Default is False.
Xixuan Wubb74a372018-08-21 17:37:08 -0700428 is_skylab: If True, schedule this suite to skylab, otherwise schedule
429 it to AFE. Default is False.
Xinan Lin3ba18a02019-08-13 15:44:55 -0700430 is_frontdoor: If True, ignore is_skylab and schedule the test to
431 frontdoor.
Xixuan Wu028f6732019-04-11 14:47:42 -0700432 override_pool: A string to indicate pool of quota scheduler.
433 override_qs_account: A string of quota scheduler account.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700434 """
435 android_build = None
436 testbed_build = None
437
438 if self.testbed_dut_count:
439 launch_control_build = '%s#%d' % (launch_control_build,
440 self.testbed_dut_count)
441 test_source_build = launch_control_build
442 board = '%s-%d' % (board, self.testbed_dut_count)
443
444 if launch_control_build:
445 if not self.testbed_dut_count:
446 android_build = launch_control_build
447 else:
448 testbed_build = launch_control_build
449
450 suite_job_parameters = {
451 'suite': self.suite,
452 'board': board,
C Shapiro7f24a002017-12-05 14:25:09 -0700453 'model': model,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700454 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
455 build_lib.BuildVersionKey.FW_RW_VERSION: firmware_rw_build,
456 build_lib.BuildVersionKey.FW_RO_VERSION: firmware_ro_build,
457 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: android_build,
458 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: testbed_build,
459 'num': self.num,
460 'pool': self.pool,
461 'priority': self.priority,
462 'timeout': self.timeout,
463 'timeout_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
464 'max_runtime_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
Xixuan Wu2ba72652017-09-15 15:49:42 -0700465 'no_wait_for_results': not self.job_retry,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700466 'test_source_build': test_source_build,
467 'job_retry': self.job_retry,
468 'no_delay': self.no_delay,
Xixuan Wu80531932017-10-12 17:26:51 -0700469 'force': self.force,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700470 'run_prod_code': run_prod_code,
Xixuan Wubb74a372018-08-21 17:37:08 -0700471 'is_skylab': is_skylab,
Xinan Lin3ba18a02019-08-13 15:44:55 -0700472 'is_frontdoor': is_frontdoor,
Xixuan Wu028f6732019-04-11 14:47:42 -0700473 'override_pool': override_pool,
474 'override_qs_account': override_qs_account,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700475 }
476
477 task_executor.push(task_executor.SUITES_QUEUE, **suite_job_parameters)
478 logging.info('Pushing task %r into taskqueue', suite_job_parameters)
Xixuan Wu5451a662017-10-17 10:57:40 -0700479 self.is_pushed = True
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700480
Xixuan Wuc6819012019-05-23 11:34:59 -0700481 def _schedule_cros_builds(self, build_dict, configs, build_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700482 """Schedule tasks with branch builds.
483
484 Args:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600485 build_dict: the build dict for ChromeOS boards, see return
Xixuan Wu6ec23e32019-05-23 11:56:02 -0700486 value of |build_lib.get_cros_builds_since_date|.
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700487 configs: A config_reader.Configs object.
Xixuan Wuc6819012019-05-23 11:34:59 -0700488 build_client: a rest_client.BuildBucketBigqueryClient object, to
489 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700490 """
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700491 lab_config = configs.lab_config
C Shapiro7f24a002017-12-05 14:25:09 -0700492 models_by_board = lab_config.get_cros_model_map() if lab_config else {}
C Shapiro09108252019-08-01 14:52:52 -0500493 model_agnostic_cros_builds = set()
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700494 for (board, passed_model, build_type,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600495 milestone), manifest in build_dict.iteritems():
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700496 cros_build = str(build_lib.CrOSBuild(board, build_type, milestone,
497 manifest))
498 logging.info('Running %s on %s', self.name, cros_build)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700499 if self.exclude_boards and board in self.exclude_boards:
500 logging.debug('Board %s is in excluded board list: %s',
501 board, self.exclude_boards)
502 continue
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700503
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700504 if self.boards and board not in self.boards:
505 logging.debug('Board %s is not in supported board list: %s',
506 board, self.boards)
507 continue
508
509 # Check the fitness of the build's branch for task
510 branch_build_spec = _pick_branch(build_type, milestone)
511 if not self._fits_spec(branch_build_spec):
512 logging.debug("branch_build spec %s doesn't fit this task's "
513 "requirement: %s", branch_build_spec, self.branch_specs)
514 continue
515
516 firmware_rw_build = None
517 firmware_ro_build = None
518 if self.firmware_rw_build_spec or self.firmware_ro_build_spec:
519 firmware_rw_build = self._get_firmware_build(
Xixuan Wuc6819012019-05-23 11:34:59 -0700520 self.firmware_rw_build_spec, board, lab_config, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700521 firmware_ro_build = self._get_firmware_build(
Xixuan Wuc6819012019-05-23 11:34:59 -0700522 self.firmware_ro_build_spec, board, lab_config, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700523
524 if not firmware_ro_build and self.firmware_ro_build_spec:
525 logging.debug('No firmware ro build to run, skip running')
526 continue
527
528 if self.test_source == build_lib.BuildType.FIRMWARE_RW:
529 test_source_build = firmware_rw_build
530 else:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700531 # Default test source build to CrOS build if it's not specified.
532 # Past versions chose based on run_prod_code, but we no longer respect
533 # that option and scheduler settings should always set it to False.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700534 test_source_build = cros_build
535
Xixuan Wub4b2f412019-05-03 11:22:31 -0700536 hwtest_board = build_lib.reshape_board(board)
Xixuan Wu1f0be4c2019-03-18 16:53:23 -0700537 is_skylab = skylab.should_run_in_skylab(configs.migration_config,
Xixuan Wub4b2f412019-05-03 11:22:31 -0700538 hwtest_board,
Xixuan Wued878ea2019-03-18 15:32:16 -0700539 passed_model,
Xixuan Wu1e42c752019-03-21 13:41:49 -0700540 self.suite,
541 self.pool)
Xixuan Wu028f6732019-04-11 14:47:42 -0700542 override_pool, override_qs_account = skylab.get_override_info(
543 configs.migration_config,
Xixuan Wub4b2f412019-05-03 11:22:31 -0700544 hwtest_board,
Xixuan Wu028f6732019-04-11 14:47:42 -0700545 passed_model,
546 self.suite,
547 self.pool)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000548 models = models_by_board.get(board, [None])
C Shapiro7f24a002017-12-05 14:25:09 -0700549
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000550 for model in models:
551 if ((passed_model is not None and model == passed_model) or
552 passed_model is None):
Xixuan Wua41efa22019-05-17 14:28:04 -0700553 full_model_name = '%s_%s' % (board, model)
554 # Respect exclude first.
555 if self.exclude_models and full_model_name in self.exclude_models:
556 logging.debug("Skip model %s as it's in exclude model list %s",
557 model, self.exclude_models)
558 continue
559
560 if self.models and full_model_name not in self.models:
561 logging.debug("Skip model %s as it's not in support model list %s",
562 model, self.models)
563 continue
564
C Shapiro09108252019-08-01 14:52:52 -0500565 explicit_model = model
566
567 if self.any_model:
Xinan Lin3ba18a02019-08-13 15:44:55 -0700568 explicit_model = None
C Shapiro09108252019-08-01 14:52:52 -0500569 unique_build = str(cros_build)
570 if unique_build in model_agnostic_cros_builds:
571 # Skip since we've already run with no explicit model set.
572 continue
573 model_agnostic_cros_builds.add(unique_build)
574
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000575 self._push_suite(
Xixuan Wub4b2f412019-05-03 11:22:31 -0700576 board=hwtest_board,
C Shapiro09108252019-08-01 14:52:52 -0500577 model=explicit_model,
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000578 cros_build=cros_build,
579 firmware_rw_build=firmware_rw_build,
580 firmware_ro_build=firmware_ro_build,
581 test_source_build=test_source_build,
Xixuan Wu028f6732019-04-11 14:47:42 -0700582 is_skylab=is_skylab,
583 override_pool=override_pool,
584 override_qs_account=override_qs_account)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700585
586 def _schedule_launch_control_builds(self, launch_control_builds):
587 """Schedule tasks with launch control builds.
588
589 Args:
590 launch_control_builds: the build dict for Android boards.
591 """
592 for board, launch_control_build in launch_control_builds.iteritems():
593 logging.debug('Running %s on %s', self.name, board)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700594 if self.exclude_boards and board in self.exclude_boards:
595 logging.debug('Board %s is in excluded board list: %s',
596 board, self.exclude_boards)
597 continue
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700598 if self.boards and board not in self.boards:
599 logging.debug('Board %s is not in supported board list: %s',
600 board, self.boards)
601 continue
602
603 for android_build in launch_control_build:
604 if not any([branch in android_build
605 for branch in self.launch_control_branches]):
606 logging.debug('Branch %s is not required to run for task '
607 '%s', android_build, self.name)
608 continue
609
610 self._push_suite(board=board,
611 test_source_build=android_build,
612 launch_control_build=android_build)
613
614
615def _pick_branch(build_type, milestone):
616 """Select branch based on build type.
617
618 If the build_type is a bare branch, return build_type as the build spec.
619 If the build_type is a normal CrOS branch, return milestone as the build
620 spec.
621
622 Args:
623 build_type: a string builder name, like 'release'.
624 milestone: a string milestone, like '55'.
625
626 Returns:
627 A string milestone if build_type represents CrOS build, otherwise
628 return build_type.
629 """
630 return build_type if build_type in build_lib.BARE_BRANCHES else milestone