Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 1 | # Copyright (c) 2012 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 | __author__ = 'cmasone@chromium.org (Chris Masone)' |
| 6 | |
| 7 | import common |
Chris Masone | a8066a9 | 2012-05-01 16:52:31 -0700 | [diff] [blame] | 8 | import datetime |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 9 | import logging |
| 10 | import sys |
Chris Masone | f8b5306 | 2012-05-08 22:14:18 -0700 | [diff] [blame] | 11 | from autotest_lib.client.common_lib import error, global_config |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 12 | from autotest_lib.client.common_lib.cros import dev_server |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 13 | from autotest_lib.server.cros import control_file_getter, dynamic_suite |
| 14 | |
| 15 | |
Chris Masone | f8b5306 | 2012-05-08 22:14:18 -0700 | [diff] [blame] | 16 | # Relevant CrosDynamicSuiteExceptions are defined in client/common_lib/error.py. |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 17 | |
| 18 | |
| 19 | class ControlFileEmpty(Exception): |
| 20 | """Raised when the control file exists on the server, but can't be read.""" |
| 21 | pass |
| 22 | |
| 23 | |
| 24 | def _rpc_utils(): |
Chris Masone | b1451a0 | 2012-03-12 10:21:14 -0700 | [diff] [blame] | 25 | """Returns the rpc_utils module. MUST be mocked for unit tests. |
| 26 | |
| 27 | rpc_utils initializes django, which we can't do in unit tests. |
| 28 | This layer of indirection allows us to only load that module if we're |
| 29 | not running unit tests. |
| 30 | |
| 31 | @return: autotest_lib.frontend.afe.rpc_utils |
| 32 | """ |
| 33 | from autotest_lib.frontend.afe import rpc_utils |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 34 | return rpc_utils |
| 35 | |
| 36 | |
Chris Masone | 6257912 | 2012-03-08 15:18:43 -0800 | [diff] [blame] | 37 | def canonicalize_suite_name(suite_name): |
| 38 | return 'test_suites/control.%s' % suite_name |
| 39 | |
| 40 | |
Chris Masone | aa10f8e | 2012-05-15 13:34:21 -0700 | [diff] [blame^] | 41 | def formatted_now(): |
| 42 | return datetime.datetime.now().strftime(dynamic_suite.TIME_FMT) |
| 43 | |
| 44 | |
Chris Masone | 6257912 | 2012-03-08 15:18:43 -0800 | [diff] [blame] | 45 | def create_suite_job(suite_name, board, build, pool, check_hosts=True): |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 46 | """ |
| 47 | Create a job to run a test suite on the given device with the given image. |
| 48 | |
| 49 | When the timeout specified in the control file is reached, the |
| 50 | job is guaranteed to have completed and results will be available. |
| 51 | |
Scott Zawalski | 6565017 | 2012-02-16 11:48:26 -0500 | [diff] [blame] | 52 | @param suite_name: the test suite to run, e.g. 'bvt'. |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 53 | @param board: the kind of device to run the tests on. |
| 54 | @param build: unique name by which to refer to the image from now on. |
Scott Zawalski | 6565017 | 2012-02-16 11:48:26 -0500 | [diff] [blame] | 55 | @param pool: Specify the pool of machines to use for scheduling |
| 56 | purposes. |
Chris Masone | 6257912 | 2012-03-08 15:18:43 -0800 | [diff] [blame] | 57 | @param check_hosts: require appropriate live hosts to exist in the lab. |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 58 | |
Chris Masone | 6257912 | 2012-03-08 15:18:43 -0800 | [diff] [blame] | 59 | @raises ControlFileNotFound if a unique suite control file doesn't exist. |
| 60 | @raises NoControlFileList if we can't list the control files at all. |
| 61 | @raises StageBuildFailure if the dev server throws 500 while staging build. |
| 62 | @raises ControlFileEmpty if the control file exists on the server, but |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 63 | can't be read. |
| 64 | |
| 65 | @return: the job ID of the suite; -1 on error. |
| 66 | """ |
Scott Zawalski | 6565017 | 2012-02-16 11:48:26 -0500 | [diff] [blame] | 67 | # All suite names are assumed under test_suites/control.XX. |
Chris Masone | 6257912 | 2012-03-08 15:18:43 -0800 | [diff] [blame] | 68 | suite_name = canonicalize_suite_name(suite_name) |
Chris Masone | a8066a9 | 2012-05-01 16:52:31 -0700 | [diff] [blame] | 69 | |
| 70 | timings = {} |
Chris Sosa | 6b288c8 | 2012-03-29 15:31:06 -0700 | [diff] [blame] | 71 | # Ensure components of |build| necessary for installing images are staged |
| 72 | # on the dev server. However set synchronous to False to allow other |
| 73 | # components to be downloaded in the background. |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 74 | ds = dev_server.DevServer.create() |
Chris Masone | aa10f8e | 2012-05-15 13:34:21 -0700 | [diff] [blame^] | 75 | timings[dynamic_suite.DOWNLOAD_STARTED_TIME] = formatted_now() |
Chris Masone | f70650c | 2012-05-16 08:52:12 -0700 | [diff] [blame] | 76 | try: |
| 77 | ds.trigger_download(build, synchronous=False) |
| 78 | except dev_server.DevServerException as e: |
| 79 | raise error.StageBuildFailure(e) |
Chris Masone | aa10f8e | 2012-05-15 13:34:21 -0700 | [diff] [blame^] | 80 | timings[dynamic_suite.PAYLOAD_FINISHED_TIME] = formatted_now() |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 81 | |
| 82 | getter = control_file_getter.DevServerGetter.create(build, ds) |
| 83 | # Get the control file for the suite. |
| 84 | control_file_in = getter.get_control_file_contents_by_name(suite_name) |
| 85 | if not control_file_in: |
Chris Masone | f8b5306 | 2012-05-08 22:14:18 -0700 | [diff] [blame] | 86 | raise error.ControlFileEmpty( |
| 87 | "Fetching %s returned no data." % suite_name) |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 88 | |
| 89 | # prepend build and board to the control file |
Scott Zawalski | 6565017 | 2012-02-16 11:48:26 -0500 | [diff] [blame] | 90 | inject_dict = {'board': board, |
| 91 | 'build': build, |
Chris Masone | 6257912 | 2012-03-08 15:18:43 -0800 | [diff] [blame] | 92 | 'check_hosts': check_hosts, |
Scott Zawalski | 6565017 | 2012-02-16 11:48:26 -0500 | [diff] [blame] | 93 | 'pool': pool} |
| 94 | control_file = dynamic_suite.inject_vars(inject_dict, control_file_in) |
Chris Masone | 859fdec | 2012-01-30 08:38:09 -0800 | [diff] [blame] | 95 | |
| 96 | return _rpc_utils().create_job_common('%s-%s' % (build, suite_name), |
| 97 | priority='Medium', |
| 98 | control_type='Server', |
| 99 | control_file=control_file, |
Chris Masone | a8066a9 | 2012-05-01 16:52:31 -0700 | [diff] [blame] | 100 | hostless=True, |
| 101 | keyvals=timings) |