blob: 419c950b45c9448f5e2ca6ac30d71a616c18fd14 [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
10import MySQLdb
11import logging
12
13import build_lib
14import 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
Craig Bergstrom58263d32018-04-26 14:11:35 -0600179 def schedule(self, launch_control_builds, cros_builds_tuple, lab_config,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700180 db_client):
181 """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 Wu0c76d5b2017-08-30 16:40:17 -0700188 lab_config: a config.LabConfig object, to read lab config file.
189 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
190
191 Raises:
192 SchedulingError: if tasks that should be scheduled fail to schedule.
Xixuan Wu5451a662017-10-17 10:57:40 -0700193
194 Returns:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700195 A boolean indicator; true if there were any suites related to this
196 task which got pushed into the suites queue.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700197 """
198 assert lab_config is not None
Xixuan Wu5451a662017-10-17 10:57:40 -0700199 self.is_pushed = False
200
Craig Bergstrom58263d32018-04-26 14:11:35 -0600201 branch_builds, relaxed_builds = cros_builds_tuple
202 builds_dict = branch_builds
203 if self.only_hwtest_sanity_required:
204 builds_dict = relaxed_builds
205
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700206 logging.info('######## Scheduling task %s ########', self.name)
207 if self.os_type == build_lib.OS_TYPE_CROS:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600208 if not builds_dict:
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700209 logging.info('No CrOS build to run, skip running.')
210 else:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600211 self._schedule_cros_builds(builds_dict, lab_config, db_client)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700212 else:
213 if not launch_control_builds:
214 logging.info('No Android build to run, skip running.')
215 else:
216 self._schedule_launch_control_builds(launch_control_builds)
217
Xixuan Wu5451a662017-10-17 10:57:40 -0700218 return self.is_pushed
219
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700220 def _set_spec_compare_info(self):
221 """Set branch spec compare info for task for further check."""
222 self._bare_branches = []
223 self._version_equal_constraint = False
224 self._version_gte_constraint = False
225 self._version_lte_constraint = False
226
227 if not self.branch_specs:
228 # Any milestone is OK.
229 self._numeric_constraint = version.LooseVersion('0')
230 else:
231 self._numeric_constraint = None
232 for spec in self.branch_specs:
233 if 'tot' in spec.lower():
234 # Convert spec >=tot-1 to >=RXX.
235 tot_str = spec[spec.index('tot'):]
236 spec = spec.replace(
237 tot_str, self.tot_manager.convert_tot_spec(tot_str))
238
239 if spec.startswith('>='):
240 self._numeric_constraint = version.LooseVersion(
241 spec.lstrip('>=R'))
242 self._version_gte_constraint = True
243 elif spec.startswith('<='):
244 self._numeric_constraint = version.LooseVersion(
245 spec.lstrip('<=R'))
246 self._version_lte_constraint = True
247 elif spec.startswith('=='):
248 self._version_equal_constraint = True
249 self._numeric_constraint = version.LooseVersion(
250 spec.lstrip('==R'))
251 else:
252 self._bare_branches.append(spec)
253
254 def _fits_spec(self, branch):
255 """Check if a branch is deemed OK by this task's branch specs.
256
257 Will return whether a branch 'fits' the specifications stored in this task.
258
259 Examples:
260 Assuming tot=R40
261 t = Task('Name', 'suite', ['factory', '>=tot-1'])
262 t._fits_spec('factory') # True
263 t._fits_spec('40') # True
264 t._fits_spec('38') # False
265 t._fits_spec('firmware') # False
266
267 Args:
268 branch: the branch to check.
269
270 Returns:
271 True if branch 'fits' with stored specs, False otherwise.
272 """
273 if branch in build_lib.BARE_BRANCHES:
274 return branch in self._bare_branches
275
276 if self._numeric_constraint:
277 if self._version_equal_constraint:
278 return version.LooseVersion(branch) == self._numeric_constraint
279 elif self._version_gte_constraint:
280 return version.LooseVersion(branch) >= self._numeric_constraint
281 elif self._version_lte_constraint:
282 return version.LooseVersion(branch) <= self._numeric_constraint
283 else:
284 return version.LooseVersion(branch) >= self._numeric_constraint
285 else:
286 return False
287
288 def _get_latest_firmware_build_from_db(self, spec, board, db_client):
289 """Get the latest firmware build from CIDB database.
290
291 Args:
292 spec: a string build spec for RO or RW firmware, eg. firmware,
293 cros. For RO firmware, the value can also be released_ro_X.
294 board: the board against which this task will run suite job.
295 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
296
297 Returns:
298 the latest firmware build.
299
300 Raises:
301 MySQLdb.OperationalError: if connection operations are not valid.
302 """
303 build_type = 'release' if spec == 'cros' else spec
304 # TODO(xixuan): not all firmware are saved in cidb.
305 build = db_client.get_latest_passed_builds('%s-%s' % (board, build_type))
306
307 if build is None:
308 return None
309 else:
310 latest_build = str(build_lib.CrOSBuild(
311 board, build_type, build.milestone, build.platform))
312 logging.debug('latest firmware build for %s-%s: %s', board,
313 build_type, latest_build)
314 return latest_build
315
316 def _get_latest_firmware_build_from_lab_config(self, spec, board,
317 lab_config):
318 """Get latest firmware from lab config file.
319
320 Args:
321 spec: a string build spec for RO or RW firmware, eg. firmware,
322 cros. For RO firmware, the value can also be released_ro_X.
323 board: a string board against which this task will run suite job.
324 lab_config: a config.LabConfig object, to read lab config file.
325
326 Returns:
327 A string latest firmware build.
328
329 Raises:
330 ValueError: if no firmware build list is found in lab config file.
331 """
332 index = int(spec[len(_RELEASE_RO_FIRMWARE_SPEC):])
333 released_ro_builds = lab_config.get_firmware_ro_build_list(
334 'RELEASED_RO_BUILDS_%s' % board).split(',')
335 if len(released_ro_builds) < index:
336 raise ValueError('No %dth ro_builds in the lab_config firmware '
337 'list %r' % (index, released_ro_builds))
338
339 logging.debug('Get ro_build: %s', released_ro_builds[index - 1])
340 return released_ro_builds[index - 1]
341
342 def _get_firmware_build(self, spec, board, lab_config, db_client):
343 """Get the firmware build name to test with ChromeOS build.
344
345 Args:
346 spec: a string build spec for RO or RW firmware, eg. firmware,
347 cros. For RO firmware, the value can also be released_ro_X.
348 board: a string board against which this task will run suite job.
349 lab_config: a config.LabConfig object, to read lab config file.
350 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
351
352 Returns:
353 A string firmware build name.
354
355 Raises:
356 ValueError: if failing to get firmware from lab config file;
357 MySQLdb.OperationalError: if DB connection is not available.
358 """
359 if not spec or spec == 'stable':
360 # TODO(crbug.com/577316): Query stable RO firmware.
361 logging.debug('%s RO firmware build is not supported.', spec)
362 return None
363
364 try:
365 if spec.startswith(_RELEASE_RO_FIRMWARE_SPEC):
366 # For RO firmware whose value is released_ro_X, where X is the index of
367 # the list defined in lab config file:
368 # CROS/RELEASED_RO_BUILDS_[board].
369 # For example, for spec 'released_ro_2', and lab config file
370 # CROS/RELEASED_RO_BUILDS_veyron_jerry: build1,build2,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600371 # return firmware RO build should be 'build2'.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700372 return self._get_latest_firmware_build_from_lab_config(
373 spec, board, lab_config)
374 else:
375 return self._get_latest_firmware_build_from_db(spec, board, db_client)
376 except ValueError as e:
377 logging.warning('Failed to get firmware from lab config file'
378 'for spec %s, board %s: %s', spec, board, str(e))
379 return None
380 except MySQLdb.OperationalError as e:
381 logging.warning('Failed to get firmware from cidb for spec %s, '
382 'board %s: %s', spec, board, str(e))
383 return None
384
C Shapiro7f24a002017-12-05 14:25:09 -0700385 def _push_suite(
386 self,
387 board=None,
388 model=None,
389 cros_build=None,
390 firmware_rw_build=None,
391 firmware_ro_build=None,
392 test_source_build=None,
393 launch_control_build=None,
Xixuan Wubb74a372018-08-21 17:37:08 -0700394 run_prod_code=False,
395 is_skylab=False):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700396 """Schedule suite job for the task by pushing suites to SuiteQueue.
397
398 Args:
399 board: the board against which this suite job run.
C Shapiro7f24a002017-12-05 14:25:09 -0700400 model: the model name for unibuild.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700401 cros_build: the CrOS build of this suite job.
402 firmware_rw_build: Firmware RW build to run this suite job with.
403 firmware_ro_build: Firmware RO build to run this suite job with.
404 test_source_build: Test source build, used for server-side
405 packaging of this suite job.
406 launch_control_build: the launch control build of this suite job.
407 run_prod_code: If True, the suite will run the test code that lives
408 in prod aka the test code currently on the lab servers. If
409 False, the control files and test code for this suite run will
410 be retrieved from the build artifacts. Default is False.
Xixuan Wubb74a372018-08-21 17:37:08 -0700411 is_skylab: If True, schedule this suite to skylab, otherwise schedule
412 it to AFE. Default is False.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700413 """
414 android_build = None
415 testbed_build = None
416
417 if self.testbed_dut_count:
418 launch_control_build = '%s#%d' % (launch_control_build,
419 self.testbed_dut_count)
420 test_source_build = launch_control_build
421 board = '%s-%d' % (board, self.testbed_dut_count)
422
423 if launch_control_build:
424 if not self.testbed_dut_count:
425 android_build = launch_control_build
426 else:
427 testbed_build = launch_control_build
428
429 suite_job_parameters = {
430 'suite': self.suite,
431 'board': board,
C Shapiro7f24a002017-12-05 14:25:09 -0700432 'model': model,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700433 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
434 build_lib.BuildVersionKey.FW_RW_VERSION: firmware_rw_build,
435 build_lib.BuildVersionKey.FW_RO_VERSION: firmware_ro_build,
436 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: android_build,
437 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: testbed_build,
438 'num': self.num,
439 'pool': self.pool,
440 'priority': self.priority,
441 'timeout': self.timeout,
442 'timeout_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
443 'max_runtime_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
Xixuan Wu2ba72652017-09-15 15:49:42 -0700444 'no_wait_for_results': not self.job_retry,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700445 'test_source_build': test_source_build,
446 'job_retry': self.job_retry,
447 'no_delay': self.no_delay,
Xixuan Wu80531932017-10-12 17:26:51 -0700448 'force': self.force,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700449 'run_prod_code': run_prod_code,
Xixuan Wubb74a372018-08-21 17:37:08 -0700450 'is_skylab': is_skylab,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700451 }
452
453 task_executor.push(task_executor.SUITES_QUEUE, **suite_job_parameters)
454 logging.info('Pushing task %r into taskqueue', suite_job_parameters)
Xixuan Wu5451a662017-10-17 10:57:40 -0700455 self.is_pushed = True
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700456
Craig Bergstrom58263d32018-04-26 14:11:35 -0600457 def _schedule_cros_builds(self, build_dict, lab_config, db_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700458 """Schedule tasks with branch builds.
459
460 Args:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600461 build_dict: the build dict for ChromeOS boards, see return
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700462 value of |build_lib.get_cros_builds_since_date_from_db|.
463 lab_config: a config.LabConfig object, to read lab config file.
464 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
465 """
C Shapiro7f24a002017-12-05 14:25:09 -0700466 models_by_board = lab_config.get_cros_model_map() if lab_config else {}
Xixuan Wubb74a372018-08-21 17:37:08 -0700467 skylab_boards = lab_config.get_skylab_board_list() if lab_config else []
Xixuan Wu446b8ad2018-08-23 11:25:43 -0700468 skylab_suites = lab_config.get_skylab_suite_list() if lab_config else []
Xixuan Wu83118dd2018-08-27 12:11:35 -0700469 logging.info('Skylab_boards: %r', skylab_boards)
470 logging.info('Skylab suites: %r', skylab_suites)
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700471 for (board, passed_model, build_type,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600472 milestone), manifest in build_dict.iteritems():
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700473 cros_build = str(build_lib.CrOSBuild(board, build_type, milestone,
474 manifest))
475 logging.info('Running %s on %s', self.name, cros_build)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700476 if self.exclude_boards and board in self.exclude_boards:
477 logging.debug('Board %s is in excluded board list: %s',
478 board, self.exclude_boards)
479 continue
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700480
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700481 if self.boards and board not in self.boards:
482 logging.debug('Board %s is not in supported board list: %s',
483 board, self.boards)
484 continue
485
486 # Check the fitness of the build's branch for task
487 branch_build_spec = _pick_branch(build_type, milestone)
488 if not self._fits_spec(branch_build_spec):
489 logging.debug("branch_build spec %s doesn't fit this task's "
490 "requirement: %s", branch_build_spec, self.branch_specs)
491 continue
492
493 firmware_rw_build = None
494 firmware_ro_build = None
495 if self.firmware_rw_build_spec or self.firmware_ro_build_spec:
496 firmware_rw_build = self._get_firmware_build(
497 self.firmware_rw_build_spec, board, lab_config, db_client)
498 firmware_ro_build = self._get_firmware_build(
499 self.firmware_ro_build_spec, board, lab_config, db_client)
500
501 if not firmware_ro_build and self.firmware_ro_build_spec:
502 logging.debug('No firmware ro build to run, skip running')
503 continue
504
505 if self.test_source == build_lib.BuildType.FIRMWARE_RW:
506 test_source_build = firmware_rw_build
507 else:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700508 # Default test source build to CrOS build if it's not specified.
509 # Past versions chose based on run_prod_code, but we no longer respect
510 # that option and scheduler settings should always set it to False.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700511 test_source_build = cros_build
512
C Shapiro7f24a002017-12-05 14:25:09 -0700513 models = models_by_board.get(board, [None])
Xixuan Wu83118dd2018-08-27 12:11:35 -0700514 is_skylab = (board in skylab_boards) and (self.suite in skylab_suites)
C Shapiro7f24a002017-12-05 14:25:09 -0700515
516 for model in models:
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700517 if ((passed_model is not None and model == passed_model) or
518 passed_model is None):
519 self._push_suite(
520 board=board,
521 model=model,
522 cros_build=cros_build,
523 firmware_rw_build=firmware_rw_build,
524 firmware_ro_build=firmware_ro_build,
525 test_source_build=test_source_build,
526 is_skylab=is_skylab)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700527
528 def _schedule_launch_control_builds(self, launch_control_builds):
529 """Schedule tasks with launch control builds.
530
531 Args:
532 launch_control_builds: the build dict for Android boards.
533 """
534 for board, launch_control_build in launch_control_builds.iteritems():
535 logging.debug('Running %s on %s', self.name, board)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700536 if self.exclude_boards and board in self.exclude_boards:
537 logging.debug('Board %s is in excluded board list: %s',
538 board, self.exclude_boards)
539 continue
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700540 if self.boards and board not in self.boards:
541 logging.debug('Board %s is not in supported board list: %s',
542 board, self.boards)
543 continue
544
545 for android_build in launch_control_build:
546 if not any([branch in android_build
547 for branch in self.launch_control_branches]):
548 logging.debug('Branch %s is not required to run for task '
549 '%s', android_build, self.name)
550 continue
551
552 self._push_suite(board=board,
553 test_source_build=android_build,
554 launch_control_build=android_build)
555
556
557def _pick_branch(build_type, milestone):
558 """Select branch based on build type.
559
560 If the build_type is a bare branch, return build_type as the build spec.
561 If the build_type is a normal CrOS branch, return milestone as the build
562 spec.
563
564 Args:
565 build_type: a string builder name, like 'release'.
566 milestone: a string milestone, like '55'.
567
568 Returns:
569 A string milestone if build_type represents CrOS build, otherwise
570 return build_type.
571 """
572 return build_type if build_type in build_lib.BARE_BRANCHES else milestone