blob: f98bc23d5be20e7ff999fc7c6db59318a8ed8c47 [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
Xixuan Wued878ea2019-03-18 15:32:16 -070013import skylab
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070014import task_executor
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070015import tot_manager
16
17# The max lifetime of a suite scheduled by suite scheduler
18_JOB_MAX_RUNTIME_MINS_DEFAULT = 72 * 60
19
20# One kind of formats for RO firmware spec.
21_RELEASE_RO_FIRMWARE_SPEC = 'released_ro_'
22
23
24class SchedulingError(Exception):
25 """Raised to indicate a failure in scheduling a task."""
26
27
28class Task(object):
29 """Represents an entry from the suite_scheduler config file.
30
31 Each entry from the suite_scheduler config file maps one-to-one to a
32 Task. Each instance has enough information to schedule itself.
33 """
34
Po-Hsien Wangdd833072018-08-16 18:09:20 -070035 def __init__(self, task_info, board_family_config={}, tot=None):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070036 """Initialize a task instance.
37
38 Args:
39 task_info: a config_reader.TaskInfo object, which includes:
40 name, name of this task, e.g. 'NightlyPower'
41 suite, the name of the suite to run, e.g. 'graphics_per-day'
42 branch_specs, a pre-vetted iterable of branch specifiers,
43 e.g. ['>=R18', 'factory']
44 pool, the pool of machines to schedule tasks. Default is None.
45 num, the number of devices to shard the test suite. It could
46 be an Integer or None. By default it's None.
Po-Hsien Wangdd833072018-08-16 18:09:20 -070047 board_families, a common separated list of board family to run this
48 task on. Boards belong to one of the board family in this list
49 would be added to task_info.boards.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070050 boards, a comma separated list of boards to run this task on. Default
Po-Hsien Wangdd833072018-08-16 18:09:20 -070051 is None, which allows this task to run on all boards. If same board
52 is specified in 'boards' and 'exclude_boards', we exclude this
53 board.
54 exclude_board_families, a common separated list of board family not to
55 run task on. Boards belong to one of the board family in this list
56 would be added to task_info.exclude_boards.
Po-Hsien Wang6d589732018-05-15 17:19:34 -070057 exclude_boards, a comma separated list of boards not to run this task
58 on. Default is None, which allows this task to run on all boards.
Po-Hsien Wangdd833072018-08-16 18:09:20 -070059 If same board is specified in 'boards' and 'exclude_boards', we
60 exclude this board.
Xixuan Wu89897182019-01-03 15:28:01 -080061 models, a comma separated list of models to run this task on. Default
62 is None, which allows this task to run on all models. If same model
63 is specified in 'models' and 'exclude_models', we exclude this
64 model.
65 exclude_models, a comma separated list of models not to run this task
66 on. Default is None, which allows this task to run on all models.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070067 priority, the string name of a priority from constants.Priorities.
68 timeout, the max lifetime of the suite in hours.
69 cros_build_spec, spec used to determine the ChromeOS build to test
70 with a firmware build, e.g., tot, R41 etc.
71 firmware_rw_build_spec, spec used to determine the firmware RW build
72 test with a ChromeOS build.
73 firmware_ro_build_spec, spec used to determine the firmware RO build
74 test with a ChromeOS build.
75 test_source, the source of test code when firmware will be updated in
76 the test. The value can be 'firmware_rw', 'firmware_ro' or 'cros'.
77 job_retry, set to True to enable job-level retry. Default is False.
Xixuan Wu80531932017-10-12 17:26:51 -070078 no_delay, set to True to raise the priority of this task in task.
79 force, set to True to schedule this suite no matter whether there's
80 duplicate jobs before.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070081 queue, so the suite jobs can start running tests with no waiting.
82 hour, an integer specifying the hour that a nightly run should be
83 triggered, default is set to 21.
84 day, an integer specifying the day of a week that a weekly run should
85 be triggered, default is set to 5 (Saturday).
86 os_type, type of OS, e.g., cros, brillo, android. Default is cros.
87 The argument is required for android/brillo builds.
88 launch_control_branches, comma separated string of launch control
89 branches. The argument is required and only applicable for
90 android/brillo builds.
91 launch_control_targets, comma separated string of build targets for
92 launch control builds. The argument is required and only
93 applicable for android/brillo builds.
94 testbed_dut_count, number of duts to test when using a testbed.
Xixuan Wu83118dd2018-08-27 12:11:35 -070095 board_family_config: A board family dictionary mapping board_family name
96 to its corresponding boards.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070097 tot: The tot manager for checking ToT. If it's None, a new tot_manager
98 instance will be initialized.
99 """
Xixuan Wu5451a662017-10-17 10:57:40 -0700100 # Indicate whether there're suites get pushed into taskqueue for this task.
101 self.is_pushed = False
102
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700103 self.name = task_info.name
104 self.suite = task_info.suite
105 self.branch_specs = task_info.branch_specs
106 self.pool = task_info.pool
107 self.num = task_info.num
108 self.priority = task_info.priority
109 self.timeout = task_info.timeout
110 self.cros_build_spec = task_info.cros_build_spec
111 self.firmware_rw_build_spec = task_info.firmware_rw_build_spec
112 self.firmware_ro_build_spec = task_info.firmware_ro_build_spec
113 self.test_source = task_info.test_source
114 self.job_retry = task_info.job_retry
115 self.no_delay = task_info.no_delay
Xixuan Wu80531932017-10-12 17:26:51 -0700116 self.force = task_info.force
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700117 self.os_type = task_info.os_type
118 self.testbed_dut_count = task_info.testbed_dut_count
Xixuan Wu008ee832017-10-12 16:59:34 -0700119 self.hour = task_info.hour
120 self.day = task_info.day
Craig Bergstrom58263d32018-04-26 14:11:35 -0600121 self.only_hwtest_sanity_required = task_info.only_hwtest_sanity_required
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700122
123 if task_info.lc_branches:
124 self.launch_control_branches = [
125 t.strip() for t in task_info.lc_branches.split(',')]
126 else:
127 self.launch_control_branches = []
128
129 if task_info.lc_targets:
130 self.launch_control_targets = [
131 t.strip() for t in task_info.lc_targets.split(',')]
132 else:
133 self.launch_control_targets = []
134
135 if task_info.boards:
136 self.boards = [t.strip() for t in task_info.boards.split(',')]
137 else:
138 self.boards = []
139
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700140 if task_info.exclude_boards:
141 self.exclude_boards = [
142 t.strip() for t in task_info.exclude_boards.split(',')]
143 else:
144 self.exclude_boards = []
145
Xixuan Wu89897182019-01-03 15:28:01 -0800146 if task_info.models:
147 self.models = [t.strip() for t in task_info.models.split(',')]
148 else:
149 self.models = []
150
151 if task_info.exclude_models:
152 self.exclude_models = [
153 t.strip() for t in task_info.exclude_models.split(',')]
154 else:
155 self.exclude_models = []
156
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700157 if task_info.board_families:
158 # Finetune the allowed boards list with board_families & boards.
159 families = [family.strip()
160 for family in task_info.board_families.split(',')]
161 for family in families:
162 self.boards += board_family_config.get(family, [])
Xixuan Wu89897182019-01-03 15:28:01 -0800163
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700164 if task_info.exclude_board_families:
165 # Finetune the disallowed boards list with exclude_board_families
166 # & exclude_boards.
167 families = [family.strip()
168 for family in task_info.exclude_board_families.split(',')]
169 for family in families:
170 self.exclude_boards += board_family_config.get(family, [])
171
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700172 if tot is None:
173 self.tot_manager = tot_manager.TotMilestoneManager()
174 else:
175 self.tot_manager = tot
176
177 self._set_spec_compare_info()
178
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700179 def schedule(self, launch_control_builds, cros_builds_tuple, configs,
Xixuan Wuc6819012019-05-23 11:34:59 -0700180 build_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700181 """Schedule the task by its settings.
182
183 Args:
184 launch_control_builds: the build dict for Android boards, see
185 return value of |get_launch_control_builds|.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600186 cros_builds_tuple: the two-tuple of build dicts for ChromeOS boards,
187 see return value of |get_cros_builds|.
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700188 configs: a config_reader.Configs object.
Xixuan Wuc6819012019-05-23 11:34:59 -0700189 build_client: a rest_client.BuildBucketBigqueryClient object, to
190 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700191
192 Raises:
193 SchedulingError: if tasks that should be scheduled fail to schedule.
Xixuan Wu5451a662017-10-17 10:57:40 -0700194
195 Returns:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700196 A boolean indicator; true if there were any suites related to this
197 task which got pushed into the suites queue.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700198 """
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700199 assert configs.lab_config is not None
Xixuan Wu5451a662017-10-17 10:57:40 -0700200 self.is_pushed = False
201
Craig Bergstrom58263d32018-04-26 14:11:35 -0600202 branch_builds, relaxed_builds = cros_builds_tuple
203 builds_dict = branch_builds
204 if self.only_hwtest_sanity_required:
205 builds_dict = relaxed_builds
206
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700207 logging.info('######## Scheduling task %s ########', self.name)
208 if self.os_type == build_lib.OS_TYPE_CROS:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600209 if not builds_dict:
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700210 logging.info('No CrOS build to run, skip running.')
211 else:
Xixuan Wuc6819012019-05-23 11:34:59 -0700212 self._schedule_cros_builds(builds_dict, configs, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700213 else:
214 if not launch_control_builds:
215 logging.info('No Android build to run, skip running.')
216 else:
217 self._schedule_launch_control_builds(launch_control_builds)
218
Xixuan Wu5451a662017-10-17 10:57:40 -0700219 return self.is_pushed
220
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700221 def _set_spec_compare_info(self):
222 """Set branch spec compare info for task for further check."""
223 self._bare_branches = []
224 self._version_equal_constraint = False
225 self._version_gte_constraint = False
226 self._version_lte_constraint = False
227
228 if not self.branch_specs:
229 # Any milestone is OK.
230 self._numeric_constraint = version.LooseVersion('0')
231 else:
232 self._numeric_constraint = None
233 for spec in self.branch_specs:
234 if 'tot' in spec.lower():
235 # Convert spec >=tot-1 to >=RXX.
236 tot_str = spec[spec.index('tot'):]
237 spec = spec.replace(
238 tot_str, self.tot_manager.convert_tot_spec(tot_str))
239
240 if spec.startswith('>='):
241 self._numeric_constraint = version.LooseVersion(
242 spec.lstrip('>=R'))
243 self._version_gte_constraint = True
244 elif spec.startswith('<='):
245 self._numeric_constraint = version.LooseVersion(
246 spec.lstrip('<=R'))
247 self._version_lte_constraint = True
248 elif spec.startswith('=='):
249 self._version_equal_constraint = True
250 self._numeric_constraint = version.LooseVersion(
251 spec.lstrip('==R'))
252 else:
253 self._bare_branches.append(spec)
254
255 def _fits_spec(self, branch):
256 """Check if a branch is deemed OK by this task's branch specs.
257
258 Will return whether a branch 'fits' the specifications stored in this task.
259
260 Examples:
261 Assuming tot=R40
262 t = Task('Name', 'suite', ['factory', '>=tot-1'])
263 t._fits_spec('factory') # True
264 t._fits_spec('40') # True
265 t._fits_spec('38') # False
266 t._fits_spec('firmware') # False
267
268 Args:
269 branch: the branch to check.
270
271 Returns:
272 True if branch 'fits' with stored specs, False otherwise.
273 """
274 if branch in build_lib.BARE_BRANCHES:
275 return branch in self._bare_branches
276
277 if self._numeric_constraint:
278 if self._version_equal_constraint:
279 return version.LooseVersion(branch) == self._numeric_constraint
280 elif self._version_gte_constraint:
281 return version.LooseVersion(branch) >= self._numeric_constraint
282 elif self._version_lte_constraint:
283 return version.LooseVersion(branch) <= self._numeric_constraint
284 else:
285 return version.LooseVersion(branch) >= self._numeric_constraint
286 else:
287 return False
288
Xixuan Wu6ec23e32019-05-23 11:56:02 -0700289 def _get_latest_firmware_build(self, spec, board, build_client):
290 """Get the latest firmware build.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700291
292 Args:
293 spec: a string build spec for RO or RW firmware, eg. firmware,
294 cros. For RO firmware, the value can also be released_ro_X.
295 board: the board against which this task will run suite job.
Xixuan Wuc6819012019-05-23 11:34:59 -0700296 build_client: a rest_client.BuildBucketBigqueryClient object, to
297 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700298
299 Returns:
300 the latest firmware build.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700301 """
302 build_type = 'release' if spec == 'cros' else spec
Xinan Lin318cf752019-07-19 14:50:23 -0700303 # TODO(linxinan): Firmware has changed its build config from <board>-firmware
304 # to <branch>-firmwarebranch. Create a new query for firmware to re-enable
305 # its suite tests. Revisit this, if we decide to (or not) replace build
306 # config for all build types.
307 if build_type == 'firmware':
308 build = build_client.get_latest_passed_builds_firmware(board)
309 else:
310 build = build_client.get_latest_passed_builds('%s-%s' %
311 (board, build_type))
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700312
313 if build is None:
314 return None
315 else:
316 latest_build = str(build_lib.CrOSBuild(
317 board, build_type, build.milestone, build.platform))
318 logging.debug('latest firmware build for %s-%s: %s', board,
319 build_type, latest_build)
320 return latest_build
321
322 def _get_latest_firmware_build_from_lab_config(self, spec, board,
323 lab_config):
324 """Get latest firmware from lab config file.
325
326 Args:
327 spec: a string build spec for RO or RW firmware, eg. firmware,
328 cros. For RO firmware, the value can also be released_ro_X.
329 board: a string board against which this task will run suite job.
330 lab_config: a config.LabConfig object, to read lab config file.
331
332 Returns:
333 A string latest firmware build.
334
335 Raises:
336 ValueError: if no firmware build list is found in lab config file.
337 """
338 index = int(spec[len(_RELEASE_RO_FIRMWARE_SPEC):])
339 released_ro_builds = lab_config.get_firmware_ro_build_list(
340 'RELEASED_RO_BUILDS_%s' % board).split(',')
341 if len(released_ro_builds) < index:
342 raise ValueError('No %dth ro_builds in the lab_config firmware '
343 'list %r' % (index, released_ro_builds))
344
345 logging.debug('Get ro_build: %s', released_ro_builds[index - 1])
346 return released_ro_builds[index - 1]
347
Xixuan Wuc6819012019-05-23 11:34:59 -0700348 def _get_firmware_build(self, spec, board, lab_config, build_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700349 """Get the firmware build name to test with ChromeOS build.
350
351 Args:
352 spec: a string build spec for RO or RW firmware, eg. firmware,
353 cros. For RO firmware, the value can also be released_ro_X.
354 board: a string board against which this task will run suite job.
355 lab_config: a config.LabConfig object, to read lab config file.
Xixuan Wuc6819012019-05-23 11:34:59 -0700356 build_client: a rest_client.BuildBucketBigqueryClient object, to
357 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700358
359 Returns:
360 A string firmware build name.
361
362 Raises:
363 ValueError: if failing to get firmware from lab config file;
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700364 """
365 if not spec or spec == 'stable':
366 # TODO(crbug.com/577316): Query stable RO firmware.
367 logging.debug('%s RO firmware build is not supported.', spec)
368 return None
369
370 try:
371 if spec.startswith(_RELEASE_RO_FIRMWARE_SPEC):
372 # For RO firmware whose value is released_ro_X, where X is the index of
373 # the list defined in lab config file:
374 # CROS/RELEASED_RO_BUILDS_[board].
375 # For example, for spec 'released_ro_2', and lab config file
376 # CROS/RELEASED_RO_BUILDS_veyron_jerry: build1,build2,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600377 # return firmware RO build should be 'build2'.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700378 return self._get_latest_firmware_build_from_lab_config(
379 spec, board, lab_config)
380 else:
Xixuan Wu6ec23e32019-05-23 11:56:02 -0700381 return self._get_latest_firmware_build(spec, board, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700382 except ValueError as e:
383 logging.warning('Failed to get firmware from lab config file'
384 'for spec %s, board %s: %s', spec, board, str(e))
385 return None
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700386
C Shapiro7f24a002017-12-05 14:25:09 -0700387 def _push_suite(
388 self,
389 board=None,
390 model=None,
391 cros_build=None,
392 firmware_rw_build=None,
393 firmware_ro_build=None,
394 test_source_build=None,
395 launch_control_build=None,
Xixuan Wubb74a372018-08-21 17:37:08 -0700396 run_prod_code=False,
Xixuan Wu028f6732019-04-11 14:47:42 -0700397 is_skylab=False,
398 override_pool='',
399 override_qs_account=''):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700400 """Schedule suite job for the task by pushing suites to SuiteQueue.
401
402 Args:
403 board: the board against which this suite job run.
C Shapiro7f24a002017-12-05 14:25:09 -0700404 model: the model name for unibuild.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700405 cros_build: the CrOS build of this suite job.
406 firmware_rw_build: Firmware RW build to run this suite job with.
407 firmware_ro_build: Firmware RO build to run this suite job with.
408 test_source_build: Test source build, used for server-side
409 packaging of this suite job.
410 launch_control_build: the launch control build of this suite job.
411 run_prod_code: If True, the suite will run the test code that lives
412 in prod aka the test code currently on the lab servers. If
413 False, the control files and test code for this suite run will
414 be retrieved from the build artifacts. Default is False.
Xixuan Wubb74a372018-08-21 17:37:08 -0700415 is_skylab: If True, schedule this suite to skylab, otherwise schedule
416 it to AFE. Default is False.
Xixuan Wu028f6732019-04-11 14:47:42 -0700417 override_pool: A string to indicate pool of quota scheduler.
418 override_qs_account: A string of quota scheduler account.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700419 """
420 android_build = None
421 testbed_build = None
422
423 if self.testbed_dut_count:
424 launch_control_build = '%s#%d' % (launch_control_build,
425 self.testbed_dut_count)
426 test_source_build = launch_control_build
427 board = '%s-%d' % (board, self.testbed_dut_count)
428
429 if launch_control_build:
430 if not self.testbed_dut_count:
431 android_build = launch_control_build
432 else:
433 testbed_build = launch_control_build
434
435 suite_job_parameters = {
436 'suite': self.suite,
437 'board': board,
C Shapiro7f24a002017-12-05 14:25:09 -0700438 'model': model,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700439 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
440 build_lib.BuildVersionKey.FW_RW_VERSION: firmware_rw_build,
441 build_lib.BuildVersionKey.FW_RO_VERSION: firmware_ro_build,
442 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: android_build,
443 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: testbed_build,
444 'num': self.num,
445 'pool': self.pool,
446 'priority': self.priority,
447 'timeout': self.timeout,
448 'timeout_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
449 'max_runtime_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
Xixuan Wu2ba72652017-09-15 15:49:42 -0700450 'no_wait_for_results': not self.job_retry,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700451 'test_source_build': test_source_build,
452 'job_retry': self.job_retry,
453 'no_delay': self.no_delay,
Xixuan Wu80531932017-10-12 17:26:51 -0700454 'force': self.force,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700455 'run_prod_code': run_prod_code,
Xixuan Wubb74a372018-08-21 17:37:08 -0700456 'is_skylab': is_skylab,
Xixuan Wu028f6732019-04-11 14:47:42 -0700457 'override_pool': override_pool,
458 'override_qs_account': override_qs_account,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700459 }
460
461 task_executor.push(task_executor.SUITES_QUEUE, **suite_job_parameters)
462 logging.info('Pushing task %r into taskqueue', suite_job_parameters)
Xixuan Wu5451a662017-10-17 10:57:40 -0700463 self.is_pushed = True
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700464
Xixuan Wuc6819012019-05-23 11:34:59 -0700465 def _schedule_cros_builds(self, build_dict, configs, build_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700466 """Schedule tasks with branch builds.
467
468 Args:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600469 build_dict: the build dict for ChromeOS boards, see return
Xixuan Wu6ec23e32019-05-23 11:56:02 -0700470 value of |build_lib.get_cros_builds_since_date|.
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700471 configs: A config_reader.Configs object.
Xixuan Wuc6819012019-05-23 11:34:59 -0700472 build_client: a rest_client.BuildBucketBigqueryClient object, to
473 connect Buildbucket Bigquery.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700474 """
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700475 lab_config = configs.lab_config
C Shapiro7f24a002017-12-05 14:25:09 -0700476 models_by_board = lab_config.get_cros_model_map() if lab_config else {}
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700477 for (board, passed_model, build_type,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600478 milestone), manifest in build_dict.iteritems():
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700479 cros_build = str(build_lib.CrOSBuild(board, build_type, milestone,
480 manifest))
481 logging.info('Running %s on %s', self.name, cros_build)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700482 if self.exclude_boards and board in self.exclude_boards:
483 logging.debug('Board %s is in excluded board list: %s',
484 board, self.exclude_boards)
485 continue
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700486
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700487 if self.boards and board not in self.boards:
488 logging.debug('Board %s is not in supported board list: %s',
489 board, self.boards)
490 continue
491
492 # Check the fitness of the build's branch for task
493 branch_build_spec = _pick_branch(build_type, milestone)
494 if not self._fits_spec(branch_build_spec):
495 logging.debug("branch_build spec %s doesn't fit this task's "
496 "requirement: %s", branch_build_spec, self.branch_specs)
497 continue
498
499 firmware_rw_build = None
500 firmware_ro_build = None
501 if self.firmware_rw_build_spec or self.firmware_ro_build_spec:
502 firmware_rw_build = self._get_firmware_build(
Xixuan Wuc6819012019-05-23 11:34:59 -0700503 self.firmware_rw_build_spec, board, lab_config, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700504 firmware_ro_build = self._get_firmware_build(
Xixuan Wuc6819012019-05-23 11:34:59 -0700505 self.firmware_ro_build_spec, board, lab_config, build_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700506
507 if not firmware_ro_build and self.firmware_ro_build_spec:
508 logging.debug('No firmware ro build to run, skip running')
509 continue
510
511 if self.test_source == build_lib.BuildType.FIRMWARE_RW:
512 test_source_build = firmware_rw_build
513 else:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700514 # Default test source build to CrOS build if it's not specified.
515 # Past versions chose based on run_prod_code, but we no longer respect
516 # that option and scheduler settings should always set it to False.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700517 test_source_build = cros_build
518
Xixuan Wub4b2f412019-05-03 11:22:31 -0700519 hwtest_board = build_lib.reshape_board(board)
Xixuan Wu1f0be4c2019-03-18 16:53:23 -0700520 is_skylab = skylab.should_run_in_skylab(configs.migration_config,
Xixuan Wub4b2f412019-05-03 11:22:31 -0700521 hwtest_board,
Xixuan Wued878ea2019-03-18 15:32:16 -0700522 passed_model,
Xixuan Wu1e42c752019-03-21 13:41:49 -0700523 self.suite,
524 self.pool)
Xixuan Wu028f6732019-04-11 14:47:42 -0700525 override_pool, override_qs_account = skylab.get_override_info(
526 configs.migration_config,
Xixuan Wub4b2f412019-05-03 11:22:31 -0700527 hwtest_board,
Xixuan Wu028f6732019-04-11 14:47:42 -0700528 passed_model,
529 self.suite,
530 self.pool)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000531 models = models_by_board.get(board, [None])
C Shapiro7f24a002017-12-05 14:25:09 -0700532
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000533 for model in models:
534 if ((passed_model is not None and model == passed_model) or
535 passed_model is None):
Xixuan Wua41efa22019-05-17 14:28:04 -0700536 full_model_name = '%s_%s' % (board, model)
537 # Respect exclude first.
538 if self.exclude_models and full_model_name in self.exclude_models:
539 logging.debug("Skip model %s as it's in exclude model list %s",
540 model, self.exclude_models)
541 continue
542
543 if self.models and full_model_name not in self.models:
544 logging.debug("Skip model %s as it's not in support model list %s",
545 model, self.models)
546 continue
547
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000548 self._push_suite(
Xixuan Wub4b2f412019-05-03 11:22:31 -0700549 board=hwtest_board,
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000550 model=model,
551 cros_build=cros_build,
552 firmware_rw_build=firmware_rw_build,
553 firmware_ro_build=firmware_ro_build,
554 test_source_build=test_source_build,
Xixuan Wu028f6732019-04-11 14:47:42 -0700555 is_skylab=is_skylab,
556 override_pool=override_pool,
557 override_qs_account=override_qs_account)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700558
559 def _schedule_launch_control_builds(self, launch_control_builds):
560 """Schedule tasks with launch control builds.
561
562 Args:
563 launch_control_builds: the build dict for Android boards.
564 """
565 for board, launch_control_build in launch_control_builds.iteritems():
566 logging.debug('Running %s on %s', self.name, board)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700567 if self.exclude_boards and board in self.exclude_boards:
568 logging.debug('Board %s is in excluded board list: %s',
569 board, self.exclude_boards)
570 continue
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700571 if self.boards and board not in self.boards:
572 logging.debug('Board %s is not in supported board list: %s',
573 board, self.boards)
574 continue
575
576 for android_build in launch_control_build:
577 if not any([branch in android_build
578 for branch in self.launch_control_branches]):
579 logging.debug('Branch %s is not required to run for task '
580 '%s', android_build, self.name)
581 continue
582
583 self._push_suite(board=board,
584 test_source_build=android_build,
585 launch_control_build=android_build)
586
587
588def _pick_branch(build_type, milestone):
589 """Select branch based on build type.
590
591 If the build_type is a bare branch, return build_type as the build spec.
592 If the build_type is a normal CrOS branch, return milestone as the build
593 spec.
594
595 Args:
596 build_type: a string builder name, like 'release'.
597 milestone: a string milestone, like '55'.
598
599 Returns:
600 A string milestone if build_type represents CrOS build, otherwise
601 return build_type.
602 """
603 return build_type if build_type in build_lib.BARE_BRANCHES else milestone