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