1# Copyright 2016 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 5import logging 6 7from autotest_lib.client.common_lib import error 8from autotest_lib.client.common_lib import global_config 9from autotest_lib.server import afe_utils 10from autotest_lib.server import test 11from autotest_lib.server.hosts import adb_host 12 13 14_CONFIG = global_config.global_config 15# pylint: disable-msg=E1120 16_IMAGE_URL_PATTERN = _CONFIG.get_config_value( 17 'ANDROID', 'image_url_pattern', type=str) 18 19 20class provision_AndroidUpdate(test.test): 21 """A test that can provision a machine to the correct Android version.""" 22 version = 1 23 24 def initialize(self, host, value, force=False, is_test_na=False, 25 repair=False): 26 """Initialize. 27 28 @param host: The host object to update to |value|. 29 @param value: String of the image we want to install on the host. 30 @param force: not used by initialize. 31 @param is_test_na: boolean, if True, will simply skip the test 32 and emit TestNAError. The control file 33 determines whether the test should be skipped 34 and passes the decision via this argument. Note 35 we can't raise TestNAError in control file as it won't 36 be caught and handled properly. 37 @param repair: not used by initialize. 38 """ 39 if is_test_na: 40 raise error.TestNAError('Provisioning not applicable.') 41 # We check value in initialize so that it fails faster. 42 if not (value or repair): 43 raise error.TestFail('No build version specified.') 44 45 46 def run_once(self, host, value=None, force=False, repair=False): 47 """The method called by the control file to start the test. 48 49 @param host: The host object to update to |value|. 50 @param value: The host object to provision with a build corresponding 51 to |value|. 52 @param force: True iff we should re-provision the machine regardless of 53 the current image version. If False and the image 54 version matches our expected image version, no 55 provisioning will be done. 56 @param repair: If True, we are doing a repair provision, therefore the 57 build to provision is looked up from the AFE's 58 get_stable_version RPC. 59 60 """ 61 logging.debug('Start provisioning %s to %s', host, value) 62 63 if not value and not repair: 64 raise error.TestFail('No build provided and this is not a repair ' 65 ' job.') 66 67 # If the host is already on the correct build, we have nothing to do. 68 if not force and afe_utils.get_build(host) == value: 69 # We can't raise a TestNA, as would make sense, as that makes 70 # job.run_test return False as if the job failed. However, it'd 71 # still be nice to get this into the status.log, so we manually 72 # emit an INFO line instead. 73 self.job.record('INFO', None, None, 74 'Host already running %s' % value) 75 return 76 77 os_type = None 78 board = afe_utils.get_board(host) 79 if board: 80 logging.debug('Host %s is board type: %s', host, board) 81 if adb_host.OS_TYPE_BRILLO in board: 82 os_type = adb_host.OS_TYPE_BRILLO 83 else: 84 os_type = adb_host.OS_TYPE_ANDROID 85 86 if repair: 87 board=board.split('-')[-1] 88 value = afe_utils.get_stable_version(board=board, android=True) 89 if not value: 90 raise error.TestFail('No stable version assigned for board: ' 91 '%s' % board) 92 url, _ = host.stage_build_for_install(value, os_type=os_type) 93 94 logging.debug('Installing image from: %s', url) 95 try: 96 afe_utils.machine_install_and_update_labels( 97 host, build_url=url, os_type=os_type) 98 except error.InstallError as e: 99 logging.error(e) 100 raise error.TestFail(str(e)) 101 logging.debug('Finished provisioning %s to %s', host, value) 102