blob: 16a1136afe39cd1859f4337c9c282558c3dc534f [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
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.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070068 priority, the string name of a priority from constants.Priorities.
69 timeout, the max lifetime of the suite in hours.
70 cros_build_spec, spec used to determine the ChromeOS build to test
71 with a firmware build, e.g., tot, R41 etc.
72 firmware_rw_build_spec, spec used to determine the firmware RW build
73 test with a ChromeOS build.
74 firmware_ro_build_spec, spec used to determine the firmware RO build
75 test with a ChromeOS build.
76 test_source, the source of test code when firmware will be updated in
77 the test. The value can be 'firmware_rw', 'firmware_ro' or 'cros'.
78 job_retry, set to True to enable job-level retry. Default is False.
Xixuan Wu80531932017-10-12 17:26:51 -070079 no_delay, set to True to raise the priority of this task in task.
80 force, set to True to schedule this suite no matter whether there's
81 duplicate jobs before.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070082 queue, so the suite jobs can start running tests with no waiting.
83 hour, an integer specifying the hour that a nightly run should be
84 triggered, default is set to 21.
85 day, an integer specifying the day of a week that a weekly run should
86 be triggered, default is set to 5 (Saturday).
87 os_type, type of OS, e.g., cros, brillo, android. Default is cros.
88 The argument is required for android/brillo builds.
89 launch_control_branches, comma separated string of launch control
90 branches. The argument is required and only applicable for
91 android/brillo builds.
92 launch_control_targets, comma separated string of build targets for
93 launch control builds. The argument is required and only
94 applicable for android/brillo builds.
95 testbed_dut_count, number of duts to test when using a testbed.
Xixuan Wu83118dd2018-08-27 12:11:35 -070096 board_family_config: A board family dictionary mapping board_family name
97 to its corresponding boards.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -070098 tot: The tot manager for checking ToT. If it's None, a new tot_manager
99 instance will be initialized.
100 """
Xixuan Wu5451a662017-10-17 10:57:40 -0700101 # Indicate whether there're suites get pushed into taskqueue for this task.
102 self.is_pushed = False
103
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700104 self.name = task_info.name
105 self.suite = task_info.suite
106 self.branch_specs = task_info.branch_specs
107 self.pool = task_info.pool
108 self.num = task_info.num
109 self.priority = task_info.priority
110 self.timeout = task_info.timeout
111 self.cros_build_spec = task_info.cros_build_spec
112 self.firmware_rw_build_spec = task_info.firmware_rw_build_spec
113 self.firmware_ro_build_spec = task_info.firmware_ro_build_spec
114 self.test_source = task_info.test_source
115 self.job_retry = task_info.job_retry
116 self.no_delay = task_info.no_delay
Xixuan Wu80531932017-10-12 17:26:51 -0700117 self.force = task_info.force
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700118 self.os_type = task_info.os_type
119 self.testbed_dut_count = task_info.testbed_dut_count
Xixuan Wu008ee832017-10-12 16:59:34 -0700120 self.hour = task_info.hour
121 self.day = task_info.day
Craig Bergstrom58263d32018-04-26 14:11:35 -0600122 self.only_hwtest_sanity_required = task_info.only_hwtest_sanity_required
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700123
124 if task_info.lc_branches:
125 self.launch_control_branches = [
126 t.strip() for t in task_info.lc_branches.split(',')]
127 else:
128 self.launch_control_branches = []
129
130 if task_info.lc_targets:
131 self.launch_control_targets = [
132 t.strip() for t in task_info.lc_targets.split(',')]
133 else:
134 self.launch_control_targets = []
135
136 if task_info.boards:
137 self.boards = [t.strip() for t in task_info.boards.split(',')]
138 else:
139 self.boards = []
140
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700141 if task_info.exclude_boards:
142 self.exclude_boards = [
143 t.strip() for t in task_info.exclude_boards.split(',')]
144 else:
145 self.exclude_boards = []
146
Xixuan Wu89897182019-01-03 15:28:01 -0800147 if task_info.models:
148 self.models = [t.strip() for t in task_info.models.split(',')]
149 else:
150 self.models = []
151
152 if task_info.exclude_models:
153 self.exclude_models = [
154 t.strip() for t in task_info.exclude_models.split(',')]
155 else:
156 self.exclude_models = []
157
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700158 if task_info.board_families:
159 # Finetune the allowed boards list with board_families & boards.
160 families = [family.strip()
161 for family in task_info.board_families.split(',')]
162 for family in families:
163 self.boards += board_family_config.get(family, [])
Xixuan Wu89897182019-01-03 15:28:01 -0800164
Po-Hsien Wangdd833072018-08-16 18:09:20 -0700165 if task_info.exclude_board_families:
166 # Finetune the disallowed boards list with exclude_board_families
167 # & exclude_boards.
168 families = [family.strip()
169 for family in task_info.exclude_board_families.split(',')]
170 for family in families:
171 self.exclude_boards += board_family_config.get(family, [])
172
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700173 if tot is None:
174 self.tot_manager = tot_manager.TotMilestoneManager()
175 else:
176 self.tot_manager = tot
177
178 self._set_spec_compare_info()
179
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700180 def schedule(self, launch_control_builds, cros_builds_tuple, configs,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700181 db_client):
182 """Schedule the task by its settings.
183
184 Args:
185 launch_control_builds: the build dict for Android boards, see
186 return value of |get_launch_control_builds|.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600187 cros_builds_tuple: the two-tuple of build dicts for ChromeOS boards,
188 see return value of |get_cros_builds|.
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700189 configs: a config_reader.Configs object.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700190 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
191
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 Wuf4a4c882019-03-15 14:48:26 -0700212 self._schedule_cros_builds(builds_dict, configs, db_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
289 def _get_latest_firmware_build_from_db(self, spec, board, db_client):
290 """Get the latest firmware build from CIDB database.
291
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.
296 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
297
298 Returns:
299 the latest firmware build.
300
301 Raises:
302 MySQLdb.OperationalError: if connection operations are not valid.
303 """
304 build_type = 'release' if spec == 'cros' else spec
305 # TODO(xixuan): not all firmware are saved in cidb.
306 build = db_client.get_latest_passed_builds('%s-%s' % (board, build_type))
307
308 if build is None:
309 return None
310 else:
311 latest_build = str(build_lib.CrOSBuild(
312 board, build_type, build.milestone, build.platform))
313 logging.debug('latest firmware build for %s-%s: %s', board,
314 build_type, latest_build)
315 return latest_build
316
317 def _get_latest_firmware_build_from_lab_config(self, spec, board,
318 lab_config):
319 """Get latest firmware from lab config file.
320
321 Args:
322 spec: a string build spec for RO or RW firmware, eg. firmware,
323 cros. For RO firmware, the value can also be released_ro_X.
324 board: a string board against which this task will run suite job.
325 lab_config: a config.LabConfig object, to read lab config file.
326
327 Returns:
328 A string latest firmware build.
329
330 Raises:
331 ValueError: if no firmware build list is found in lab config file.
332 """
333 index = int(spec[len(_RELEASE_RO_FIRMWARE_SPEC):])
334 released_ro_builds = lab_config.get_firmware_ro_build_list(
335 'RELEASED_RO_BUILDS_%s' % board).split(',')
336 if len(released_ro_builds) < index:
337 raise ValueError('No %dth ro_builds in the lab_config firmware '
338 'list %r' % (index, released_ro_builds))
339
340 logging.debug('Get ro_build: %s', released_ro_builds[index - 1])
341 return released_ro_builds[index - 1]
342
343 def _get_firmware_build(self, spec, board, lab_config, db_client):
344 """Get the firmware build name to test with ChromeOS build.
345
346 Args:
347 spec: a string build spec for RO or RW firmware, eg. firmware,
348 cros. For RO firmware, the value can also be released_ro_X.
349 board: a string board against which this task will run suite job.
350 lab_config: a config.LabConfig object, to read lab config file.
351 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
352
353 Returns:
354 A string firmware build name.
355
356 Raises:
357 ValueError: if failing to get firmware from lab config file;
358 MySQLdb.OperationalError: if DB connection is not available.
359 """
360 if not spec or spec == 'stable':
361 # TODO(crbug.com/577316): Query stable RO firmware.
362 logging.debug('%s RO firmware build is not supported.', spec)
363 return None
364
365 try:
366 if spec.startswith(_RELEASE_RO_FIRMWARE_SPEC):
367 # For RO firmware whose value is released_ro_X, where X is the index of
368 # the list defined in lab config file:
369 # CROS/RELEASED_RO_BUILDS_[board].
370 # For example, for spec 'released_ro_2', and lab config file
371 # CROS/RELEASED_RO_BUILDS_veyron_jerry: build1,build2,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600372 # return firmware RO build should be 'build2'.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700373 return self._get_latest_firmware_build_from_lab_config(
374 spec, board, lab_config)
375 else:
376 return self._get_latest_firmware_build_from_db(spec, board, db_client)
377 except ValueError as e:
378 logging.warning('Failed to get firmware from lab config file'
379 'for spec %s, board %s: %s', spec, board, str(e))
380 return None
381 except MySQLdb.OperationalError as e:
382 logging.warning('Failed to get firmware from cidb for spec %s, '
383 'board %s: %s', spec, board, str(e))
384 return None
385
C Shapiro7f24a002017-12-05 14:25:09 -0700386 def _push_suite(
387 self,
388 board=None,
389 model=None,
390 cros_build=None,
391 firmware_rw_build=None,
392 firmware_ro_build=None,
393 test_source_build=None,
394 launch_control_build=None,
Xixuan Wubb74a372018-08-21 17:37:08 -0700395 run_prod_code=False,
396 is_skylab=False):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700397 """Schedule suite job for the task by pushing suites to SuiteQueue.
398
399 Args:
400 board: the board against which this suite job run.
C Shapiro7f24a002017-12-05 14:25:09 -0700401 model: the model name for unibuild.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700402 cros_build: the CrOS build of this suite job.
403 firmware_rw_build: Firmware RW build to run this suite job with.
404 firmware_ro_build: Firmware RO build to run this suite job with.
405 test_source_build: Test source build, used for server-side
406 packaging of this suite job.
407 launch_control_build: the launch control build of this suite job.
408 run_prod_code: If True, the suite will run the test code that lives
409 in prod aka the test code currently on the lab servers. If
410 False, the control files and test code for this suite run will
411 be retrieved from the build artifacts. Default is False.
Xixuan Wubb74a372018-08-21 17:37:08 -0700412 is_skylab: If True, schedule this suite to skylab, otherwise schedule
413 it to AFE. Default is False.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700414 """
415 android_build = None
416 testbed_build = None
417
418 if self.testbed_dut_count:
419 launch_control_build = '%s#%d' % (launch_control_build,
420 self.testbed_dut_count)
421 test_source_build = launch_control_build
422 board = '%s-%d' % (board, self.testbed_dut_count)
423
424 if launch_control_build:
425 if not self.testbed_dut_count:
426 android_build = launch_control_build
427 else:
428 testbed_build = launch_control_build
429
430 suite_job_parameters = {
431 'suite': self.suite,
432 'board': board,
C Shapiro7f24a002017-12-05 14:25:09 -0700433 'model': model,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700434 build_lib.BuildVersionKey.CROS_VERSION: cros_build,
435 build_lib.BuildVersionKey.FW_RW_VERSION: firmware_rw_build,
436 build_lib.BuildVersionKey.FW_RO_VERSION: firmware_ro_build,
437 build_lib.BuildVersionKey.ANDROID_BUILD_VERSION: android_build,
438 build_lib.BuildVersionKey.TESTBED_BUILD_VERSION: testbed_build,
439 'num': self.num,
440 'pool': self.pool,
441 'priority': self.priority,
442 'timeout': self.timeout,
443 'timeout_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
444 'max_runtime_mins': _JOB_MAX_RUNTIME_MINS_DEFAULT,
Xixuan Wu2ba72652017-09-15 15:49:42 -0700445 'no_wait_for_results': not self.job_retry,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700446 'test_source_build': test_source_build,
447 'job_retry': self.job_retry,
448 'no_delay': self.no_delay,
Xixuan Wu80531932017-10-12 17:26:51 -0700449 'force': self.force,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700450 'run_prod_code': run_prod_code,
Xixuan Wubb74a372018-08-21 17:37:08 -0700451 'is_skylab': is_skylab,
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700452 }
453
454 task_executor.push(task_executor.SUITES_QUEUE, **suite_job_parameters)
455 logging.info('Pushing task %r into taskqueue', suite_job_parameters)
Xixuan Wu5451a662017-10-17 10:57:40 -0700456 self.is_pushed = True
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700457
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700458 def _schedule_cros_builds(self, build_dict, configs, db_client):
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700459 """Schedule tasks with branch builds.
460
461 Args:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600462 build_dict: the build dict for ChromeOS boards, see return
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700463 value of |build_lib.get_cros_builds_since_date_from_db|.
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700464 configs: A config_reader.Configs object.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700465 db_client: a cloud_sql_client.CIDBClient object to connect to cidb.
466 """
Xixuan Wuf4a4c882019-03-15 14:48:26 -0700467 lab_config = configs.lab_config
C Shapiro7f24a002017-12-05 14:25:09 -0700468 models_by_board = lab_config.get_cros_model_map() if lab_config else {}
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700469 for (board, passed_model, build_type,
Craig Bergstrom58263d32018-04-26 14:11:35 -0600470 milestone), manifest in build_dict.iteritems():
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700471 cros_build = str(build_lib.CrOSBuild(board, build_type, milestone,
472 manifest))
473 logging.info('Running %s on %s', self.name, cros_build)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700474 if self.exclude_boards and board in self.exclude_boards:
475 logging.debug('Board %s is in excluded board list: %s',
476 board, self.exclude_boards)
477 continue
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700478
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700479 if self.boards and board not in self.boards:
480 logging.debug('Board %s is not in supported board list: %s',
481 board, self.boards)
482 continue
483
484 # Check the fitness of the build's branch for task
485 branch_build_spec = _pick_branch(build_type, milestone)
486 if not self._fits_spec(branch_build_spec):
487 logging.debug("branch_build spec %s doesn't fit this task's "
488 "requirement: %s", branch_build_spec, self.branch_specs)
489 continue
490
491 firmware_rw_build = None
492 firmware_ro_build = None
493 if self.firmware_rw_build_spec or self.firmware_ro_build_spec:
494 firmware_rw_build = self._get_firmware_build(
495 self.firmware_rw_build_spec, board, lab_config, db_client)
496 firmware_ro_build = self._get_firmware_build(
497 self.firmware_ro_build_spec, board, lab_config, db_client)
498
499 if not firmware_ro_build and self.firmware_ro_build_spec:
500 logging.debug('No firmware ro build to run, skip running')
501 continue
502
503 if self.test_source == build_lib.BuildType.FIRMWARE_RW:
504 test_source_build = firmware_rw_build
505 else:
Jacob Kopczynski79d00102018-07-13 15:37:03 -0700506 # Default test source build to CrOS build if it's not specified.
507 # Past versions chose based on run_prod_code, but we no longer respect
508 # that option and scheduler settings should always set it to False.
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700509 test_source_build = cros_build
510
Xixuan Wu1f0be4c2019-03-18 16:53:23 -0700511 is_skylab = skylab.should_run_in_skylab(configs.migration_config,
512 board,
Xixuan Wued878ea2019-03-18 15:32:16 -0700513 passed_model,
Xixuan Wu1e42c752019-03-21 13:41:49 -0700514 self.suite,
515 self.pool)
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000516 models = models_by_board.get(board, [None])
C Shapiro7f24a002017-12-05 14:25:09 -0700517
Harpreet Grewalbbbb7de2019-02-05 19:35:03 +0000518 for model in models:
519 if ((passed_model is not None and model == passed_model) or
520 passed_model is None):
521 self._push_suite(
522 board=board,
523 model=model,
524 cros_build=cros_build,
525 firmware_rw_build=firmware_rw_build,
526 firmware_ro_build=firmware_ro_build,
527 test_source_build=test_source_build,
528 is_skylab=is_skylab)
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700529
530 def _schedule_launch_control_builds(self, launch_control_builds):
531 """Schedule tasks with launch control builds.
532
533 Args:
534 launch_control_builds: the build dict for Android boards.
535 """
536 for board, launch_control_build in launch_control_builds.iteritems():
537 logging.debug('Running %s on %s', self.name, board)
Po-Hsien Wang6d589732018-05-15 17:19:34 -0700538 if self.exclude_boards and board in self.exclude_boards:
539 logging.debug('Board %s is in excluded board list: %s',
540 board, self.exclude_boards)
541 continue
Xixuan Wu0c76d5b2017-08-30 16:40:17 -0700542 if self.boards and board not in self.boards:
543 logging.debug('Board %s is not in supported board list: %s',
544 board, self.boards)
545 continue
546
547 for android_build in launch_control_build:
548 if not any([branch in android_build
549 for branch in self.launch_control_branches]):
550 logging.debug('Branch %s is not required to run for task '
551 '%s', android_build, self.name)
552 continue
553
554 self._push_suite(board=board,
555 test_source_build=android_build,
556 launch_control_build=android_build)
557
558
559def _pick_branch(build_type, milestone):
560 """Select branch based on build type.
561
562 If the build_type is a bare branch, return build_type as the build spec.
563 If the build_type is a normal CrOS branch, return milestone as the build
564 spec.
565
566 Args:
567 build_type: a string builder name, like 'release'.
568 milestone: a string milestone, like '55'.
569
570 Returns:
571 A string milestone if build_type represents CrOS build, otherwise
572 return build_type.
573 """
574 return build_type if build_type in build_lib.BARE_BRANCHES else milestone