David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 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. |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 4 | |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 5 | import logging |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 6 | import random |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 7 | import time |
| 8 | |
David Haddock | 463faf4 | 2018-01-23 14:21:11 -0800 | [diff] [blame] | 9 | from autotest_lib.client.common_lib import error |
David Haddock | 3a8f572 | 2018-04-13 16:24:16 -0700 | [diff] [blame] | 10 | from autotest_lib.client.common_lib.cros import tpm_utils |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 11 | from autotest_lib.server.cros.update_engine import update_engine_test |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 12 | from chromite.lib import retry_util |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 13 | |
| 14 | class autoupdate_ForcedOOBEUpdate(update_engine_test.UpdateEngineTest): |
| 15 | """Runs a forced autoupdate during OOBE.""" |
| 16 | version = 1 |
| 17 | |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 18 | |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 19 | def cleanup(self): |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 20 | self._host.run('rm %s' % self._CUSTOM_LSB_RELEASE, ignore_status=True) |
| 21 | |
| 22 | # Get the last two update_engine logs: before and after reboot. |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 23 | files = self._host.run('ls -t -1 %s' % |
| 24 | self._UPDATE_ENGINE_LOG_DIR).stdout.splitlines() |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 25 | for i in range(2): |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 26 | self._host.get_file('%s%s' % (self._UPDATE_ENGINE_LOG_DIR, |
| 27 | files[i]), self.resultsdir) |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 28 | cmd = 'update_engine_client --update_over_cellular=no' |
| 29 | retry_util.RetryException(error.AutoservRunError, 2, self._host.run, |
| 30 | cmd) |
David Haddock | 50dbfee | 2018-01-12 12:43:12 -0800 | [diff] [blame] | 31 | super(autoupdate_ForcedOOBEUpdate, self).cleanup() |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 32 | |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 33 | |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 34 | def _wait_for_oobe_update_to_complete(self): |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 35 | """Wait for the update that started to complete. |
| 36 | |
| 37 | Repeated check status of update. It should move from DOWNLOADING to |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 38 | FINALIZING to COMPLETE (then reboot) to IDLE. |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 39 | """ |
| 40 | while True: |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 41 | status = self._get_update_engine_status() |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 42 | |
| 43 | # During reboot, status will be None |
| 44 | if status is not None: |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 45 | if self._UPDATE_STATUS_IDLE == status[self._CURRENT_OP]: |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 46 | break |
| 47 | time.sleep(1) |
| 48 | |
| 49 | |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 50 | def run_once(self, host, full_payload=True, cellular=False, |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 51 | interrupt=False, max_updates=1, job_repo_url=None): |
| 52 | """ |
| 53 | Runs a forced autoupdate during ChromeOS OOBE. |
| 54 | |
| 55 | @param host: The DUT that we are running on. |
| 56 | @param full_payload: True for a full payload. False for delta. |
| 57 | @param cellular: True to do the update over a cellualar connection. |
| 58 | Requires that the DUT have a sim card slot. |
| 59 | @param interrupt: True to interrupt the update in the middle. |
| 60 | @param max_updates: Used to tell the test how many times it is |
| 61 | expected to ping its omaha server. |
| 62 | @param job_repo_url: Used for debugging locally. This is used to figure |
| 63 | out the current build and the devserver to use. |
| 64 | The test will read this from a host argument |
| 65 | when run in the lab. |
| 66 | |
| 67 | """ |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 68 | self._host = host |
David Haddock | 3a8f572 | 2018-04-13 16:24:16 -0700 | [diff] [blame] | 69 | tpm_utils.ClearTPMOwnerRequest(self._host) |
David Haddock | 463faf4 | 2018-01-23 14:21:11 -0800 | [diff] [blame] | 70 | |
| 71 | # veyron_rialto is a medical device with a different OOBE that auto |
| 72 | # completes so this test is not valid on that device. |
| 73 | if 'veyron_rialto' in self._host.get_board(): |
| 74 | raise error.TestNAError('Rialto has a custom OOBE. Skipping test.') |
| 75 | |
David Haddock | 50dbfee | 2018-01-12 12:43:12 -0800 | [diff] [blame] | 76 | update_url = self.get_update_url_for_test(job_repo_url, |
David Haddock | 463faf4 | 2018-01-23 14:21:11 -0800 | [diff] [blame] | 77 | full_payload=full_payload, |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 78 | critical_update=True, |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 79 | public=cellular, |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 80 | max_updates=max_updates) |
David Haddock | 50dbfee | 2018-01-12 12:43:12 -0800 | [diff] [blame] | 81 | logging.info('Update url: %s', update_url) |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 82 | before = self._get_chromeos_version() |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 83 | payload_info = None |
| 84 | if cellular: |
| 85 | cmd = 'update_engine_client --update_over_cellular=yes' |
| 86 | retry_util.RetryException(error.AutoservRunError, 2, self._host.run, |
| 87 | cmd) |
| 88 | # Get the payload's information (size, SHA256 etc) since we will be |
| 89 | # setting up our own omaha instance on the DUT. We pass this to |
| 90 | # the client test. |
| 91 | payload = self._get_payload_url(full_payload=full_payload) |
| 92 | staged_url = self._stage_payload_by_uri(payload) |
| 93 | payload_info = self._get_staged_file_info(staged_url) |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 94 | |
| 95 | # Call client test to start the forced OOBE update. |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 96 | self._run_client_test_and_check_result('autoupdate_StartOOBEUpdate', |
| 97 | image_url=update_url, |
| 98 | public=cellular, |
| 99 | payload_info=payload_info, |
| 100 | full_payload=full_payload) |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 101 | |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 102 | |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 103 | if interrupt: |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 104 | # Choose a random downloaded progress to interrupt the update. |
| 105 | progress = random.uniform(0.1, 0.8) |
| 106 | logging.debug('Progress when we will interrupt: %f', progress) |
| 107 | self._wait_for_progress(progress) |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 108 | logging.info('We will start interrupting the update.') |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 109 | completed = self._get_update_progress() |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 110 | |
| 111 | # Reboot the DUT during the update. |
| 112 | self._host.reboot() |
| 113 | if not self._update_continued_where_it_left_off(completed): |
| 114 | raise error.TestFail('The update did not continue where it ' |
| 115 | 'left off before rebooting.') |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 116 | completed = self._get_update_progress() |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 117 | |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 118 | self._disconnect_then_reconnect_network(update_url) |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 119 | if not self._update_continued_where_it_left_off(completed): |
| 120 | raise error.TestFail('The update did not continue where it ' |
| 121 | 'left off before disconnecting network.') |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 122 | completed = self._get_update_progress() |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 123 | |
| 124 | # Suspend / Resume |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 125 | self._suspend_then_resume() |
David Haddock | 0bad4a3 | 2018-02-02 13:05:26 -0800 | [diff] [blame] | 126 | if not self._update_continued_where_it_left_off(completed): |
| 127 | raise error.TestFail('The update did not continue where it ' |
| 128 | 'left off after suspend/resume.') |
| 129 | |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 130 | self._wait_for_oobe_update_to_complete() |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 131 | |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 132 | if cellular: |
| 133 | # We didn't have a devserver so we cannot check the hostlog to |
| 134 | # ensure the update completed successfully. Instead we can check |
| 135 | # that the second-to-last update engine log has the successful |
| 136 | # update message. Second to last because its the one before OOBE |
| 137 | # rebooted. |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 138 | update_engine_files_cmd = 'ls -t -1 %s' % \ |
| 139 | self._UPDATE_ENGINE_LOG_DIR |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 140 | files = self._host.run(update_engine_files_cmd).stdout.splitlines() |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 141 | before_reboot_file = self._host.run('cat %s%s' % ( |
| 142 | self._UPDATE_ENGINE_LOG_DIR, files[1])).stdout |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 143 | self._check_for_cellular_entries_in_update_log(before_reboot_file) |
| 144 | |
| 145 | success = 'Update successfully applied, waiting to reboot.' |
David Haddock | 80e3b8f | 2018-04-10 17:44:43 -0700 | [diff] [blame^] | 146 | update_ec = self._host.run('cat %s%s | grep ' |
| 147 | '"%s"' % (self._UPDATE_ENGINE_LOG_DIR, |
| 148 | files[1], success)).exit_status |
David Haddock | ac21089 | 2018-02-05 20:36:27 -0800 | [diff] [blame] | 149 | if update_ec != 0: |
| 150 | raise error.TestFail('We could not verify that the update ' |
| 151 | 'completed successfully. Check the logs.') |
| 152 | return |
| 153 | |
David Haddock | 95e7fbe | 2017-12-01 17:49:53 -0800 | [diff] [blame] | 154 | # Verify that the update completed successfully by checking hostlog. |
| 155 | rootfs_hostlog, reboot_hostlog = self._create_hostlog_files() |
| 156 | self.verify_update_events(self._CUSTOM_LSB_VERSION, rootfs_hostlog) |
| 157 | self.verify_update_events(self._CUSTOM_LSB_VERSION, reboot_hostlog, |
| 158 | self._CUSTOM_LSB_VERSION) |
| 159 | |
| 160 | after = self._get_chromeos_version() |
| 161 | logging.info('Successfully force updated from %s to %s.', before, after) |