1# Copyright 2016 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, re 6 7# http://docs.python.org/2/library/errno.html 8import errno 9 10from autotest_lib.client.common_lib import error 11 12class WatchdogTester(object): 13 """Helper class to perform various watchdog tests.""" 14 15 WD_DEV = '/dev/watchdog' 16 17 def _exists_on_client(self): 18 return self._client.run('test -c "%s"' % self.WD_DEV, 19 ignore_status=True).exit_status == 0 20 21 # If daisydog is running, stop it so we can use /dev/watchdog 22 def _stop_daemon(self): 23 """If running, stop daisydog so we can use /dev/watchdog.""" 24 self._client.run('stop daisydog', ignore_status=True) 25 26 def _start_daemon(self): 27 self._client.run('start daisydog', ignore_status=True) 28 29 def _query_hw_interval(self): 30 """Check how long the hardware interval is.""" 31 output = self._client.run('daisydog -c').stdout 32 secs = re.findall(r'HW watchdog interval is (\d*) seconds', output)[0] 33 return int(secs) 34 35 def __init__(self, client): 36 self._client = client 37 self._supported = self._exists_on_client() 38 39 def is_supported(self): 40 return self._supported 41 42 def __enter__(self): 43 self._stop_daemon() 44 self._hw_interval = self._query_hw_interval() 45 46 def trigger_watchdog(self, timeout=60): 47 """ 48 Trigger a watchdog reset by opening the watchdog device but not petting 49 it. Will ensure the device goes down and comes back up again. 50 """ 51 52 try: 53 self._client.run('echo "z" > %s' % self.WD_DEV) 54 except error.AutoservRunError, e: 55 raise error.TestError('write to %s failed (%s)' % 56 (self.WD_DEV, errno.errorcode[e.errno])) 57 58 logging.info("WatchdogHelper: tickled watchdog on %s (%ds to reboot)", 59 self._client.hostname, self._hw_interval) 60 61 # machine should became unpingable after lockup 62 # ...give 5 seconds slack... 63 wait_down = self._hw_interval + 5 64 if not self._client.wait_down(timeout=wait_down): 65 raise error.TestError('machine should be unpingable ' 66 'within %d seconds' % wait_down) 67 68 # make sure the machine comes back, 69 # DHCP can take up to 45 seconds in odd cases. 70 if not self._client.wait_up(timeout=timeout): 71 raise error.TestError('machine did not reboot/ping within ' 72 '%d seconds of HW reset' % timeout) 73 74 def __exit__(self, exception, value, traceback): 75 self._start_daemon() 76