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 6import socket 7 8import common 9from autotest_lib.client.common_lib import hosts 10from autotest_lib.server import utils 11 12 13def require_servo(host): 14 """Require a DUT to have a working servo for a repair action.""" 15 if not host.servo: 16 raise hosts.AutoservRepairError( 17 '%s has no working servo.' % host.hostname, 'no_working_servo') 18 19 20class SshVerifier(hosts.Verifier): 21 """ 22 Verifier to test a host's accessibility via `ssh`. 23 24 This verifier checks whether a given host is reachable over `ssh`. 25 In the event of failure, it distinguishes one of three distinct 26 conditions: 27 * The host can't be found with a DNS lookup. 28 * The host doesn't answer to ping. 29 * The host answers to ping, but not to ssh. 30 """ 31 32 def verify(self, host): 33 if host.is_up(): 34 return 35 msg = 'No answer to ssh from %s' 36 try: 37 socket.gethostbyname(host.hostname) 38 except Exception as e: 39 logging.exception('DNS lookup failure') 40 msg = 'Unable to look up %%s in DNS: %s' % e 41 else: 42 if utils.ping(host.hostname, tries=1, deadline=1) != 0: 43 msg = 'No answer to ping from %s' 44 raise hosts.AutoservVerifyError(msg % host.hostname) 45 46 47 @property 48 def description(self): 49 return 'host is available via ssh' 50 51 52class LegacyHostVerifier(hosts.Verifier): 53 """ 54 Ask a Host instance to perform its own verification. 55 56 This class exists as a temporary legacy during refactoring to 57 provide access to code that hasn't yet been rewritten to use the new 58 repair and verify framework. 59 """ 60 61 def verify(self, host): 62 host.verify_software() 63 host.verify_hardware() 64 65 66 @property 67 def description(self): 68 return 'Legacy host verification checks' 69 70 71class RebootRepair(hosts.RepairAction): 72 """Repair a target device by rebooting it.""" 73 74 def repair(self, host): 75 host.reboot() 76 77 78 @property 79 def description(self): 80 return 'Reboot the host' 81 82 83class RPMCycleRepair(hosts.RepairAction): 84 """ 85 Cycle AC power using the RPM infrastructure. 86 87 This is meant to catch two distinct kinds of failure: 88 * If the target has no battery (that is, a chromebox), power 89 cycling it may force it back on. 90 * If the target has a batter that is discharging or even fully 91 drained, power cycling will leave power on, enabling other 92 repair procedures. 93 """ 94 95 def repair(self, host): 96 if not host.has_power(): 97 raise hosts.AutoservRepairError( 98 '%s has no RPM connection.' % host.hostname, 99 'no_working_rpm') 100 host.power_cycle() 101 if not host.wait_up(timeout=host.BOOT_TIMEOUT): 102 raise hosts.AutoservRepairError( 103 '%s is still offline after powercycling' % 104 host.hostname, 'failed_to_boot_after_rpm_power_cycle') 105 106 107 @property 108 def description(self): 109 return 'Power cycle the host with RPM' 110