# Copyright (c) 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.

# DESCRIPTION :
# This factory test checks image version in lsb-release. If the version doesn't
# match what's provided in the test argument, flash netboot firmware if it is
# provided.

from distutils import version
import logging
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
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.umpire.client import get_update
from cros.factory.umpire.client import umpire_server_proxy
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import debug_utils


_TEST_TITLE = i18n_test_ui.MakeI18nLabel('Check Image Version')

_CSS = """
.start-font-size {
  font-size: 2em;
}
"""

# Messages for tasks
_MSG_VERSION_MISMATCH = i18n_test_ui.MakeI18nLabelWithClass(
    'Factory 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_NETBOOT = i18n_test_ui.MakeI18nLabel(
    'Factory 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')

_LSB_RELEASE_PATH = '/etc/lsb-release'

_SHOPFLOOR_TIMEOUT_SECS = 10
_RETRY_INTERVAL_SECS = 3


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):
    if self._test.args.umpire:
      shopfloor_proxy = shopfloor.get_instance(
          detect=True, timeout=_SHOPFLOOR_TIMEOUT_SECS)
      netboot_firmware = get_update.GetUpdateForNetbootFirmware(shopfloor_proxy)
      if netboot_firmware:
        with open(flash_netboot.DEFAULT_NETBOOT_FIRMWARE_PATH, 'wb') as f:
          f.write(netboot_firmware)

    firmware_path = (self._test.args.netboot_fw or
                     flash_netboot.DEFAULT_NETBOOT_FIRMWARE_PATH)
    self._test.template.SetState(_MSG_REIMAGING)
    try:
      if self.dut.link.IsLocal():
        self.dut.CheckCall(
            ['/usr/local/factory/bin/flash_netboot',
             '-y', '-i', firmware_path, '--no-reboot'], log=True)
      else:
        with self.dut.temp.TempFile() as temp_file:
          self.dut.link.Push(firmware_path, temp_file)
          factory_par = deploy_utils.FactoryPythonArchive(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:  # pylint: disable=bare-except
      self._test.template.SetState(_MSG_FLASH_ERROR)

  def CheckImageFromUmpire(self):
    factory.console.info('Connecting to Umpire server...')
    shopfloor_client = None
    while True:
      try:
        shopfloor_client = shopfloor.get_instance(
            detect=True, timeout=_SHOPFLOOR_TIMEOUT_SECS)
        need_update = get_update.NeedImageUpdate(shopfloor_client)
        if need_update:
          logging.info('Umpire decide to update this DUT')
        else:
          logging.info('Umpire decide not to update this DUT')
        return need_update
      except umpire_server_proxy.UmpireServerProxyException:
        exception_string = debug_utils.FormatExceptionOnly()
        logging.info('Unable to sync with shopfloor server: %s',
                     exception_string)
      time.sleep(_RETRY_INTERVAL_SECS)

  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):
    need_update = (self.CheckImageFromUmpire if self._test.args.umpire else
                   self.CheckImageVersion)
    if need_update():
      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 factory or release image version. If umpire is set, '
          ' this args will be neglected.', default=None, optional=True),
      Arg('loose_version', bool, 'Allow any version number representation.',
          default=False),
      Arg('netboot_fw', str, 'The path to netboot firmware image.',
          default=None, optional=True),
      Arg('reimage', bool, 'True to re-image when image version mismatch.',
          default=True, optional=True),
      Arg('require_space', bool,
          'True to require a space key press before reimaging.',
          default=True, optional=True),
      Arg('check_release_image', bool,
          'True to check release image instead of factory image.',
          default=False, optional=True),
      Arg('umpire', bool, 'True to check image update from Umpire 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)
    self.template.SetTitle(_TEST_TITLE)

  def runTest(self):
    factory_task.FactoryTaskManager(self.ui, self._task_list).Run()
