15ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi# Copyright 2016 The Chromium OS Authors. All rights reserved. 25ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi# Use of this source code is governed by a BSD-style license that can be 35ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi# found in the LICENSE file. 45ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 55ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basiimport logging 65ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 75ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basifrom autotest_lib.client.common_lib import error 85ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basifrom autotest_lib.client.common_lib import global_config 95ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basifrom autotest_lib.server import afe_utils 105ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basifrom autotest_lib.server import test 1181ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shifrom autotest_lib.server.hosts import testbed 125ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 135ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 145ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi_CONFIG = global_config.global_config 155ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi# pylint: disable-msg=E1120 165ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi_IMAGE_URL_PATTERN = _CONFIG.get_config_value( 175ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 'ANDROID', 'image_url_pattern', type=str) 185ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 195ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 205ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basiclass provision_AndroidUpdate(test.test): 215ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi """A test that can provision a machine to the correct Android version.""" 225ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi version = 1 235ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 24beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi def initialize(self, host, value, force=False, is_test_na=False, 25beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi repair=False): 265ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi """Initialize. 275ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 285ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param host: The host object to update to |value|. 295ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param value: String of the image we want to install on the host. 305ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param force: not used by initialize. 315ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param is_test_na: boolean, if True, will simply skip the test 325ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi and emit TestNAError. The control file 335ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi determines whether the test should be skipped 345ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi and passes the decision via this argument. Note 355ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi we can't raise TestNAError in control file as it won't 365ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi be caught and handled properly. 37beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi @param repair: not used by initialize. 385ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi """ 395ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi if is_test_na: 405ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi raise error.TestNAError('Provisioning not applicable.') 415ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi # We check value in initialize so that it fails faster. 42beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi if not (value or repair): 435ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi raise error.TestFail('No build version specified.') 445ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 455ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 46e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi def run_once(self, host, value=None, force=False, repair=False, board=None, 47e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi os=None): 485ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi """The method called by the control file to start the test. 495ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 505ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param host: The host object to update to |value|. 515ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param value: The host object to provision with a build corresponding 525ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi to |value|. 535ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi @param force: True iff we should re-provision the machine regardless of 545ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi the current image version. If False and the image 555ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi version matches our expected image version, no 565ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi provisioning will be done. 57beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi @param repair: If True, we are doing a repair provision, therefore the 58beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi build to provision is looked up from the AFE's 59beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi get_stable_version RPC. 60e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi @param board: Board name of the device. For host created in testbed, 61e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi it does not have host labels and attributes. Therefore, 62e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi the board name needs to be passed in from the testbed 63e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi repair call. 64e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi @param os: OS of the device. For host created in testbed, it does not 65e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi have host labels and attributes. Therefore, the OS needs to 66e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi be passed in from the testbed repair call. 675ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 685ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi """ 695ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi logging.debug('Start provisioning %s to %s', host, value) 705ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 71beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi if not value and not repair: 72beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi raise error.TestFail('No build provided and this is not a repair ' 73beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi ' job.') 74beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi 753d470dd3952967294b76d55808b9a0514a54bfe8Prathmesh Prabhu info = host.host_info_store.get() 765ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi # If the host is already on the correct build, we have nothing to do. 773d470dd3952967294b76d55808b9a0514a54bfe8Prathmesh Prabhu if not force and info.build == value: 785ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi # We can't raise a TestNA, as would make sense, as that makes 795ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi # job.run_test return False as if the job failed. However, it'd 805ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi # still be nice to get this into the status.log, so we manually 815ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi # emit an INFO line instead. 825ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi self.job.record('INFO', None, None, 835ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 'Host already running %s' % value) 845ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi return 855ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 86e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi board = board or info.board 87e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi os = os or info.os 88e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi logging.debug('Host %s is board type: %s, OS type: %s', host, board, os) 89beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi if repair: 90212880e75defac5ecbdb6dc078f0ddbba671f3a3Kevin Cheng # TODO(kevcheng): remove the board.split() line when all android 91212880e75defac5ecbdb6dc078f0ddbba671f3a3Kevin Cheng # devices have their board label updated to have no android in 92212880e75defac5ecbdb6dc078f0ddbba671f3a3Kevin Cheng # there. 93e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi board = board.split('-')[-1] 94260cbd038544b9a183206d9f4c59db74808ad543Richard Barnette value = afe_utils.get_stable_android_version(board) 95beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi if not value: 96beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi raise error.TestFail('No stable version assigned for board: ' 97beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi '%s' % board) 98e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi logging.debug('Stable version found for board %s: %s', board, value) 995ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi 10081ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shi if not isinstance(host, testbed.TestBed): 101e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi url, _ = host.stage_build_for_install(value, os_type=os) 10281ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shi logging.debug('Installing image from: %s', url) 103e104c89bdf8a10c0281909e01e5d87a97e89ac21Dan Shi args = {'build_url': url, 'os_type': os} 10481ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shi else: 10581ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shi logging.debug('Installing image: %s', value) 10681ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shi args = {'image': value} 1075ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi try: 108beb2bb20028027fa31c2790e54619c82f4d51422Simran Basi afe_utils.machine_install_and_update_labels( 10981ddc4246d344deff31ea5c4d8cd0f5ba35dea26Dan Shi host, **args) 1105ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi except error.InstallError as e: 1115ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi logging.error(e) 1125ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi raise error.TestFail(str(e)) 1135ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi logging.debug('Finished provisioning %s to %s', host, value) 114