blob: 08906138bc5dd0e900dab839688b28f03e398fb3 [file] [log] [blame]
# Copyright 2013 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.
"""Check release or test OS image version on internal storage.
Description
-----------
This test checks if Chrome OS test image or release image version in
'/etc/lsb-release' are greater than or equal to the value of argument
``min_version``. If the version is too old and argument ``reimage`` is set to
True, reflash either local netboot firmware or remote netboot firmware from
factory server (e.g., Mini-Omaha or Umpire). After that, the DUT will reboot
into netboot firmware and start network image installation process to reimage.
Test Procedure
--------------
1. This test will first check if test image (when ``check_release_image`` is
False) or release image (when ``check_release_image`` is True) version >=
``min_version``. If so, this test will pass.
2. If ``reimage`` is set to False, this test will fail.
3. If ``require_space`` is set to True, this test will wait for the user presses
spacebar.
4. If ``download_from_server`` is set to True, this test will try to download
netboot firmware from factory server to the path indicated by argument
``netboot_fw``. If there is no available netboot firmware on factory server,
this test will fail.
5. Main firmware will be flashed with the firmware image in path ``netboot_fw``.
6. The DUT will then reboot into netboot firmware and start network image
installation process to reimage.
Dependency
----------
- If argument ``reimage`` is set to True, factory server must be set up and be
ready for network image installation.
- If argument ``download_from_server`` is set to True, netboot firmware must be
available on factory server. If ``download_from_server`` is set to False,
netboot firmware must be prepared in the path that argument ``netboot_fw``
indicated.
Examples
--------
To check test image version is greater than or equal to 9876.5.4::
OperatorTest(pytest_name='check_image_version',
dargs=dict(min_version='9876.5.4', reimage=False))
Reimage if release image version is older than 9876.5.4 by flashing local
netboot firmware, which is located in '/usr/local/factory/board/image.net.bin',
and make pressing spacebar not needed::
OperatorTest(pytest_name='check_image_version',
dargs=dict(check_release_image=True, min_version='9876.5.4',
require_space=False))
Reimage if test image version is greater than or equal to 9876.5.2012_12_21_2359
(loose format version) by flashing netboot firmware image on factory server::
OperatorTest(pytest_name='check_image_version',
dargs=dict(min_version='9876.5.2012_12_21_2359',
loose_version=True, download_from_server=True))
"""
from distutils import version
import logging
import shutil
import time
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test.event_log import Log
from cros.factory.test import factory_task
from cros.factory.test.i18n import test_ui as i18n_test_ui
from cros.factory.test import shopfloor
from cros.factory.test import test_ui
from cros.factory.test import ui_templates
from cros.factory.test.utils import deploy_utils
from cros.factory.tools import flash_netboot
from cros.factory.utils.arg_utils import Arg
_CSS = """
.start-font-size {
font-size: 2em;
}
"""
# Messages for tasks
_MSG_VERSION_MISMATCH = i18n_test_ui.MakeI18nLabelWithClass(
'Image version is incorrect. Please re-image this device.',
'start-font-size test-error')
_MSG_NETWORK = i18n_test_ui.MakeI18nLabel('Please connect to ethernet.')
_MSG_NO_FIRMWARE_ON_SERVER = i18n_test_ui.MakeI18nLabel(
'Netboot firmware not available on factory server.')
_MSG_NETBOOT = i18n_test_ui.MakeI18nLabel(
'Image version is incorrect. Press space to re-image.')
_MSG_REIMAGING = i18n_test_ui.MakeI18nLabel('Flashing netboot firmware...')
_MSG_FLASH_ERROR = i18n_test_ui.MakeI18nLabelWithClass(
'Error flashing netboot firmware!', 'start-font-size test-error')
class ImageCheckTask(factory_task.FactoryTask):
def __init__(self, test):
super(ImageCheckTask, self).__init__()
self._test = test
self.dut = test.dut
def CheckNetwork(self):
while not self.dut.status.eth_on:
time.sleep(0.5)
self._test.template.SetState(_MSG_NETWORK)
def PromptReimage(self):
self._test.template.SetState(_MSG_NETBOOT)
self._test.ui.BindKey(test_ui.SPACE_KEY, self.Reimage)
def Reimage(self):
# TODO(b/64881268): Run cros_payload to update release image directly.
if self._test.args.download_from_server:
payload, unused_components, downloader = (
shopfloor.GetUpdateFromCROSPayload(
'netboot_firmware',
proxy=shopfloor.get_instance()))
del unused_components
if not payload:
self._test.template.SetState(_MSG_NO_FIRMWARE_ON_SERVER)
return
with downloader() as res_path:
shutil.move(res_path, self._test.args.netboot_fw)
self._test.template.SetState(_MSG_REIMAGING)
try:
with self.dut.temp.TempFile() as temp_file:
self.dut.link.Push(self._test.args.netboot_fw, temp_file)
factory_par = deploy_utils.CreateFactoryTools(self.dut)
factory_par.CheckCall(
['flash_netboot', '-y', '-i', temp_file, '--no-reboot'], log=True)
self.dut.CheckCall(['reboot'], log=True)
self.Fail('Incorrect image version, DUT is rebooting to reimage.')
except Exception:
self._test.template.SetState(_MSG_FLASH_ERROR)
def CheckImageVersion(self):
if self._test.args.check_release_image:
ver = self.dut.info.release_image_version
else:
ver = self.dut.info.factory_image_version
Log('image_version', version=ver)
version_format = (version.LooseVersion if self._test.args.loose_version else
version.StrictVersion)
logging.info('Using version format: %r', version_format.__name__)
logging.info('current version: %r', ver)
logging.info('expected version: %r', self._test.args.min_version)
return version_format(ver) < version_format(self._test.args.min_version)
def Run(self):
if self.CheckImageVersion():
if self._test.args.reimage:
self.CheckNetwork()
if self._test.args.require_space:
self.PromptReimage()
else:
self.Reimage()
else:
self._test.template.SetState(_MSG_VERSION_MISMATCH)
return
self.Pass()
class CheckImageVersionTest(unittest.TestCase):
ARGS = [
Arg('min_version', str, 'Minimum allowed test or release image version.'),
Arg('loose_version', bool, 'Allow any version number representation.',
default=False),
Arg('netboot_fw', str, 'The path to netboot firmware image.',
default=flash_netboot.DEFAULT_NETBOOT_FIRMWARE_PATH),
Arg('reimage', bool, 'True to re-image when image version mismatch.',
default=True),
Arg('require_space', bool,
'True to require a space key press before reimaging.', default=True),
Arg('check_release_image', bool,
'True to check release image instead of test image.', default=False),
Arg('download_from_server', bool,
'True to download netboot firmware image from factory server.',
default=False)]
def setUp(self):
self.dut = device_utils.CreateDUTInterface()
self._task_list = [ImageCheckTask(self)]
self.ui = test_ui.UI()
self.template = ui_templates.OneSection(self.ui)
self.ui.AppendCSS(_CSS)
def runTest(self):
factory_task.FactoryTaskManager(self.ui, self._task_list).Run()