#!/usr/bin/python
#

# Copyright (C) 2010 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


"""Import/export daemon.

"""

# pylint: disable=C0103
# C0103: Invalid name import-export

import errno
import logging
import optparse
import os
import select
import signal
import subprocess
import sys
import time
import math

from ganeti import constants
from ganeti import cli
from ganeti import utils
from ganeti import errors
from ganeti import serializer
from ganeti import objects
from ganeti import impexpd
from ganeti import netutils


#: How many lines to keep in the status file
MAX_RECENT_OUTPUT_LINES = 20

#: Don't update status file more than once every 5 seconds (unless forced)
MIN_UPDATE_INTERVAL = 5.0

#: How long to wait for a connection to be established
DEFAULT_CONNECT_TIMEOUT = 60

#: Get dd(1) statistics every few seconds
DD_STATISTICS_INTERVAL = 5.0

#: Seconds for throughput calculation
DD_THROUGHPUT_INTERVAL = 60.0

#: Number of samples for throughput calculation
DD_THROUGHPUT_SAMPLES = int(math.ceil(float(DD_THROUGHPUT_INTERVAL) /
                                      DD_STATISTICS_INTERVAL))


# Global variable for options
options = None


def SetupLogging():
  """Configures the logging module.

  """
  formatter = logging.Formatter("%(asctime)s: %(message)s")

  stderr_handler = logging.StreamHandler()
  stderr_handler.setFormatter(formatter)
  stderr_handler.setLevel(logging.NOTSET)

  root_logger = logging.getLogger("")
  root_logger.addHandler(stderr_handler)

  if options.debug:
    root_logger.setLevel(logging.NOTSET)
  elif options.verbose:
    root_logger.setLevel(logging.INFO)
  else:
    root_logger.setLevel(logging.ERROR)

  # Create special logger for child process output
  child_logger = logging.Logger("child output")
  child_logger.addHandler(stderr_handler)
  child_logger.setLevel(logging.NOTSET)

  return child_logger


class StatusFile(object):
  """Status file manager.

  """
  def __init__(self, path):
    """Initializes class.

    """
    self._path = path
    self._data = objects.ImportExportStatus(ctime=time.time(),
                                            mtime=None,
                                            recent_output=[])

  def AddRecentOutput(self, line):
    """Adds a new line of recent output.

    """
    self._data.recent_output.append(line)

    # Remove old lines
    del self._data.recent_output[:-MAX_RECENT_OUTPUT_LINES]

  def SetListenPort(self, port):
    """Sets the port the daemon is listening on.

    @type port: int
    @param port: TCP/UDP port

    """
    assert isinstance(port, (int, long)) and 0 < port < (2 ** 16)
    self._data.listen_port = port

  def GetListenPort(self):
    """Returns the port the daemon is listening on.

    """
    return self._data.listen_port

  def SetConnected(self):
    """Sets the connected flag.

    """
    self._data.connected = True

  def GetConnected(self):
    """Determines whether the daemon is connected.

    """
    return self._data.connected

  def SetProgress(self, mbytes, throughput, percent, eta):
    """Sets how much data has been transferred so far.

    @type mbytes: number
    @param mbytes: Transferred amount of data in MiB.
    @type throughput: float
    @param throughput: MiB/second
    @type percent: number
    @param percent: Percent processed
    @type eta: number
    @param eta: Expected number of seconds until done

    """
    self._data.progress_mbytes = mbytes
    self._data.progress_throughput = throughput
    self._data.progress_percent = percent
    self._data.progress_eta = eta

  def SetExitStatus(self, exit_status, error_message):
    """Sets the exit status and an error message.

    """
    # Require error message when status isn't 0
    assert exit_status == 0 or error_message

    self._data.exit_status = exit_status
    self._data.error_message = error_message

  def ExitStatusIsSuccess(self):
    """Returns whether the exit status means "success".

    """
    return not bool(self._data.error_message)

  def Update(self, force):
    """Updates the status file.

    @type force: bool
    @param force: Write status file in any case, not only when minimum interval
                  is expired

    """
    if not (force or
            self._data.mtime is None or
            time.time() > (self._data.mtime + MIN_UPDATE_INTERVAL)):
      return

    logging.debug("Updating status file %s", self._path)

    self._data.mtime = time.time()
    utils.WriteFile(self._path,
                    data=serializer.DumpJson(self._data.ToDict()),
                    mode=0400)


def ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd,
                   dd_pid_read_fd, exp_size_read_fd, status_file, child_logger,
                   signal_notify, signal_handler, mode):
  """Handles the child processes' output.

  """
  assert not (signal_handler.signum - set([signal.SIGTERM, signal.SIGINT])), \
         "Other signals are not handled in this function"

  # Buffer size 0 is important, otherwise .read() with a specified length
  # might buffer data while poll(2) won't mark its file descriptor as
  # readable again.
  socat_stderr_read = os.fdopen(socat_stderr_read_fd, "r", 0)
  dd_stderr_read = os.fdopen(dd_stderr_read_fd, "r", 0)
  dd_pid_read = os.fdopen(dd_pid_read_fd, "r", 0)
  exp_size_read = os.fdopen(exp_size_read_fd, "r", 0)

  tp_samples = DD_THROUGHPUT_SAMPLES

  if options.exp_size == constants.IE_CUSTOM_SIZE:
    exp_size = None
  else:
    exp_size = options.exp_size

  child_io_proc = impexpd.ChildIOProcessor(options.debug, status_file,
                                           child_logger, tp_samples,
                                           exp_size)
  try:
    fdmap = {
      child.stderr.fileno():
        (child.stderr, child_io_proc.GetLineSplitter(impexpd.PROG_OTHER)),
      socat_stderr_read.fileno():
        (socat_stderr_read, child_io_proc.GetLineSplitter(impexpd.PROG_SOCAT)),
      dd_pid_read.fileno():
        (dd_pid_read, child_io_proc.GetLineSplitter(impexpd.PROG_DD_PID)),
      dd_stderr_read.fileno():
        (dd_stderr_read, child_io_proc.GetLineSplitter(impexpd.PROG_DD)),
      exp_size_read.fileno():
        (exp_size_read, child_io_proc.GetLineSplitter(impexpd.PROG_EXP_SIZE)),
      signal_notify.fileno(): (signal_notify, None),
      }

    poller = select.poll()
    for fd in fdmap:
      utils.SetNonblockFlag(fd, True)
      poller.register(fd, select.POLLIN)

    if options.connect_timeout and mode == constants.IEM_IMPORT:
      listen_timeout = utils.RunningTimeout(options.connect_timeout, True)
    else:
      listen_timeout = None

    exit_timeout = None
    dd_stats_timeout = None

    while True:
      # Break out of loop if only signal notify FD is left
      if len(fdmap) == 1 and signal_notify.fileno() in fdmap:
        break

      timeout = None

      if listen_timeout and not exit_timeout:
        assert mode == constants.IEM_IMPORT and options.connect_timeout
        if status_file.GetConnected():
          listen_timeout = None
        elif listen_timeout.Remaining() < 0:
          errmsg = ("Child process didn't establish connection in time"
                    " (%0.0fs), sending SIGTERM" % options.connect_timeout)
          logging.error(errmsg)
          status_file.AddRecentOutput(errmsg)
          status_file.Update(True)

          child.Kill(signal.SIGTERM)
          exit_timeout = \
            utils.RunningTimeout(constants.CHILD_LINGER_TIMEOUT, True)
          # Next block will calculate timeout
        else:
          # Not yet connected, check again in a second
          timeout = 1000

      if exit_timeout:
        timeout = exit_timeout.Remaining() * 1000
        if timeout < 0:
          logging.info("Child process didn't exit in time")
          break

      if (not dd_stats_timeout) or dd_stats_timeout.Remaining() < 0:
        notify_status = child_io_proc.NotifyDd()
        if notify_status:
          # Schedule next notification
          dd_stats_timeout = utils.RunningTimeout(DD_STATISTICS_INTERVAL, True)
        else:
          # Try again soon (dd isn't ready yet)
          dd_stats_timeout = utils.RunningTimeout(1.0, True)

      if dd_stats_timeout:
        dd_timeout = max(0, dd_stats_timeout.Remaining() * 1000)

        if timeout is None:
          timeout = dd_timeout
        else:
          timeout = min(timeout, dd_timeout)

      for fd, event in utils.RetryOnSignal(poller.poll, timeout):
        if event & (select.POLLIN | event & select.POLLPRI):
          (from_, to) = fdmap[fd]

          # Read up to 1 KB of data
          data = from_.read(1024)
          if data:
            if to:
              to.write(data)
            elif fd == signal_notify.fileno():
              # Signal handling
              if signal_handler.called:
                signal_handler.Clear()
                if exit_timeout:
                  logging.info("Child process still has about %0.2f seconds"
                               " to exit", exit_timeout.Remaining())
                else:
                  logging.info("Giving child process %0.2f seconds to exit",
                               constants.CHILD_LINGER_TIMEOUT)
                  exit_timeout = \
                    utils.RunningTimeout(constants.CHILD_LINGER_TIMEOUT, True)
          else:
            poller.unregister(fd)
            del fdmap[fd]

        elif event & (select.POLLNVAL | select.POLLHUP |
                      select.POLLERR):
          poller.unregister(fd)
          del fdmap[fd]

      child_io_proc.FlushAll()

    # If there was a timeout calculator, we were waiting for the child to
    # finish, e.g. due to a signal
    return not bool(exit_timeout)
  finally:
    child_io_proc.CloseAll()


def ParseOptions():
  """Parses the options passed to the program.

  @return: Arguments to program

  """
  global options # pylint: disable=W0603

  parser = optparse.OptionParser(usage=("%%prog <status-file> {%s|%s}" %
                                        (constants.IEM_IMPORT,
                                         constants.IEM_EXPORT)))
  parser.add_option(cli.DEBUG_OPT)
  parser.add_option(cli.VERBOSE_OPT)
  parser.add_option("--key", dest="key", action="store", type="string",
                    help="RSA key file")
  parser.add_option("--cert", dest="cert", action="store", type="string",
                    help="X509 certificate file")
  parser.add_option("--ca", dest="ca", action="store", type="string",
                    help="X509 CA file")
  parser.add_option("--bind", dest="bind", action="store", type="string",
                    help="Bind address")
  parser.add_option("--ipv4", dest="ipv4", action="store_true",
                    help="Use IPv4 only")
  parser.add_option("--ipv6", dest="ipv6", action="store_true",
                    help="Use IPv6 only")
  parser.add_option("--host", dest="host", action="store", type="string",
                    help="Remote hostname")
  parser.add_option("--port", dest="port", action="store", type="int",
                    help="Remote port")
  parser.add_option("--connect-retries", dest="connect_retries", action="store",
                    type="int", default=0,
                    help=("How many times the connection should be retried"
                          " (export only)"))
  parser.add_option("--connect-timeout", dest="connect_timeout", action="store",
                    type="int", default=DEFAULT_CONNECT_TIMEOUT,
                    help="Timeout for connection to be established (seconds)")
  parser.add_option("--compress", dest="compress", action="store",
                    type="string", help="Compression method",
                    default=constants.IEC_GZIP)
  parser.add_option("--expected-size", dest="exp_size", action="store",
                    type="string", default=None,
                    help="Expected import/export size (MiB)")
  parser.add_option("--magic", dest="magic", action="store",
                    type="string", default=None, help="Magic string")
  parser.add_option("--cmd-prefix", dest="cmd_prefix", action="store",
                    type="string", help="Command prefix")
  parser.add_option("--cmd-suffix", dest="cmd_suffix", action="store",
                    type="string", help="Command suffix")

  (options, args) = parser.parse_args()

  if len(args) != 2:
    # Won't return
    parser.error("Expected exactly two arguments")

  (status_file_path, mode) = args

  if mode not in (constants.IEM_IMPORT,
                  constants.IEM_EXPORT):
    # Won't return
    parser.error("Invalid mode: %s" % mode)

  # Normalize and check parameters
  if options.host is not None and not netutils.IPAddress.IsValid(options.host):
    try:
      options.host = netutils.Hostname.GetNormalizedName(options.host)
    except errors.OpPrereqError, err:
      parser.error("Invalid hostname '%s': %s" % (options.host, err))

  if options.port is not None:
    options.port = utils.ValidateServiceName(options.port)

  if (options.exp_size is not None and
      options.exp_size != constants.IE_CUSTOM_SIZE):
    try:
      options.exp_size = int(options.exp_size)
    except (ValueError, TypeError), err:
      # Won't return
      parser.error("Invalid value for --expected-size: %s (%s)" %
                   (options.exp_size, err))

  if not (options.magic is None or constants.IE_MAGIC_RE.match(options.magic)):
    parser.error("Magic must match regular expression %s" %
                 constants.IE_MAGIC_RE.pattern)

  if options.ipv4 and options.ipv6:
    parser.error("Can only use one of --ipv4 and --ipv6")

  return (status_file_path, mode)


# Return code signifying that no program was found
PROGRAM_NOT_FOUND_RCODE = 127


def _RunWithTimeout(cmd, timeout, silent=False):
  """Runs a command, killing it if a timeout was reached.

  Uses the alarm signal, not thread-safe. Waits regardless of whether the
  command exited early.

  @type timeout: number
  @param timeout: Timeout, in seconds
  @type silent: Boolean
  @param silent: Whether command output should be suppressed
  @rtype: tuple of (bool, int)
  @return: Whether the command timed out, and the return code

  """
  try:
    if silent:
      with open(os.devnull, 'wb') as null_fd:
        p = subprocess.Popen(cmd, stdout=null_fd, stderr=null_fd)
    else:
      p = subprocess.Popen(cmd)

  except OSError:
    return False, PROGRAM_NOT_FOUND_RCODE

  time.sleep(timeout)

  timed_out = False
  status = p.poll()
  if status is None:
    timed_out = True
    p.kill()

  return timed_out, p.wait()


CHECK_SWITCH = "-h"


def VerifyOptions():
  """Performs various runtime checks to make sure the options are valid.

  """
  if options.compress != constants.IEC_NONE:
    utility_name = constants.IEC_COMPRESSION_UTILITIES.get(options.compress,
                                                           options.compress)
    timed_out, rcode = \
      _RunWithTimeout([utility_name, CHECK_SWITCH], 2, silent=True)

    if timed_out:
      raise Exception("The invoked utility has timed out - the %s switch to"
                      " check for presence must be supported" % CHECK_SWITCH)

    if rcode != 0:
      raise Exception("Verification attempt of selected compression method %s"
                      " failed - check that %s is present and can be invoked"
                      " safely with the %s switch" %
                      (options.compress, utility_name, CHECK_SWITCH))


class ChildProcess(subprocess.Popen):
  def __init__(self, env, cmd, noclose_fds):
    """Initializes this class.

    """
    self._noclose_fds = noclose_fds

    # Not using close_fds because doing so would also close the socat stderr
    # pipe, which we still need.
    subprocess.Popen.__init__(self, cmd, env=env, shell=False, close_fds=False,
                              stderr=subprocess.PIPE, stdout=None, stdin=None,
                              preexec_fn=self._ChildPreexec)
    self._SetProcessGroup()

  def _ChildPreexec(self):
    """Called before child executable is execve'd.

    """
    # Move to separate process group. By sending a signal to its process group
    # we can kill the child process and all grandchildren.
    os.setpgid(0, 0)

    # Close almost all file descriptors
    utils.CloseFDs(noclose_fds=self._noclose_fds)

  def _SetProcessGroup(self):
    """Sets the child's process group.

    """
    assert self.pid, "Can't be called in child process"

    # Avoid race condition by setting child's process group (as good as
    # possible in Python) before sending signals to child. For an
    # explanation, see preexec function for child.
    try:
      os.setpgid(self.pid, self.pid)
    except EnvironmentError, err:
      # If the child process was faster we receive EPERM or EACCES
      if err.errno not in (errno.EPERM, errno.EACCES):
        raise

  def Kill(self, signum):
    """Sends signal to child process.

    """
    logging.info("Sending signal %s to child process", signum)
    utils.IgnoreProcessNotFound(os.killpg, self.pid, signum)

  def ForceQuit(self):
    """Ensure child process is no longer running.

    """
    # Final check if child process is still alive
    if utils.RetryOnSignal(self.poll) is None:
      logging.error("Child process still alive, sending SIGKILL")
      self.Kill(signal.SIGKILL)
      utils.RetryOnSignal(self.wait)


def main():
  """Main function.

  """
  # Option parsing
  (status_file_path, mode) = ParseOptions()

  # Configure logging
  child_logger = SetupLogging()

  status_file = StatusFile(status_file_path)
  try:
    try:
      # Option verification
      VerifyOptions()

      # Pipe to receive socat's stderr output
      (socat_stderr_read_fd, socat_stderr_write_fd) = os.pipe()

      # Pipe to receive dd's stderr output
      (dd_stderr_read_fd, dd_stderr_write_fd) = os.pipe()

      # Pipe to receive dd's PID
      (dd_pid_read_fd, dd_pid_write_fd) = os.pipe()

      # Pipe to receive size predicted by export script
      (exp_size_read_fd, exp_size_write_fd) = os.pipe()

      # Get child process command
      cmd_builder = impexpd.CommandBuilder(mode, options, socat_stderr_write_fd,
                                           dd_stderr_write_fd, dd_pid_write_fd)
      cmd = cmd_builder.GetCommand()

      # Prepare command environment
      cmd_env = os.environ.copy()

      if options.exp_size == constants.IE_CUSTOM_SIZE:
        cmd_env["EXP_SIZE_FD"] = str(exp_size_write_fd)

      logging.debug("Starting command %r", cmd)

      # Start child process
      child = ChildProcess(cmd_env, cmd,
                           [socat_stderr_write_fd, dd_stderr_write_fd,
                            dd_pid_write_fd, exp_size_write_fd])
      try:

        def _ForwardSignal(signum, _):
          """Forwards signals to child process.

          """
          child.Kill(signum)

        signal_wakeup = utils.SignalWakeupFd()
        try:
          # TODO: There is a race condition between starting the child and
          # handling the signals here. While there might be a way to work around
          # it by registering the handlers before starting the child and
          # deferring sent signals until the child is available, doing so can be
          # complicated.
          signal_handler = utils.SignalHandler([signal.SIGTERM, signal.SIGINT],
                                               handler_fn=_ForwardSignal,
                                               wakeup=signal_wakeup)
          try:
            # Close child's side
            utils.RetryOnSignal(os.close, socat_stderr_write_fd)
            utils.RetryOnSignal(os.close, dd_stderr_write_fd)
            utils.RetryOnSignal(os.close, dd_pid_write_fd)
            utils.RetryOnSignal(os.close, exp_size_write_fd)

            if ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd,
                              dd_pid_read_fd, exp_size_read_fd,
                              status_file, child_logger,
                              signal_wakeup, signal_handler, mode):
              # The child closed all its file descriptors and there was no
              # signal
              # TODO: Implement timeout instead of waiting indefinitely
              utils.RetryOnSignal(child.wait)
          finally:
            signal_handler.Reset()
        finally:
          signal_wakeup.Reset()
      finally:
        child.ForceQuit()

      if child.returncode == 0:
        errmsg = None
      elif child.returncode < 0:
        errmsg = "Exited due to signal %s" % (-child.returncode, )
      else:
        errmsg = "Exited with status %s" % (child.returncode, )

      status_file.SetExitStatus(child.returncode, errmsg)
    except Exception, err: # pylint: disable=W0703
      logging.exception("Unhandled error occurred")
      status_file.SetExitStatus(constants.EXIT_FAILURE,
                                "Unhandled error occurred: %s" % (err, ))

    if status_file.ExitStatusIsSuccess():
      sys.exit(constants.EXIT_SUCCESS)

    sys.exit(constants.EXIT_FAILURE)
  finally:
    status_file.Update(True)


if __name__ == "__main__":
  main()
