Home | History | Annotate | Download | only in autoupdate_ForcedOOBEUpdate
      1 # 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 import logging
      6 import random
      7 import time
      8 
      9 from autotest_lib.client.common_lib import error
     10 from autotest_lib.client.common_lib.cros import tpm_utils
     11 from autotest_lib.server.cros.update_engine import update_engine_test
     12 
     13 class autoupdate_ForcedOOBEUpdate(update_engine_test.UpdateEngineTest):
     14     """Runs a forced autoupdate during OOBE."""
     15     version = 1
     16 
     17 
     18     def cleanup(self):
     19         self._host.run('rm %s' % self._CUSTOM_LSB_RELEASE, ignore_status=True)
     20 
     21         # Get the last two update_engine logs: before and after reboot.
     22         self._save_extra_update_engine_logs()
     23         self._change_cellular_setting_in_update_engine(False)
     24 
     25         # Cancel any update still in progress.
     26         if not self._is_update_engine_idle():
     27             logging.debug('Canceling the in-progress update.')
     28             self._host.run('restart update-engine')
     29         super(autoupdate_ForcedOOBEUpdate, self).cleanup()
     30 
     31 
     32     def _wait_for_oobe_update_to_complete(self):
     33         """Wait for the update that started to complete.
     34 
     35         Repeated check status of update. It should move from DOWNLOADING to
     36         FINALIZING to COMPLETE (then reboot) to IDLE.
     37         """
     38         # 20 minute timeout.
     39         timeout_minutes = 20
     40         timeout = time.time() + 60 * timeout_minutes
     41         while True:
     42             status = self._get_update_engine_status(timeout=10)
     43 
     44             # During reboot, status will be None
     45             if status is not None:
     46                 if self._UPDATE_STATUS_IDLE == status[self._CURRENT_OP]:
     47                     break
     48             time.sleep(1)
     49             if time.time() > timeout:
     50                 raise error.TestFail('OOBE update did not finish in %d '
     51                                      'minutes.' % timeout_minutes)
     52 
     53 
     54     def run_once(self, full_payload=True, cellular=False,
     55                  interrupt=False, max_updates=1, job_repo_url=None):
     56         """
     57         Runs a forced autoupdate during ChromeOS OOBE.
     58 
     59         @param full_payload: True for a full payload. False for delta.
     60         @param cellular: True to do the update over a cellualar connection.
     61                          Requires that the DUT have a sim card slot.
     62         @param interrupt: True to interrupt the update in the middle.
     63         @param max_updates: Used to tell the test how many times it is
     64                             expected to ping its omaha server.
     65         @param job_repo_url: Used for debugging locally. This is used to figure
     66                              out the current build and the devserver to use.
     67                              The test will read this from a host argument
     68                              when run in the lab.
     69 
     70         """
     71         tpm_utils.ClearTPMOwnerRequest(self._host)
     72 
     73         # veyron_rialto is a medical device with a different OOBE that auto
     74         # completes so this test is not valid on that device.
     75         if 'veyron_rialto' in self._host.get_board():
     76             raise error.TestNAError('Rialto has a custom OOBE. Skipping test.')
     77 
     78         update_url = self.get_update_url_for_test(job_repo_url,
     79                                                   full_payload=full_payload,
     80                                                   critical_update=True,
     81                                                   public=cellular,
     82                                                   max_updates=max_updates)
     83         before = self._get_chromeos_version()
     84         payload_info = None
     85         if cellular:
     86             self._change_cellular_setting_in_update_engine(True)
     87             # Get the payload's information (size, SHA256 etc) since we will be
     88             # setting up our own omaha instance on the DUT. We pass this to
     89             # the client test.
     90             payload = self._get_payload_url(full_payload=full_payload)
     91             staged_url = self._stage_payload_by_uri(payload)
     92             payload_info = self._get_staged_file_info(staged_url)
     93 
     94         # Call client test to start the forced OOBE update.
     95         self._run_client_test_and_check_result('autoupdate_StartOOBEUpdate',
     96                                                image_url=update_url,
     97                                                cellular=cellular,
     98                                                payload_info=payload_info,
     99                                                full_payload=full_payload)
    100 
    101 
    102         if interrupt:
    103             # Choose a random downloaded progress to interrupt the update.
    104             progress = random.uniform(0.1, 0.8)
    105             logging.debug('Progress when we will interrupt: %f', progress)
    106             self._wait_for_progress(progress)
    107             logging.info('We will start interrupting the update.')
    108 
    109             # Reboot the DUT during the update.
    110             self._take_screenshot('before_reboot.png')
    111             completed = self._get_update_progress()
    112             self._host.reboot()
    113             # Screenshot to check that if OOBE was not skipped by interruption.
    114             self._take_screenshot('after_reboot.png')
    115             if self._is_update_finished_downloading():
    116                 raise error.TestError('Reboot interrupt: Update finished '
    117                                       'downloading before any more '
    118                                       'interruptions. Started interrupting '
    119                                       'at: %f' % progress)
    120             if self._is_update_engine_idle():
    121                 raise error.TestFail('The update was IDLE after reboot.')
    122 
    123             # Disconnect / Reconnect network.
    124             completed = self._get_update_progress()
    125             self._disconnect_then_reconnect_network(update_url)
    126             self._take_screenshot('after_network.png')
    127             if self._is_update_finished_downloading():
    128                 raise error.TestError('Network interrupt: Update finished '
    129                                       'downloading before any more '
    130                                       'interruptions. Started interrupting '
    131                                       'at: %f' % progress)
    132             if not self._update_continued_where_it_left_off(completed):
    133                 raise error.TestFail('The update did not continue where it '
    134                                      'left off before disconnecting network.')
    135 
    136             # Suspend / Resume.
    137             completed = self._get_update_progress()
    138             self._suspend_then_resume()
    139             self._take_screenshot('after_suspend.png')
    140             if self._is_update_finished_downloading():
    141                 raise error.TestError('Suspend interrupt: Update finished '
    142                                       'downloading before any more '
    143                                       'interruptions. Started interrupting '
    144                                       'at: %f' % progress)
    145             if not self._update_continued_where_it_left_off(completed):
    146                 raise error.TestFail('The update did not continue where it '
    147                                      'left off after suspend/resume.')
    148 
    149         self._wait_for_oobe_update_to_complete()
    150 
    151         if cellular:
    152             # We didn't have a devserver so we cannot check the hostlog to
    153             # ensure the update completed successfully. Instead we can check
    154             # that the second-to-last update engine log has the successful
    155             # update message. Second to last because its the one before OOBE
    156             # rebooted.
    157             before_reboot_file = self._get_second_last_update_engine_log()
    158             self._check_for_cellular_entries_in_update_log(before_reboot_file)
    159             success = 'Update successfully applied, waiting to reboot.'
    160             self._check_update_engine_log_for_entry(success,
    161                                                     raise_error=True,
    162                                                     update_engine_log=
    163                                                     before_reboot_file)
    164             return
    165 
    166         # Verify that the update completed successfully by checking hostlog.
    167         rootfs_hostlog, reboot_hostlog = self._create_hostlog_files()
    168         self.verify_update_events(self._CUSTOM_LSB_VERSION, rootfs_hostlog)
    169         self.verify_update_events(self._CUSTOM_LSB_VERSION, reboot_hostlog,
    170                                   self._CUSTOM_LSB_VERSION)
    171 
    172         after = self._get_chromeos_version()
    173         logging.info('Successfully force updated from %s to %s.', before, after)
    174