| # Copyright 2021 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import time |
| |
| from autotest_lib.server import test |
| from autotest_lib.server.hosts import cros_firmware |
| from autotest_lib.client.common_lib import error |
| |
| |
| class fleet_FirmwareUpdate(test.test): |
| """Test to update OS bundled firmware and validate DUT is in good state.""" |
| version = 1 |
| |
| UPDATE_CMD = "/usr/sbin/chromeos-firmwareupdate --wp=1 --mode=autoupdate" |
| |
| def update_os_bundled_firmware(self, host): |
| """Update OS bundled firmware, RW only. |
| |
| Args: |
| host: Target host machine to update firmware. |
| |
| raises: |
| error.TestFail if update firmware cmd return with non-zero code. |
| """ |
| logging.info("Starting update firmware on %s.", host.hostname) |
| try: |
| res = host.run(self.UPDATE_CMD) |
| except: |
| raise error.TestFail("Failed to update firmware.") |
| |
| def pre_update_validation(self, host): |
| """Validate DUT is in good state before firmware update. |
| |
| Args: |
| host: Target host machine to do the validation. |
| |
| raises: |
| error.TestNAError if DUT is not sshable, or not come back after |
| reboot. |
| """ |
| # Ensure the DUT is sshable before firmware update. |
| if not host.is_up(): |
| raise error.TestNAError("DUT is down before firmware update.") |
| |
| # Ensure the DUT can reboot normally before firmware update. |
| logging.info("Rebooting %s prior firmware update", host.hostname) |
| try: |
| host.reboot(timeout=host.BOOT_TIMEOUT, wait=True) |
| except Exception as e: |
| logging.error(e) |
| raise error.TestNAError("DUT failed to reboot before firmware" |
| " update.") |
| |
| def is_firmware_updated(self, host): |
| """Check whether the DUT is updated to OS bundled firmware. |
| |
| Args: |
| host: Target host machine to check. |
| """ |
| expected = cros_firmware._get_available_firmware(host) |
| if not expected: |
| logging.info("Couldn't get expected version based on model" |
| " info, skip firmware version check.") |
| actual = host.run("crossystem fwid").stdout |
| logging.debug("Expected firmware: %s, actual firmware on DUT: %s.", |
| expected, actual) |
| return expected == actual |
| |
| def post_update_validation(self, host): |
| """Validate DUT is good after firmware update. |
| |
| Args: |
| host: Target host machine to do the validation. |
| |
| raises: |
| error.TestFail if the DUT failed to pass validation. |
| """ |
| try: |
| host.reboot(timeout=host.BOOT_TIMEOUT, wait=True) |
| except Exception as e: |
| logging.error(e) |
| raise error.TestFail("DUT didn't come back from reboot after" |
| " firmware update.") |
| if not self.is_firmware_updated(host): |
| raise error.TestFail("Firmware on DUT mismatch with OS bundled" |
| " firmware after update.") |
| |
| def run_once(self, host): |
| """Main control of test steps: |
| |
| 1. Pre-update validation, ensure the DUT is in good state before actual |
| test to reduce flakiness. |
| 2. Firmware update, update os bundled firmware in RW portion. |
| 3. Post-update validation, test if the DUT is still in good state after |
| receive firmware update. |
| """ |
| self.pre_update_validation(host) |
| # Need to wait for machine fully ready for firmware update to reduce |
| # flakiness. |
| time.sleep(60) |
| if self.is_firmware_updated(host): |
| raise error.TestNAError("Firmware version on the DUT is already" |
| " up-to-date.") |
| self.update_os_bundled_firmware(host) |
| self.post_update_validation(host) |