# Copyright (c) 2013 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 traceback from autotest_lib.client.common_lib import error from autotest_lib.server import test class platform_CrashStateful(test.test): """Tests the crash recovery of the stateful file system 1. Create a specific file 'charlie' 2. Sync 3. Crash system 4. Wait for reboot 5. Check if 'charlie' is there and complete 6. Clean up Do the samething with an ecryptfs volume. """ version = 1 _STATEFUL_DIR = '/usr/local/CrashDir' _ECRYPT_DIR = '/usr/local/ecryptfs_tst' _ECRYPT_MOUNT_POINT = '/usr/local/ecryptfs_mnt' _ECRYPT_TEST_DIR = '%s/CrashDir' % _ECRYPT_MOUNT_POINT def _run(self, cmd): """Run the give command and log results @param cmd: command to be run """ result = self.client.run(cmd) if result.exit_status != 0: logging.error('%s: %s', cmd, result.stdout) def _ecrypt_mount(self, edir, mnt): """Mount the eCrypt File System @param ddir: directory where encrypted file system is stored @param mnt: mount point for encrypted file system """ options = ('-o' ' key=passphrase:passphrase_passwd=secret' ',ecryptfs_cipher=aes' ',ecryptfs_key_bytes=32' ',no_sig_cache' ',ecryptfs_passthrough=no' ',ecryptfs_enable_filename_crypto=no') self._run('mkdir -p %s %s' % (edir, mnt)) self._run('mount -t ecryptfs %s %s %s' % (options, edir, mnt)) def _ecrypt_unmount(self, edir, mnt): """Unmount the eCrypt File System and remove it and its mount point @param dir: directory where encrypted file system is stored @param mnt: mount point for encrypted file system """ self._run('umount %s' % mnt) self._run('rm -R %s' % edir) self._run('rm -R %s' % mnt) def _crash(self): """crash the client without giving anything a chance to clean up We use the kernel crash testing interface to immediately reboot the system. No chance for any flushing of I/O or cleaning up. """ logging.info('CrashStateful: force panic %s', self.client.hostname) interface = "/sys/kernel/debug/provoke-crash/DIRECT" cmd = 'echo PANIC > %s' % interface if not self.client.run('ls %s' % interface, ignore_status=True).exit_status == 0: interface = "/proc/breakme" cmd = 'echo panic > %s' % interface try: """The following is necessary to avoid command execution errors 1) If ssh on the DUT doesn't terminate cleanly, it will exit with status 255 causing an exception 2) ssh won't terminate if a background process holds open stdin, stdout, or stderr 3) without a sleep delay, the reboot may close the connection with an error """ wrapped_cmd = 'sleep 1; %s' self.client.reboot(reboot_cmd=wrapped_cmd % cmd) except error.AutoservRebootError as e: raise error.TestFail('%s.\nTest failed with error %s' % ( traceback.format_exc(), str(e))) def _create_file_and_crash(self, dir): """Sets up first part of test, then crash @param dir - directory where test files are created """ self._run('mkdir -p %s' % dir) self._run('echo charlie smith >%s/charlie' % dir) self._run('sync') self._crash() def _verify_and_cleanup(self, dir): """Verify results and clean up @param dir - directory where test files were created """ result = self.client.run('cat %s/charlie' % dir) hi = result.stdout.strip() if hi != 'charlie smith': raise error.TestFail('Test failed, Sync mechanism failed') self._run('rm -fr %s' % dir) def _crash_stateful(self, dir): """Crash the stateful file system while changing it @param dir - directory where test files are created """ self._create_file_and_crash(dir) self._verify_and_cleanup(dir) def _crash_ecrptfs(self, edir, mnt, dir): """Crash the stateful file system while changing it @param edir - directory used for the encrypted file system @param mnt - mount point for the encrypted file system @param dir - directory where test files are created """ self._ecrypt_mount(edir, mnt) self._create_file_and_crash(dir) self._ecrypt_mount(edir, mnt) self._verify_and_cleanup(dir) self._ecrypt_unmount(edir, mnt) def run_once(self, host=None): """run_once runs the test. 1. Runs a crash test on stateful partition 2. Create an ecryptfs volume and run the same crash test @param host - the host machine running the test """ self.client = host self._crash_stateful(self._STATEFUL_DIR) self._crash_ecrptfs(self._ECRYPT_DIR, self._ECRYPT_MOUNT_POINT, self._ECRYPT_TEST_DIR)