blob: 8d277e794889cdbaae7bdf7faa26a63f072a7e87 [file] [log] [blame] [edit]
# Copyright (c) 2014 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 os
import time
from autotest_lib.client.common_lib import error
from autotest_lib.server import autotest
from autotest_lib.server import hosts
from autotest_lib.server import test
from autotest_lib.server.cros import remote_command
class network_DiskFull(test.test):
"""Test networking daemons when /var is full."""
version = 1
CLIENT_TEST_LIST = [
('network_DhcpNegotiationSuccess', {}),
('network_DhcpRenew', {}),
('network_RestartShill', {
'tag': 'profile_exists',
'remove_profile': False}),
('network_RestartShill', {
'tag': 'profile_missing',
'remove_profile': True}),
]
CLIENT_TMP_DIR = '/tmp'
DISK_FILL_SCRIPT = 'hog_disk.sh'
FILL_TIMEOUT_SECONDS = 5
MAX_FREE_KB = 1024
STATEFUL_PATH = '/var'
TEST_TIMEOUT_SECONDS = 180
def get_free_kilobytes(self, mount_point):
"""
Get the size of free space on the filesystem mounted at |mount_point|,
in kilobytes.
@return Kilobytes free, as an integer.
"""
# Filesystem 1024-blocks Used Available Capacity Mount...
# /dev/mapper/encstateful 290968 47492 243476 17% /var
output = self._client.run('df -P %s' % mount_point).stdout
lines = output.splitlines()
if len(lines) != 2:
raise error.TestFail('Unexpected df output: %s' % lines)
_, _, _, free_kb, _, df_mount_point = lines[1].split(None, 5)
if df_mount_point != mount_point:
raise error.TestFail('Failed to find %s, got %s instead.' %
(mount_point, df_mount_point))
return int(free_kb)
def wait_until_full(self, mount_point, max_free_kilobytes):
"""
Wait until |mount_point| has no more than |max_free_kilobytes| free.
@param mount_point The path at which the filesystem is mounted.
@param max_free_kilobytes Maximum free space permitted, in kilobytes.
@return True if the disk is full, else False
"""
start_time = time.time()
while time.time() - start_time < self.FILL_TIMEOUT_SECONDS:
if (self.get_free_kilobytes(mount_point) <= max_free_kilobytes):
return True
else:
time.sleep(1)
return False
def run_once(self, client_addr):
"""
Test main loop.
@param client_addr DUT hostname or IP address.
"""
self._client = hosts.create_host(client_addr)
client_autotest = autotest.Autotest(self._client)
disk_filler_src = os.path.join(self.bindir, self.DISK_FILL_SCRIPT)
disk_filler_dst = os.path.join(self.CLIENT_TMP_DIR,
os.path.basename(self.DISK_FILL_SCRIPT))
self._client.send_file(disk_filler_src, disk_filler_dst)
disk_filler_command = '%s %s %d' % (
disk_filler_dst, self.STATEFUL_PATH, self.TEST_TIMEOUT_SECONDS)
with remote_command.Command(self._client, disk_filler_command) \
as disk_filler_process:
if not self.wait_until_full(self.STATEFUL_PATH, self.MAX_FREE_KB):
logging.debug(disk_filler_process.result)
raise error.TestFail(
'did not fill %s within %d seconds' % (
self.STATEFUL_PATH, self.FILL_TIMEOUT_SECONDS))
client_autotest.run_test('network_CheckCriticalProcesses',
tag='before_client_tests')
passed_with_failsafe = []
for name, kwargs in self.CLIENT_TEST_LIST:
# Autotest goes to /mnt/stateful_partition/dev_image,
# while /var is on /mnt/stateful_partition/encrypted.
#
# These are separate partitions, so we can copy
# the tests onto the DUT even when /var is full.
client_autotest.run_test(name, **kwargs)
if 'tag' in kwargs:
full_test_name = '%s.%s' % (name, kwargs['tag'])
else:
full_test_name = name
# To avoid leaving the system in a bad state, the disk
# filler times out eventually. This means a test can
# "pass" due to the failsafe. Check if the failsafe
# kicked in, by checking if the disk is still full.
if (self.get_free_kilobytes(self.STATEFUL_PATH) >
self.MAX_FREE_KB):
passed_with_failsafe.append(full_test_name)
client_autotest.run_test('network_CheckCriticalProcesses',
tag='after_%s' % full_test_name)
if len(passed_with_failsafe):
raise error.TestFail(
'%d test(s) triggered the fail-safe: %s. '
'They may be incorrectly listed as passing.' % (
len(passed_with_failsafe),
', '.join(passed_with_failsafe)))