1# Copyright (c) 2013 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. 4 5import logging 6import traceback 7from autotest_lib.client.common_lib import error 8from autotest_lib.server import test 9 10class platform_CrashStateful(test.test): 11 """Tests the crash recovery of the stateful file system 12 13 1. Create a specific file 'charlie' 14 2. Sync 15 3. Crash system 16 4. Wait for reboot 17 5. Check if 'charlie' is there and complete 18 6. Clean up 19 20 Do the samething with an ecryptfs volume. 21 """ 22 version = 1 23 _STATEFUL_DIR = '/usr/local/CrashDir' 24 _ECRYPT_DIR = '/usr/local/ecryptfs_tst' 25 _ECRYPT_MOUNT_POINT = '/usr/local/ecryptfs_mnt' 26 _ECRYPT_TEST_DIR = '%s/CrashDir' % _ECRYPT_MOUNT_POINT 27 28 29 def _run(self, cmd): 30 """Run the give command and log results 31 32 @param cmd: command to be run 33 """ 34 result = self.client.run(cmd) 35 if result.exit_status != 0: 36 logging.error('%s: %s', cmd, result.stdout) 37 38 39 def _ecrypt_mount(self, edir, mnt): 40 """Mount the eCrypt File System 41 42 @param ddir: directory where encrypted file system is stored 43 @param mnt: mount point for encrypted file system 44 """ 45 options = ('-o' 46 ' key=passphrase:passphrase_passwd=secret' 47 ',ecryptfs_cipher=aes' 48 ',ecryptfs_key_bytes=32' 49 ',no_sig_cache' 50 ',ecryptfs_passthrough=no' 51 ',ecryptfs_enable_filename_crypto=no') 52 self._run('mkdir -p %s %s' % (edir, mnt)) 53 self._run('mount -t ecryptfs %s %s %s' % 54 (options, edir, mnt)) 55 56 57 def _ecrypt_unmount(self, edir, mnt): 58 """Unmount the eCrypt File System and remove it and its mount point 59 60 @param dir: directory where encrypted file system is stored 61 @param mnt: mount point for encrypted file system 62 """ 63 self._run('umount %s' % mnt) 64 self._run('rm -R %s' % edir) 65 self._run('rm -R %s' % mnt) 66 67 68 def _crash(self): 69 """crash the client without giving anything a chance to clean up 70 71 We use the kernel crash testing interface to immediately reboot the 72 system. No chance for any flushing of I/O or cleaning up. 73 """ 74 logging.info('CrashStateful: force panic %s', self.client.hostname) 75 interface = "/sys/kernel/debug/provoke-crash/DIRECT" 76 cmd = 'echo PANIC > %s' % interface 77 if not self.client.run('ls %s' % interface, 78 ignore_status=True).exit_status == 0: 79 interface = "/proc/breakme" 80 cmd = 'echo panic > %s' % interface 81 try: 82 """The following is necessary to avoid command execution errors 83 1) If ssh on the DUT doesn't terminate cleanly, it will exit with 84 status 255 causing an exception 85 2) ssh won't terminate if a background process holds open stdin, 86 stdout, or stderr 87 3) without a sleep delay, the reboot may close the connection with 88 an error 89 """ 90 wrapped_cmd = 'sleep 1; %s' 91 self.client.reboot(reboot_cmd=wrapped_cmd % cmd) 92 except error.AutoservRebootError as e: 93 raise error.TestFail('%s.\nTest failed with error %s' % ( 94 traceback.format_exc(), str(e))) 95 96 97 def _create_file_and_crash(self, dir): 98 """Sets up first part of test, then crash 99 100 @param dir - directory where test files are created 101 """ 102 self._run('mkdir -p %s' % dir) 103 self._run('echo charlie smith >%s/charlie' % dir) 104 self._run('sync') 105 self._crash() 106 107 108 def _verify_and_cleanup(self, dir): 109 """Verify results and clean up 110 111 @param dir - directory where test files were created 112 """ 113 result = self.client.run('cat %s/charlie' % dir) 114 hi = result.stdout.strip() 115 if hi != 'charlie smith': 116 raise error.TestFail('Test failed, Sync mechanism failed') 117 self._run('rm -fr %s' % dir) 118 119 120 def _crash_stateful(self, dir): 121 """Crash the stateful file system while changing it 122 123 @param dir - directory where test files are created 124 """ 125 self._create_file_and_crash(dir) 126 self._verify_and_cleanup(dir) 127 128 129 def _crash_ecrptfs(self, edir, mnt, dir): 130 """Crash the stateful file system while changing it 131 132 @param edir - directory used for the encrypted file system 133 @param mnt - mount point for the encrypted file system 134 @param dir - directory where test files are created 135 """ 136 self._ecrypt_mount(edir, mnt) 137 self._create_file_and_crash(dir) 138 self._ecrypt_mount(edir, mnt) 139 self._verify_and_cleanup(dir) 140 self._ecrypt_unmount(edir, mnt) 141 142 143 def run_once(self, host=None): 144 """run_once runs the test. 145 146 1. Runs a crash test on stateful partition 147 2. Create an ecryptfs volume and run the same 148 crash test 149 150 @param host - the host machine running the test 151 """ 152 self.client = host 153 154 self._crash_stateful(self._STATEFUL_DIR) 155 156 self._crash_ecrptfs(self._ECRYPT_DIR, self._ECRYPT_MOUNT_POINT, 157 self._ECRYPT_TEST_DIR) 158