170 lines
7.5 KiB
Python
170 lines
7.5 KiB
Python
# Copyright 2018 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
|
|
import urlparse
|
|
|
|
from autotest_lib.client.bin import test, utils
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.cros.update_engine import dlc_util
|
|
from autotest_lib.client.cros.update_engine import update_engine_util
|
|
|
|
class UpdateEngineTest(test.test, update_engine_util.UpdateEngineUtil):
|
|
"""Base class for update engine client tests."""
|
|
|
|
_NETWORK_INTERFACES = ['eth0', 'eth1', 'eth2']
|
|
|
|
|
|
def initialize(self):
|
|
"""Initialize for this test."""
|
|
self._set_util_functions(utils.run, shutil.copy)
|
|
self._internet_was_disabled = False
|
|
|
|
# Utilities for DLC management
|
|
self._dlc_util = dlc_util.DLCUtil(self._run)
|
|
|
|
|
|
def cleanup(self):
|
|
"""Cleanup for this test."""
|
|
# Make sure to grab the update engine log for every test run.
|
|
shutil.copy(self._UPDATE_ENGINE_LOG, self.resultsdir)
|
|
|
|
# Ensure ethernet adapters are back on
|
|
self._enable_internet()
|
|
|
|
|
|
def _enable_internet(self, ping_server='google.com'):
|
|
"""
|
|
Re-enables the internet connection.
|
|
|
|
@param ping_server: The server to ping to check we are online.
|
|
|
|
"""
|
|
if not self._internet_was_disabled:
|
|
return
|
|
|
|
self._internet_was_disabled = False
|
|
logging.debug('Before reconnect: %s', utils.run(['ifconfig']))
|
|
for eth in self._NETWORK_INTERFACES:
|
|
utils.run(['ifconfig', eth, 'up'], ignore_status=True)
|
|
utils.start_service('recover_duts', ignore_status=True)
|
|
|
|
# Print ifconfig to help debug DUTs that stay offline.
|
|
logging.debug('After reconnect: %s', utils.run(['ifconfig']))
|
|
|
|
# We can't return right after reconnecting the network or the server
|
|
# test may not receive the message. So we wait a bit longer for the
|
|
# DUT to be reconnected.
|
|
utils.poll_for_condition(lambda: utils.ping(ping_server,
|
|
tries=3, timeout=10) == 0,
|
|
timeout=120,
|
|
sleep_interval=1,
|
|
exception=error.TestFail(
|
|
'Ping failed after reconnecting network'))
|
|
|
|
|
|
def _disable_internet(self, ping_server='google.com'):
|
|
"""Disable the internet connection"""
|
|
self._internet_was_disabled = True
|
|
try:
|
|
logging.debug('Before disconnect: %s', utils.run(['ifconfig']))
|
|
# DUTs in the lab have a service called recover_duts that is used to
|
|
# check that the DUT is online and if it is not it will bring it
|
|
# back online. We will need to stop this service for the length
|
|
# of this test.
|
|
utils.stop_service('recover_duts', ignore_status=True)
|
|
for eth in self._NETWORK_INTERFACES:
|
|
result = utils.run(['ifconfig', eth, 'down'],
|
|
ignore_status=True)
|
|
logging.debug(result)
|
|
|
|
# Print ifconfig to help debug DUTs that stay online.
|
|
logging.debug('After disconnect: %s', utils.run('ifconfig'))
|
|
|
|
# Make sure we are offline
|
|
utils.poll_for_condition(lambda: utils.ping(ping_server,
|
|
deadline=5,
|
|
timeout=5) != 0,
|
|
timeout=60,
|
|
sleep_interval=1,
|
|
desc='Ping failure while offline.')
|
|
except (error.CmdError, utils.TimeoutError):
|
|
logging.exception('Failed to disconnect one or more interfaces.')
|
|
logging.debug(utils.run(['ifconfig'], ignore_status=True))
|
|
raise error.TestFail('Disabling the internet connection failed.')
|
|
|
|
|
|
def _disconnect_reconnect_network_test(self, update_url,
|
|
time_without_network=120,
|
|
accepted_movement=0.015):
|
|
"""
|
|
Disconnects the network for a period of time, verifies that the update
|
|
pauses, reconnects the network, and ensures that the update picks up
|
|
from where it left off. This will be used as a part of
|
|
autoupdate_ForcedOOBEUpdate.interrupt and autoupdate_Interruptions.
|
|
|
|
@param update_url: The update url used by the test. We will ping it to
|
|
check whether we are online/offline.
|
|
@param time_without_network: Duration of the network disconnection in
|
|
seconds.
|
|
@param accepted_movement: Acceptable movement of update_engine
|
|
progress after the network is disabled.
|
|
Sometimes when network is disabled
|
|
update_engine progress will move a little,
|
|
which can cause false positives.
|
|
|
|
"""
|
|
logging.info('Starting network interruption check.')
|
|
if self._is_update_finished_downloading():
|
|
raise error.TestFail('The update has already finished before we '
|
|
'can disconnect network.')
|
|
self._update_server = urlparse.urlparse(update_url).hostname
|
|
self._disable_internet()
|
|
|
|
# Check that we are offline.
|
|
result = utils.ping(self._update_server, deadline=5, timeout=5)
|
|
if result != 2:
|
|
raise error.TestFail('Ping succeeded even though we were offline.')
|
|
|
|
# We are seeing update_engine progress move a very tiny amount
|
|
# after disconnecting network so wait for it to stop moving.
|
|
utils.poll_for_condition(lambda: self._has_progress_stopped,
|
|
desc='Waiting for update progress to stop.')
|
|
|
|
# Get the update progress as the network is down
|
|
progress_before = float(self._get_update_engine_status()[
|
|
self._PROGRESS])
|
|
|
|
seconds = 1
|
|
while seconds < time_without_network:
|
|
logging.info(self._get_update_engine_status())
|
|
time.sleep(1)
|
|
seconds += 1
|
|
|
|
progress_after = float(self._get_update_engine_status()[
|
|
self._PROGRESS])
|
|
|
|
if progress_before != progress_after:
|
|
if progress_before < progress_after:
|
|
if progress_after - progress_before > accepted_movement:
|
|
raise error.TestFail('The update continued while the '
|
|
'network was supposedly disabled. '
|
|
'Before: %f, After: %f' % (
|
|
progress_before, progress_after))
|
|
else:
|
|
logging.warning('The update progress moved slightly while '
|
|
'network was off.')
|
|
elif self._is_update_finished_downloading():
|
|
raise error.TestFail('The update finished while the network '
|
|
'was disabled. Before: %f, After: %f' %
|
|
(progress_before, progress_after))
|
|
else:
|
|
raise error.TestFail('The update appears to have restarted. '
|
|
'Before: %f, After: %f' % (progress_before,
|
|
progress_after))
|
|
|
|
self._enable_internet()
|