blob: 25c9ab2d6e4c511686797d33495a298ff3f38eef [file] [log] [blame]
#!/usr/bin/env python2
# Copyright 2020 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 common
import base
import constants
import servo_updater
from autotest_lib.server.cros.storage import storage_validate as storage
from autotest_lib.client.common_lib import utils as client_utils
try:
from chromite.lib import metrics
except ImportError:
metrics = client_utils.metrics_mock
class VerifyDutStorage(base._BaseDUTVerifier):
"""Verify the state of the storage on the DUT
The process to determine the type of storage and read metrics
of usage and EOL(end-of-life) information to determine the
state.
Supported storage types: MMS, NVME, SSD.
Possible states are:
UNKNOWN - not access to the DUT, not determine type of storage,
not information to determine metrics
NORMAL - the storage is in good shape and will work stable
device will work stable. (supported for all types)
ACCEPTABLE - the storage almost used all resources, device will
work stable but it is better be ready for replacement
device will work stable. (supported by MMS, NVME)
NEED_REPLACEMENT - the storage broken or worn off the life limit
device can work by not stable and can cause the
flakiness on the tests. (supported by all types)
"""
def __init__(self, dut_host):
super(VerifyDutStorage, self).__init__(dut_host)
self._state = None
def _verify(self, set_label=True):
try:
validator = storage.StorageStateValidator(self.get_host())
storage_type = validator.get_type()
logging.debug('Detected storage type: %s', storage_type)
storage_state = validator.get_state()
logging.debug('Detected storage state: %s', storage_state)
state = self.convert_state(storage_state)
if state and set_label:
self._set_host_info_state(constants.DUT_STORAGE_STATE_PREFIX,
state)
self._state = state
except Exception as e:
raise base.AuditError('Exception during getting state of'
' storage %s' % str(e))
def convert_state(self, state):
"""Mapping state from validator to verifier"""
if state == storage.STORAGE_STATE_NORMAL:
return constants.HW_STATE_NORMAL
if state == storage.STORAGE_STATE_WARNING:
return constants.HW_STATE_ACCEPTABLE
if state == storage.STORAGE_STATE_CRITICAL:
return constants.HW_STATE_NEED_REPLACEMENT
return None
def get_state(self):
return self._state
class VerifyServoUsb(base._BaseServoVerifier):
"""Verify the state of the USB-drive on the Servo
The process to determine by checking the USB-drive on having any
bad sectors on it.
Possible states are:
UNKNOWN - not access to the device or servo, not available
software on the servo.
NORMAL - the device available for testing and not bad sectors.
was found on it, device will work stable
NEED_REPLACEMENT - the device available for testing and
some bad sectors were found on it. The device can
work but cause flakiness in the tests or repair process.
badblocks errors:
No such device or address while trying to determine device size
"""
def _verify(self):
servo = self.get_host().get_servo()
usb = servo.probe_host_usb_dev()
if not usb:
logging.error('Usb not detected')
metrics.Counter(
'chromeos/autotest/servo/usb/not_detected'
).increment(fields={'host': self._dut_host.hostname})
self._set_state(constants.HW_STATE_NEED_REPLACEMENT)
return
state = None
try:
# The USB will be format during checking to the bad blocks.
command = 'badblocks -sw -e 1 -t 0xff %s' % usb
logging.info('Running command: %s', command)
# The response is the list of bad block on USB.
result = servo.system_output(command)
logging.info("Check result: '%s'", result)
if result:
# So has result is Bad and empty is Good.
state = constants.HW_STATE_NEED_REPLACEMENT
else:
state = constants.HW_STATE_NORMAL
except Exception as e:
if 'Timeout encountered:' in str(e):
logging.info('Timeout during running action')
metrics.Counter(
'chromeos/autotest/audit/servo/usb/timeout'
).increment(fields={'host': self._dut_host.hostname})
else:
# badblocks generate errors when device not reachable or
# cannot read system information to execute process
state = constants.HW_STATE_NEED_REPLACEMENT
logging.debug(str(e))
self._set_state(state)
# install fresh image to the USB because badblocks formats it
# https://crbug.com/1091406
try:
logging.debug('Started to install test image to USB-drive')
_, image_path = self._dut_host.stage_image_for_servo()
servo.image_to_servo_usb(image_path, power_off_dut=False)
logging.debug('Finished installing test image to USB-drive')
except:
# ignore any error which happined during install image
# it not relative to the main goal
logging.debug('Fail to install test image to USB-drive')
pass
def _set_state(self, state):
if state:
self._set_host_info_state(constants.SERVO_USB_STATE_PREFIX, state)
class VerifyServoFw(base._BaseServoVerifier):
"""Force update Servo firmware if it not up-to-date.
This is rarely case when servo firmware was not updated by labstation
when servod started. This should ensure that the servo_v4 and
servo_micro is up-to-date.
"""
UPDATERS = [
servo_updater.UpdateServoV4Fw,
servo_updater.UpdateServoMicroFw,
]
def _verify(self):
host = self.get_host()
# create all updater
updaters = [updater(host) for updater in self.UPDATERS]
# run checker for all updaters
for updater in updaters:
supported = updater.check_needs()
logging.debug('The board %s is supported: %s',
updater.get_board(), supported)
# to run updater we need stop servod
host.stop_servod()
# run update
for updater in updaters:
try:
updater.update()
except Exception as e:
metrics.Counter(
'chromeos/autotest/audit/servo/fw/update/error'
).increment(fields={'host': self._dut_host.hostname})
logging.info('Fail update firmware for %s',
updater.get_board())
logging.debug('Fail update firmware for %s: %s',
updater.get_board(), str(e))
# starting servod to restore previous state
host.start_servod()