blob: d3427bc496290872e0bbe57a95a83db1991426c2 [file] [log] [blame]
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import shutil
import time
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros.cellular import test_environment
from autotest_lib.client.cros.update_engine import nano_omaha_devserver
class autoupdate_StartOOBEUpdate(test.test):
"""Starts a forced update at OOBE.
Chrome OS will restart when the update is complete so this test will just
start the update. The rest of the processing will be done in a server
side test.
"""
version = 1
_CUSTOM_LSB_RELEASE = '/mnt/stateful_partition/etc/lsb-release'
def setup(self):
utils.run('rm %s' % self._CUSTOM_LSB_RELEASE, ignore_status=True)
def cleanup(self):
logging.info('Update engine log saved to results dir.')
shutil.copy('/var/log/update_engine.log', self.resultsdir)
def _setup_custom_lsb_release(self, update_url):
"""Create a custom lsb-release file.
In order to tell OOBE to ping a different update server than the
default we need to create our own lsb-release. We will include a
deserver update URL.
@param update_url: The update url to use.
"""
utils.run('mkdir /mnt/stateful_partition/etc', ignore_status=True)
utils.run('touch %s' % self._CUSTOM_LSB_RELEASE)
utils.run('echo CHROMEOS_RELEASE_VERSION=0.0.0.0 >> %s' %
self._CUSTOM_LSB_RELEASE)
utils.run('echo CHROMEOS_AUSERVER=%s >> %s' %
(update_url, self._CUSTOM_LSB_RELEASE))
def _skip_to_oobe_update_screen(self):
"""Skips to the OOBE update check screen."""
self._oobe.WaitForJavaScriptCondition("typeof Oobe == 'function' && "
"Oobe.readyForTesting",
timeout=30)
self._oobe.ExecuteJavaScript('Oobe.skipToUpdateForTesting()')
def _is_update_started(self):
"""Checks if the update has started."""
status = utils.run('update_engine_client --status',
ignore_timeout=True).stdout
status = status.splitlines()
logging.info(status)
return any(arg in status[2] for arg in ['UPDATE_STATUS_DOWNLOADING',
'UPDATE_STATUS_FINALIZING'])
def _wait_for_update_to_complete(self):
"""Checks if the update has got to FINALIZING status."""
while True:
status = utils.run('update_engine_client --status',
ignore_timeout=True, timeout=10)
# During reboot, status will be None
if status is not None:
status = status.stdout.splitlines()
logging.debug(status)
statuses = ['UPDATE_STATUS_FINALIZING',
'UPDATE_STATUS_UPDATED_NEED_REBOOT']
if any(arg in status[2] for arg in statuses):
break
time.sleep(1)
def _start_oobe_update(self, url):
"""
Jump to the update check screen at OOBE and wait for update to start.
@param url: The omaha update URL we expect to call.
"""
self._setup_custom_lsb_release(url)
# Start chrome instance to interact with OOBE.
self._chrome = chrome.Chrome(auto_login=False)
self._oobe = self._chrome.browser.oobe
self._skip_to_oobe_update_screen()
try:
utils.poll_for_condition(self._is_update_started,
error.TestFail('Update did not start.'),
timeout=30)
except error.TestFail as e:
if self._critical_update:
raise e
def run_once(self, image_url, cellular=False, payload_info=None,
full_payload=True, critical_update=True):
"""
Test that will start a forced update at OOBE.
@param image_url: The omaha URL to call. It contains the payload url
for cellular tests.
@param cellular: True if we should run this test using a sim card.
@payload_payload_info: For cellular tests we need to have our own
omaha instance and this is a dictionary of
payload information to be used in the omaha
response.
@full_payload: True for full payloads, False for delta.
"""
utils.run('restart update-engine')
self._critical_update = critical_update
if cellular:
try:
test_env = test_environment.CellularOTATestEnvironment()
CONNECT_TIMEOUT = 120
with test_env:
service = test_env.shill.wait_for_cellular_service_object()
if not service:
raise error.TestError('No cellular service found.')
test_env.shill.connect_service_synchronous(
service, CONNECT_TIMEOUT)
# Setup an omaha instance on the DUT because we cant reach
# devservers over cellular.
self._omaha = nano_omaha_devserver.NanoOmahaDevserver()
self._omaha.set_image_params(image_url,
payload_info['size'],
payload_info['sha256'],
is_delta=not full_payload,
critical=True)
self._omaha.start()
# We will tell OOBE to call localhost for update requests.
url = 'http://127.0.0.1:%d/update' % self._omaha.get_port()
self._start_oobe_update(url)
# Remove the custom omaha server from lsb release because
# after we reboot it will no longer be running.
utils.run('rm %s' % self._CUSTOM_LSB_RELEASE,
ignore_status=True)
# We need to return from the client test before OOBE
# reboots or the server side test will hang. But we cannot
# return right away when the OOBE update starts because
# all of the code from using a cellular connection is in
# client side and we will switch back to ethernet. So we
# need to wait for the update to get as close to the end as
# possible so that we are done downloading the payload
# via cellular and don't need to ping omaha again. When
# the DUT reboots it will send a final update ping to
# production omaha and then move to the sign in screen.
self._wait_for_update_to_complete()
except error.TestError as e:
logging.error('Failure setting up sim card.')
raise error.TestFail(e)
else:
self._start_oobe_update(image_url)