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

"""Module containing methods and classes to interact with a devserver instance.
"""

import logging
import multiprocessing
import os
import psutil
import re
import sys
import tempfile
import time
import urllib2

import constants
from chromite.lib import cros_build_lib

# Wait up to 15 minutes for the dev server to start. It can take a while to
# start when generating payloads in parallel.
DEV_SERVER_TIMEOUT = 900
CHECK_HEALTH_URL = 'http://127.0.0.1:8080/check_health'
KILL_TIMEOUT = 10


def GetIPAddress(device='eth0'):
  """Returns the IP Address for a given device using ifconfig.

  socket.gethostname() is insufficient for machines where the host files are
  not set up "correctly."  Since some of our builders may have this issue,
  this method gives you a generic way to get the address so you are reachable
  either via a VM or remote machine on the same network.
  """
  result = cros_build_lib.RunCommandCaptureOutput(
      ['/sbin/ifconfig', device], print_cmd=False)
  match = re.search('.*inet addr:(\d+\.\d+\.\d+\.\d+).*', result.output)
  if match:
    return match.group(1)
  cros_build_lib.Warning('Failed to find ip address in %r', result.output)
  return None


def GenerateUpdateId(target, src, key, for_vm):
  """Returns a simple representation id of target and src paths."""
  update_id = target
  if src: update_id = '->'.join([src, update_id])
  if key: update_id = '+'.join([update_id, key])
  if not for_vm: update_id = '+'.join([update_id, 'patched_kernel'])
  return update_id


class DevServerException(Exception):
  """Thrown when the devserver fails to start up correctly."""


class DevServerWrapper(multiprocessing.Process):
  """A Simple wrapper around a dev server instance."""

  def __init__(self, test_root=None):
    super(DevServerWrapper, self).__init__()
    self.test_root = test_root or DevServerWrapper.MkChrootTemp(is_dir=True)
    self._log_filename = os.path.join(self.test_root, 'dev_server.log')
    self._pid_file = DevServerWrapper.MkChrootTemp(is_dir=False)
    self._pid = None

  # Chroot helper methods. Since we call a script into the chroot with paths
  # created outside the chroot, translation back and forth is needed. These
  # methods all assume the default chroot dir.

  @staticmethod
  def MkChrootTemp(is_dir):
    """Returns a temp(dir if is_dir, file otherwise) in the chroot."""
    chroot_tmp = os.path.join(constants.SOURCE_ROOT, 'chroot', 'tmp')
    if is_dir:
      return tempfile.mkdtemp(prefix='devserver_wrapper', dir=chroot_tmp)
    else:
      return tempfile.NamedTemporaryFile(prefix='devserver_wrapper',
                                         dir=chroot_tmp, delete=False).name

  @staticmethod
  def ToChrootPath(path):
    """Converts the path outside the chroot to one that can be used inside."""
    path = os.path.abspath(path)
    if '/chroot/' not in path:
      raise ValueError('Path %s is not a path that points inside the chroot' %
                       path)

    return '/' + path.partition('/chroot/')[2]

  def _WaitUntilStarted(self):
    """Wait until the devserver has started."""
    current_time = time.time()
    deadline = current_time + DEV_SERVER_TIMEOUT
    while current_time <= deadline:
      try:
        urllib2.urlopen(CHECK_HEALTH_URL, timeout=0.05)
        return
      except IOError:
        # urlopen errors will throw a subclass of IOError if we can't connect.
        pass
      finally:
        # Let's not churn needlessly in this loop as the devserver starts up.
        time.sleep(1)

      current_time = time.time()
    else:
      self.terminate()
      raise DevServerException('Devserver did not start')

  def run(self):
    """Kicks off devserver in a separate process and waits for it to finish."""
    cmd = ['start_devserver',
           '--pidfile', DevServerWrapper.ToChrootPath(self._pid_file),
           '--logfile', DevServerWrapper.ToChrootPath(self._log_filename)]
    return_obj = cros_build_lib.SudoRunCommand(
        cmd, enter_chroot=True, debug_level=logging.DEBUG,
        cwd=constants.SOURCE_ROOT, error_code_ok=True,
        redirect_stdout=True, combine_stdout_stderr=True)
    if return_obj.returncode != 0:
      logging.error('Devserver terminated unexpectedly!')
      logging.error(return_obj.output)

  def Start(self):
    """Starts a background devserver and waits for it to start.

    Starts a background devserver and waits for it to start. Will only return
    once devserver has started and running pid has been read.
    """
    self.start()
    self._WaitUntilStarted()
    # Pid file was passed into the chroot.
    with open(self._pid_file, 'r') as f:
      self._pid = int(f.read())

  def Stop(self):
    """Kills the devserver instance with SIGTERM and SIGKILL if SIGTERM fails"""
    if not self._pid:
      logging.error('No devserver running.')
      return

    logging.debug('Stopping devserver instance with pid %s', self._pid)
    process = psutil.Process(self._pid)
    if process.is_running():
      cros_build_lib.SudoRunCommand(['kill', str(self._pid)])
    else:
      logging.error('Devserver not running!')
      return

    try:
      process.wait(KILL_TIMEOUT)
    except psutil.error.TimeoutExpired:
      logging.warning('Devserver is unstoppable. Killing with SIGKILL')
      cros_build_lib.SudoRunCommand(['kill', '-9', str(self._pid)])

  def PrintLog(self):
    """Print devserver output to stdout."""
    print '--- Start output from %s ---' % self._log_filename
    # Open in update mode in case the child process hasn't opened the file yet.
    with open(self._log_filename) as log:
      sys.stdout.writelines(log)

    print '--- End output from %s ---' % self._log_filename

  @classmethod
  def GetDevServerURL(cls, port=None, sub_dir=None):
    """Returns the dev server url for a given port and sub directory."""
    if not port: port = 8080
    url = 'http://%(ip)s:%(port)s' % {'ip': GetIPAddress(), 'port': str(port)}
    if sub_dir:
      url += '/' + sub_dir

    return url

  @classmethod
  def WipePayloadCache(cls):
    """Cleans up devserver cache of payloads."""
    cros_build_lib.Info('Cleaning up previously generated payloads.')
    cmd = ['start_devserver', '--clear_cache', '--exit']
    cros_build_lib.SudoRunCommand(
        cmd, enter_chroot=True, print_cmd=False, combine_stdout_stderr=True,
        redirect_stdout=True, redirect_stderr=True, cwd=constants.SOURCE_ROOT)
