blob: ec254187d9d4e6c02138a7663e235710b04c6db3 [file] [log] [blame]
Julius Wernerfe3474b2016-03-23 17:40:05 -07001# 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()