# Copyright 2012 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.

"""Connect to factory server to find software updates and upload logs.

Description
-----------
This test will create connections from DUT to Chrome OS factory server and
invoke remote procedure calls for syncing data and programs.

This test will sync following items:

1. If ``sync_time`` is enabled (default True), sync system time from server.
2. If ``sync_event_logs`` is enabled (default True), sync the ``event_log`` YAML
   event logs to factory server.
3. If ``flush_testlog`` is enabled (default False), flush TestLog to factory
   server (which should have Instalog node running).
4. If ``upload_report`` is enabled (default False), upload a ``Gooftool`` style
   report collecting system information and manufacturing logs to server.
5. If ``update_toolkit`` is enabled (default True), compare the factory software
   (toolkit) installed on DUT with the active version on server, and update
   if needed.
6. If ``upload_reg_codes`` is enabled (default False), upload the registration
   codes to server using ``UploadCSVEntry`` API, and have the data stored in
   ``registration_code_log.csv`` file on server. If the reg codes must be sent
   back to partner's shopfloor backend, please use shopfloor_service pytest
   and ActivateRegCode API instead.

Additionally, if argument ``server_url`` is specified, this test will update the
stored 'default factory server URL' so all following tests connecting to factory
server via ``server_proxy.GetServerProxy()`` will use the new URL.

``server_url`` supports few different input:

- If a string is given, that is interpreted as simple URL. For example,
  ``"http://10.3.0.11:8080/"``.
- If a mapping (dict) is given, take key as network IP/CIDR and value as URL.
  For example, ``{"10.3.0.0/24": "http://10.3.0.11:8080"}``

Test Procedure
--------------
Basically no user interaction required unless a toolkit update is found.

- Make sure network is connected.
- Start the test and it will try to reach factory server and sync time and logs.
- If `update_toolkit` is True, compare installed toolkit with server's active
  version.
- If a new version is found, a message like 'A software update is available.'
  will be displayed on screen. Operator can follow the instruction (usually
  just press space) to start downloading and installing new software.

Dependency
----------
Nothing special.
This test uses only server components in Chrome OS Factory Software.

Examples
--------
To connect to default server and sync time, event logs, and update software,
add this in test list::

  {
    "pytest_name": "sync_factory_server"
  }

To only sync time and logs, and never update software (useful for stations)::

  {
    "pytest_name": "sync_factory_server",
    "args": {
      "update_toolkit": false
    }
  }

To sync time and logs, and then upload a report::

  {
    "pytest_name": "sync_factory_server",
    "args": {
      "upload_report": true
    }
  }

To override default factory server URL for all tests, change the
``default_factory_server_url`` in test list constants::

  {
    "constants": {
      "default_factory_server_url": "http://192.168.3.11:8080"
    }
  }

It is also possible to override and create one test item using different factory
server URL, and all tests after that::

  {
    "pytest_name": "sync_factory_server",
    "args": {
      "server_url": "http://192.168.3.11:8080"
    }
  }

To implement "station specific factory server" in JSON test lists, extend
``SyncFactoryServer`` from ``generic_common.test_list.json`` as::

  { "inherit": "SyncFactoryServer",
    "args": {
      "server_url": "eval! locals.factory_server_url"
    }
  }

And then in each station (or stage), override URL in locals::

  {"SMT": {"locals": {"factory_server_url": "http://192.168.3.11:8080" }}},
  {"FAT": {"locals": {"factory_server_url": "http://10.3.0.11:8080" }}},
  {"RunIn": {"locals": {"factory_server_url": "http://10.1.2.10:7000" }}},
  {"FFT": {"locals": {"factory_server_url": "http://10.3.0.11:8080" }}},
  {"GRT": {"locals": {"factory_server_url": "http://172.30.1.2:8081" }}},

To implement "auto-detect factory server by received DHCP IP address", specify a
mapping object with key set to "IP/CIDR" and value set to server URL::

  {
    "constants": {
      "default_factory_server_url": {
        "192.168.3.0/24": "http://192.168.3.11:8080",
        "10.3.0.0/24": "http://10.3.0.11:8080",
        "10.1.0.0/16": "http://10.1.2.10:8080"
      }
    }
  }
"""

import logging
import threading
import time

import factory_common  # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.gooftool import commands
from cros.factory.goofy import updater
from cros.factory.test import device_data
from cros.factory.test.i18n import _
from cros.factory.test.rules import registration_codes
from cros.factory.test import server_proxy
from cros.factory.test import session
from cros.factory.test import state
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.test.utils import time_utils
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import debug_utils
from cros.factory.utils import log_utils
from cros.factory.utils import sync_utils


ID_TEXT_INPUT_URL = 'text_input_url'
ID_BUTTON_EDIT_URL = 'button_edit_url'

EVENT_SET_URL = 'event_set_url'
EVENT_CANCEL_SET_URL = 'event_cancel_set_url'
EVENT_DO_SET_URL = 'event_do_set_url'


class Report(object):
  """A structure for reports uploaded to factory server."""

  def __init__(self, serial_number, blob, station):
    self.serial_number = serial_number
    self.blob = blob
    self.station = station


class SyncFactoryServer(test_case.TestCase):
  ARGS = [
      Arg('first_retry_secs', int,
          'Time to wait after the first attempt; this will increase '
          'exponentially up to retry_secs.  This is useful because '
          'sometimes the network may not be available by the time the '
          'tests starts, but a full 10-second wait is unnecessary.',
          1),
      Arg('retry_secs', int, 'Maximum time to wait between retries.', 10),
      Arg('timeout_secs', int, 'Timeout for XML/RPC operations.', 10),
      Arg('update_toolkit', bool, 'Whether to check factory update.',
          default=True),
      Arg('update_without_prompt', bool, 'Update without prompting when an '
          'update is available.', default=False),
      Arg('sync_time', bool, 'Sync system time from factory server.',
          default=True),
      Arg('sync_event_logs', bool, 'Sync event logs to factory server.',
          default=True),
      Arg('flush_testlog', bool, 'Flush test logs to factory server.',
          # TODO(hungte) Change flush_testlog to default True when Umpire is
          # officially deployed.
          default=False),
      Arg('upload_reg_codes', bool, 'Upload registration codes to server.',
          default=False),
      Arg('upload_report', bool, 'Upload a factory report to factory server.',
          default=False),
      Arg('report_stage', str, 'Stage of report to upload.', default=None),
      Arg('report_serial_number_name', str,
          'Name of serial number to use for report file name to use.',
          default=None),
      Arg('server_url', (basestring, dict),
          'Set and keep new factory server URL.',
          default=None),
  ]

  def setUp(self):
    self.server = None
    self.do_setup_url = threading.Event()
    self.allow_edit_url = True
    self.event_url_set = threading.Event()
    self.goofy = state.GetInstance()
    self.report = Report(None, None, self.args.report_stage)
    self.dut = device_utils.CreateDUTInterface()
    self.station = device_utils.CreateStationInterface()

  @staticmethod
  def CreateButton(node_id, message, on_click):
    return [
        '<button type="button" id="%s" onclick=%r>' % (node_id, on_click),
        message, '</button>'
    ]

  def CreateChangeURLButton(self):
    return self.CreateButton(
        ID_BUTTON_EDIT_URL,
        _('Change URL'),
        'this.disabled = true; window.test.sendTestEvent("%s");' %
        EVENT_DO_SET_URL)

  def OnButtonSetClicked(self, event):
    self.ChangeServerURL(event.data)
    self.do_setup_url.clear()
    self.event_url_set.set()

  def OnButtonCancelClicked(self, event):
    del event  # Unused.
    self.do_setup_url.clear()
    self.event_url_set.set()

  def OnButtonEditClicked(self, event):
    del event  # Unused.
    self.do_setup_url.set()
    self.ui.SetHTML(
        _('Please wait few seconds to edit...'), id=ID_BUTTON_EDIT_URL)

  def EditServerURL(self):
    current_url = server_proxy.GetServerURL() or ''

    if current_url:
      prompt = []
    else:
      prompt = [
          '<span class="warning_label">',
          _('No factor server URL configured.'),
          '</span><span class="warning_message">',
          # TODO(hungte) Add message when we can't connect to factory server.
          _('For debugging or development, '
            'enter engineering mode to start individual tests.'),
          '</span>'
      ]

    self.ui.SetState([
        prompt,
        _('Change server URL: '),
        '<input type="text" id="%s" value="%s"/>' % (ID_TEXT_INPUT_URL,
                                                     current_url), '<span>',
        self.CreateButton('btnSet',
                          _('Set'), 'window.test.sendTestEvent("%s", '
                          'document.getElementById("%s").value)' %
                          (EVENT_SET_URL, ID_TEXT_INPUT_URL)),
        self.CreateButton(
            'btnCancel',
            _('Cancel'),
            'window.test.sendTestEvent("%s")' % EVENT_CANCEL_SET_URL), '</span>'
    ])

  def DetectServerURL(self):
    expected_networks = self.args.server_url.keys()
    label_connect = _('Please connect to network...')
    label_status = _('Expected network: {networks}', networks=expected_networks)

    while True:
      new_url = self.FindServerURL(self.args.server_url)
      if new_url:
        break
      # Collect current networks. The output format is DEV STATUS NETWORK.
      output = self.station.CallOutput(['ip', '-f', 'inet', '-br', 'addr'])
      networks = [entry.split()[2] for entry in output.splitlines()
                  if ' UP ' in entry]
      self.ui.SetState([
          label_connect, label_status,
          _('Current networks: {networks}', networks=networks)
      ])
      self.Sleep(0.5)

    self.ChangeServerURL(new_url)
    self.do_setup_url.clear()

  def Ping(self):
    if self.do_setup_url.is_set():
      self.event_url_set.clear()
      self.EditServerURL()
      sync_utils.EventWait(self.event_url_set)

    self.ui.SetState(
        [_('Trying to reach server...'),
         self.CreateChangeURLButton()])
    self.server = server_proxy.GetServerProxy(timeout=self.args.timeout_secs)

    if self.do_setup_url.is_set():
      raise Exception('Edit URL clicked.')

    self.ui.SetState(
        [_('Trying to check server protocol...'),
         self.CreateChangeURLButton()])
    self.server.Ping()
    self.allow_edit_url = False

  def ChangeServerURL(self, new_server_url):
    server_url = server_proxy.GetServerURL() or ''

    if new_server_url and new_server_url != server_url:
      server_proxy.SetServerURL(new_server_url.rstrip('/'))
      # Read again because server_proxy module may normalize it.
      new_server_url = server_proxy.GetServerURL()
      session.console.info(
          'Factory server URL has been changed from [%s] to [%s].',
          server_url, new_server_url)
      server_url = new_server_url

    self.ui.SetInstruction(_('Server URL: {server_url}', server_url=server_url))
    if not server_url:
      self.do_setup_url.set()

  def FlushTestlog(self):
    # TODO(hungte) goofy.FlushTestlog should reload factory_server_url.
    result = False
    while not result:
      result, progress = self.goofy.FlushTestlog(timeout=2)
      self.ui.SetState(
          _('Flush Test Log: Progress = <br>{progress}', progress=progress))

  def CreateReport(self):
    self.ui.SetState(_('Collecting report data...'))
    self.report.blob = commands.CreateReportArchiveBlob()
    self.ui.SetState(_('Getting serial number...'))
    self.report.serial_number = device_data.GetSerialNumber(
        self.args.report_serial_number_name or
        device_data.NAME_SERIAL_NUMBER)

  def UploadReport(self):
    self.server.UploadReport(
        self.report.serial_number, self.report.blob, None, self.report.station)

  def UploadRegCodes(self):
    """Uploads registration codes to factory server.

    The registration codes should be sent in format from http://goto/nkjyr.
    """
    hwid = device_data.GetDeviceData(
        device_data.KEY_HWID, self.dut.CallOutput('crossystem hwid'))
    if not hwid:
      raise Exception('Need HWID before uploading registration codes.')

    board = hwid.partition(' ')[0]
    ubind = device_data.GetDeviceData(device_data.KEY_VPD_USER_REGCODE)
    gbind = device_data.GetDeviceData(device_data.KEY_VPD_GROUP_REGCODE)
    for label, value in ('user', ubind), ('group', gbind):
      if not value:
        raise Exception('Missing %s registration codes in device data (%r).' %
                        (label, value))

    registration_codes.CheckRegistrationCode(ubind)
    registration_codes.CheckRegistrationCode(gbind)
    timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())
    entry = [board, ubind, gbind, timestamp, hwid]
    self.server.UploadCSVEntry('registration_code_log', entry)

  def UpdateToolkit(self):
    unused_toolkit_version, has_update = updater.CheckForUpdate(
        self.args.timeout_secs)
    if not has_update:
      return

    # Update necessary. Note that updateFactory() will kill this test.
    if not self.args.update_without_prompt:
      # Display message and require update.
      self.ui.SetState(
          _('A software update is available. Press SPACE to update.'))
      self.ui.WaitKeysOnce(test_ui.SPACE_KEY)

    self.ui.CallJSFunction('window.test.updateFactory')

    # Let this test sleep forever, and wait for either the SPACE event, or the
    # factory update to complete. Note that we want the test to neither pass or
    # fail, so we won't be accidentally running other tests when the
    # updateFactory is running.
    self.WaitTaskEnd()

  @staticmethod
  def IsDynamicServer(url_spec):
    """Returns if the url_spec is something to be dynamically configured."""
    return isinstance(url_spec, dict) and url_spec

  def FindServerURL(self, url_spec):
    """Try to return a single normalized URL from given specification.

    It is very often that partner may want to deploy multiple servers with
    different IP, and expect DUT to connect right server according to the DHCP
    IP it has received.

    This function tries to parse argument url_spec and find a "best match
    URL" for it.

    Args:
      url_spec: a simple string as URL or a mapping from IP/CIDR to URL.

    Returns:
      A single URL string that best matches given spec.
    """
    if not self.IsDynamicServer(url_spec):
      return url_spec

    # Sort by CIDR so smaller network matches first.
    networks = sorted(
        url_spec, reverse=True, key=lambda k: int(k.partition('/')[-1] or 0))
    for ip_cidr in networks:
      # The command returned zero even if no interfaces match.
      if self.station.CallOutput(['ip', 'addr', 'show', 'to', ip_cidr]):
        return url_spec[ip_cidr]

    return url_spec.get('default', '')

  def runTest(self):
    self.ui.SetInstruction(_('Preparing...'))
    retry_secs = self.args.first_retry_secs

    self.event_loop.AddEventHandler(EVENT_SET_URL, self.OnButtonSetClicked)
    self.event_loop.AddEventHandler(EVENT_CANCEL_SET_URL,
                                    self.OnButtonCancelClicked)
    self.event_loop.AddEventHandler(EVENT_DO_SET_URL, self.OnButtonEditClicked)

    # Setup tasks to perform.
    tasks = [(_('Ping'), self.Ping)]

    if self.IsDynamicServer(self.args.server_url):
      # Server URL must be confirmed before Ping.
      tasks = [(_('Detect Server URL'), self.DetectServerURL)] + tasks

    if self.args.sync_time:
      def SyncTime():
        if not time_utils.SyncTimeWithFactoryServer():
          raise Exception('Failed to sync time with factory server')
      tasks += [(_('Sync time'), SyncTime)]

    if self.args.sync_event_logs:
      tasks += [(_('Flush Event Logs'), self.goofy.FlushEventLogs)]

    if self.args.flush_testlog:
      tasks += [(_('Flush Test Log'), self.FlushTestlog)]

    if self.args.upload_report:
      tasks += [(_('Create Report'), self.CreateReport)]
      tasks += [(_('Upload report'), self.UploadReport)]

    if self.args.upload_reg_codes:
      tasks += [(_('Upload Reg Codes'), self.UploadRegCodes)]

    if self.args.update_toolkit:
      tasks += [(_('Update Toolkit'), self.UpdateToolkit)]
    else:
      session.console.info('Toolkit update is disabled.')

    # Setup new server URL
    server_proxy.ValidateServerConfig()
    self.ChangeServerURL(self.FindServerURL(self.args.server_url))

    # It's very often that a DUT under FA is left without network connected for
    # hours to days, so we should not log (which will increase TestLog events)
    # if the exception string is not changed.
    logger = log_utils.NoisyLogger(
        lambda fault, prompt: logging.exception(prompt, fault))

    self.ui.DrawProgressBar(len(tasks))

    for label, task in tasks:
      while True:
        try:
          self.ui.SetState(_('Running task: {label}', label=label))
          task()
          self.ui.SetState([
              '<span style="color: green">',
              _('Server Task Finished: {label}', label=label), '</span>'
          ])
          self.Sleep(0.5)
          break
        except server_proxy.Fault as f:
          message = f.faultString
          logger.Log(message, 'Server fault with message: %s')
        except Exception:
          message = debug_utils.FormatExceptionOnly()
          logger.Log(message, 'Unable to sync with server: %s')

        msg = lambda time_left, label_: _(
            'Task <b>{label}</b> failed, retry in {time_left} seconds...',
            time_left=time_left,
            label=label_)
        edit_url_button = (['<p>', self.CreateChangeURLButton(), '</p>']
                           if self.allow_edit_url else '')
        self.ui.SetState([
            '<span id="retry">',
            msg(retry_secs, label), '</span>', edit_url_button,
            '<p><textarea rows=25 cols=90 readonly class="sync-detail">',
            test_ui.Escape(message, False), '</textarea>'
        ])

        try:
          # sync_utils.EventWait() may log timeout message every second, so we
          # disable logging.INFO temporarily.
          logging.disable(logging.INFO)
          for sec in xrange(retry_secs):
            if sync_utils.EventWait(self.do_setup_url, timeout=1):
              break
            self.ui.SetHTML(msg(retry_secs - sec - 1, label), id='retry')
        finally:
          logging.disable(logging.NOTSET)
        retry_secs = min(2 * retry_secs, self.args.retry_secs)

      self.ui.AdvanceProgress()
