You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.1 KiB
156 lines
5.1 KiB
# Copyright 2016 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 socket
|
|
|
|
import common
|
|
from autotest_lib.client.common_lib import hosts
|
|
from autotest_lib.server import utils
|
|
from autotest_lib.server.hosts import servo_constants
|
|
from autotest_lib.server.hosts import cros_constants
|
|
|
|
from chromite.lib import timeout_util
|
|
|
|
|
|
def require_servo(host, ignore_state=False):
|
|
"""Require a DUT to have a working servo for a repair action.
|
|
|
|
@param host Host object that require servo.
|
|
@param ignore_state Ignore servo state as long as the we still have
|
|
servo connection. Some non-critical verifier
|
|
failures may not cause servo connection been
|
|
disconnected.
|
|
"""
|
|
servo_initialized = host.servo is not None
|
|
servo_working = (host.get_servo_state() ==
|
|
servo_constants.SERVO_STATE_WORKING or ignore_state)
|
|
|
|
if not (servo_initialized and servo_working):
|
|
raise hosts.AutoservRepairError(
|
|
'%s has no working servo.' % host.hostname, 'no_working_servo')
|
|
logging.info('Servo dependence is available for the RepairAction/test.')
|
|
|
|
|
|
class SshVerifier(hosts.Verifier):
|
|
"""
|
|
Verifier to test a host's accessibility via `ssh`.
|
|
|
|
This verifier checks whether a given host is reachable over `ssh`.
|
|
In the event of failure, it distinguishes one of three distinct
|
|
conditions:
|
|
* The host can't be found with a DNS lookup.
|
|
* The host doesn't answer to ping.
|
|
* The host answers to ping, but not to ssh.
|
|
"""
|
|
|
|
@timeout_util.TimeoutDecorator(cros_constants.VERIFY_TIMEOUT_SEC)
|
|
def verify(self, host):
|
|
if host.is_up():
|
|
return
|
|
msg = 'No answer to ssh from %s'
|
|
try:
|
|
socket.gethostbyname(host.hostname)
|
|
except Exception as e:
|
|
logging.exception('DNS lookup failure')
|
|
msg = 'Unable to look up %%s in DNS: %s' % e
|
|
else:
|
|
if utils.ping(host.hostname, tries=1, deadline=1) != 0:
|
|
msg = 'No answer to ping from %s'
|
|
raise hosts.AutoservVerifyError(msg % host.hostname)
|
|
|
|
@property
|
|
def description(self):
|
|
return 'host is available via ssh'
|
|
|
|
|
|
class PingVerifier(hosts.Verifier):
|
|
"""
|
|
Verifier to test a host's accessibility via `ping`.
|
|
|
|
This verifier checks whether a given host is reachable over `ping`.
|
|
The device is pingable as soon as booted to level when network driver
|
|
can respond.
|
|
In the event of failure, it distinguishes one of distinct conditions:
|
|
* The host can't be found with a DNS lookup.
|
|
* The host doesn't booted with network drivers.
|
|
"""
|
|
|
|
@timeout_util.TimeoutDecorator(cros_constants.VERIFY_TIMEOUT_SEC)
|
|
def verify(self, host):
|
|
if host.is_up_fast(count=10):
|
|
return
|
|
msg = 'No answer to ping to %s'
|
|
ip_address = None
|
|
try:
|
|
ip_address = socket.gethostbyname(host.hostname)
|
|
except Exception as e:
|
|
logging.exception('DNS lookup failure')
|
|
msg = 'Unable to look up %s in DNS: %s' % (host.hostname, str(e))
|
|
raise hosts.AutoservVerifyError(msg)
|
|
if not ip_address:
|
|
msg = 'Hostname: %s not present in DNS' % host.hostname
|
|
raise hosts.AutoservVerifyError(msg)
|
|
|
|
@property
|
|
def description(self):
|
|
return 'host is available via ping'
|
|
|
|
|
|
class LegacyHostVerifier(hosts.Verifier):
|
|
"""
|
|
Ask a Host instance to perform its own verification.
|
|
|
|
This class exists as a temporary legacy during refactoring to
|
|
provide access to code that hasn't yet been rewritten to use the new
|
|
repair and verify framework.
|
|
"""
|
|
|
|
@timeout_util.TimeoutDecorator(cros_constants.VERIFY_TIMEOUT_SEC)
|
|
def verify(self, host):
|
|
host.verify_software()
|
|
host.verify_hardware()
|
|
|
|
@property
|
|
def description(self):
|
|
return 'Legacy host verification checks'
|
|
|
|
|
|
class RebootRepair(hosts.RepairAction):
|
|
"""Repair a target device by rebooting it."""
|
|
|
|
# Timeout of this action should defined in child class.
|
|
def repair(self, host):
|
|
host.reboot()
|
|
|
|
@property
|
|
def description(self):
|
|
return 'Reboot the host'
|
|
|
|
|
|
class RPMCycleRepair(hosts.RepairAction):
|
|
"""
|
|
Cycle AC power using the RPM infrastructure.
|
|
|
|
This is meant to catch two distinct kinds of failure:
|
|
* If the target has no battery (that is, a chromebox), power
|
|
cycling it may force it back on.
|
|
* If the target has a batter that is discharging or even fully
|
|
drained, power cycling will leave power on, enabling other
|
|
repair procedures.
|
|
"""
|
|
|
|
@timeout_util.TimeoutDecorator(cros_constants.REPAIR_TIMEOUT_SEC)
|
|
def repair(self, host):
|
|
if not host.has_power():
|
|
raise hosts.AutoservRepairError(
|
|
'%s has no RPM connection.' % host.hostname,
|
|
'no_working_rpm')
|
|
host.power_cycle()
|
|
|
|
|
|
@property
|
|
def description(self):
|
|
return 'Power cycle the host with RPM'
|