#
#

# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012, 2013 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

"""Ganeti Remote API master script.

"""

# pylint: disable=C0103,W0142

# C0103: Invalid name ganeti-watcher

import logging
import optparse
import sys
import os
import os.path
import errno

try:
  from pyinotify import pyinotify # pylint: disable=E0611
except ImportError:
  import pyinotify

from ganeti import asyncnotifier
from ganeti import constants
from ganeti import http
from ganeti import daemon
from ganeti import ssconf
from ganeti import luxi
from ganeti import serializer
from ganeti import compat
from ganeti import utils
from ganeti import pathutils
from ganeti.rapi import connector
from ganeti.rapi import baserlib

import ganeti.http.auth   # pylint: disable=W0611
import ganeti.http.server


class RemoteApiRequestContext(object):
  """Data structure for Remote API requests.

  """
  def __init__(self):
    self.handler = None
    self.handler_fn = None
    self.handler_access = None
    self.body_data = None


class RemoteApiHandler(http.auth.HttpServerRequestAuthentication,
                       http.server.HttpServerHandler):
  """REST Request Handler Class.

  """
  AUTH_REALM = "Ganeti Remote API"

  def __init__(self, user_fn, reqauth, _client_cls=None):
    """Initializes this class.

    @type user_fn: callable
    @param user_fn: Function receiving username as string and returning
      L{http.auth.PasswordFileUser} or C{None} if user is not found
    @type reqauth: bool
    @param reqauth: Whether to require authentication

    """
    # pylint: disable=W0233
    # it seems pylint doesn't see the second parent class there
    http.server.HttpServerHandler.__init__(self)
    http.auth.HttpServerRequestAuthentication.__init__(self)
    self._client_cls = _client_cls
    self._resmap = connector.Mapper()
    self._user_fn = user_fn
    self._reqauth = reqauth

  @staticmethod
  def FormatErrorMessage(values):
    """Formats the body of an error message.

    @type values: dict
    @param values: dictionary with keys C{code}, C{message} and C{explain}.
    @rtype: tuple; (string, string)
    @return: Content-type and response body

    """
    return (http.HTTP_APP_JSON, serializer.DumpJson(values))

  def _GetRequestContext(self, req):
    """Returns the context for a request.

    The context is cached in the req.private variable.

    """
    if req.private is None:
      (HandlerClass, items, args) = \
                     self._resmap.getController(req.request_path)

      ctx = RemoteApiRequestContext()
      ctx.handler = HandlerClass(items, args, req, _client_cls=self._client_cls)

      method = req.request_method.upper()
      try:
        ctx.handler_fn = getattr(ctx.handler, method)
      except AttributeError:
        raise http.HttpNotImplemented("Method %s is unsupported for path %s" %
                                      (method, req.request_path))

      ctx.handler_access = baserlib.GetHandlerAccess(ctx.handler, method)

      # Require permissions definition (usually in the base class)
      if ctx.handler_access is None:
        raise AssertionError("Permissions definition missing")

      # This is only made available in HandleRequest
      ctx.body_data = None

      req.private = ctx

    # Check for expected attributes
    assert req.private.handler
    assert req.private.handler_fn
    assert req.private.handler_access is not None

    return req.private

  def AuthenticationRequired(self, req):
    """Determine whether authentication is required.

    """
    return self._reqauth or bool(self._GetRequestContext(req).handler_access)

  def Authenticate(self, req, username, password):
    """Checks whether a user can access a resource.

    """
    ctx = self._GetRequestContext(req)

    user = self._user_fn(username)
    if not (user and
            self.VerifyBasicAuthPassword(req, username, password,
                                         user.password)):
      # Unknown user or password wrong
      return False

    if (not ctx.handler_access or
        set(user.options).intersection(ctx.handler_access)):
      # Allow access
      return True

    # Access forbidden
    raise http.HttpForbidden()

  def HandleRequest(self, req):
    """Handles a request.

    """
    ctx = self._GetRequestContext(req)

    # Deserialize request parameters
    if req.request_body:
      # RFC2616, 7.2.1: Any HTTP/1.1 message containing an entity-body SHOULD
      # include a Content-Type header field defining the media type of that
      # body. [...] If the media type remains unknown, the recipient SHOULD
      # treat it as type "application/octet-stream".
      req_content_type = req.request_headers.get(http.HTTP_CONTENT_TYPE,
                                                 http.HTTP_APP_OCTET_STREAM)
      if req_content_type.lower() != http.HTTP_APP_JSON.lower():
        raise http.HttpUnsupportedMediaType()

      try:
        ctx.body_data = serializer.LoadJson(req.request_body)
      except Exception:
        raise http.HttpBadRequest(message="Unable to parse JSON data")
    else:
      ctx.body_data = None

    try:
      result = ctx.handler_fn()
    except luxi.TimeoutError:
      raise http.HttpGatewayTimeout()
    except luxi.ProtocolError, err:
      raise http.HttpBadGateway(str(err))

    req.resp_headers[http.HTTP_CONTENT_TYPE] = http.HTTP_APP_JSON

    return serializer.DumpJson(result)


class RapiUsers:
  def __init__(self):
    """Initializes this class.

    """
    self._users = None

  def Get(self, username):
    """Checks whether a user exists.

    """
    if self._users:
      return self._users.get(username, None)
    else:
      return None

  def Load(self, filename):
    """Loads a file containing users and passwords.

    @type filename: string
    @param filename: Path to file

    """
    logging.info("Reading users file at %s", filename)
    try:
      try:
        contents = utils.ReadFile(filename)
      except EnvironmentError, err:
        self._users = None
        if err.errno == errno.ENOENT:
          logging.warning("No users file at %s", filename)
        else:
          logging.warning("Error while reading %s: %s", filename, err)
        return False

      users = http.auth.ParsePasswordFile(contents)

    except Exception, err: # pylint: disable=W0703
      # We don't care about the type of exception
      logging.error("Error while parsing %s: %s", filename, err)
      return False

    self._users = users

    return True


class FileEventHandler(asyncnotifier.FileEventHandlerBase):
  def __init__(self, wm, path, cb):
    """Initializes this class.

    @param wm: Inotify watch manager
    @type path: string
    @param path: File path
    @type cb: callable
    @param cb: Function called on file change

    """
    asyncnotifier.FileEventHandlerBase.__init__(self, wm)

    self._cb = cb
    self._filename = os.path.basename(path)

    # Different Pyinotify versions have the flag constants at different places,
    # hence not accessing them directly
    mask = (pyinotify.EventsCodes.ALL_FLAGS["IN_CLOSE_WRITE"] |
            pyinotify.EventsCodes.ALL_FLAGS["IN_DELETE"] |
            pyinotify.EventsCodes.ALL_FLAGS["IN_MOVED_FROM"] |
            pyinotify.EventsCodes.ALL_FLAGS["IN_MOVED_TO"])

    self._handle = self.AddWatch(os.path.dirname(path), mask)

  def process_default(self, event):
    """Called upon inotify event.

    """
    if event.name == self._filename:
      logging.debug("Received inotify event %s", event)
      self._cb()


def SetupFileWatcher(filename, cb):
  """Configures an inotify watcher for a file.

  @type filename: string
  @param filename: File to watch
  @type cb: callable
  @param cb: Function called on file change

  """
  wm = pyinotify.WatchManager()
  handler = FileEventHandler(wm, filename, cb)
  asyncnotifier.AsyncNotifier(wm, default_proc_fun=handler)


def CheckRapi(options, args):
  """Initial checks whether to run or exit with a failure.

  """
  if args: # rapi doesn't take any arguments
    print >> sys.stderr, ("Usage: %s [-f] [-d] [-p port] [-b ADDRESS]" %
                          sys.argv[0])
    sys.exit(constants.EXIT_FAILURE)

  ssconf.CheckMaster(options.debug)

  # Read SSL certificate (this is a little hackish to read the cert as root)
  if options.ssl:
    options.ssl_params = http.HttpSslParams(ssl_key_path=options.ssl_key,
                                            ssl_cert_path=options.ssl_cert)
  else:
    options.ssl_params = None


def PrepRapi(options, _):
  """Prep remote API function, executed with the PID file held.

  """
  mainloop = daemon.Mainloop()

  users = RapiUsers()

  handler = RemoteApiHandler(users.Get, options.reqauth)

  # Setup file watcher (it'll be driven by asyncore)
  SetupFileWatcher(pathutils.RAPI_USERS_FILE,
                   compat.partial(users.Load, pathutils.RAPI_USERS_FILE))

  users.Load(pathutils.RAPI_USERS_FILE)

  server = \
    http.server.HttpServer(mainloop, options.bind_address, options.port,
                           handler,
                           ssl_params=options.ssl_params, ssl_verify_peer=False)
  server.Start()

  return (mainloop, server)


def ExecRapi(options, args, prep_data): # pylint: disable=W0613
  """Main remote API function, executed with the PID file held.

  """
  (mainloop, server) = prep_data
  try:
    mainloop.Run()
  finally:
    server.Stop()


def Main():
  """Main function.

  """
  parser = optparse.OptionParser(description="Ganeti Remote API",
                                 usage=("%prog [-f] [-d] [-p port] [-b ADDRESS]"
                                        " [-i INTERFACE]"),
                                 version="%%prog (ganeti) %s" %
                                 constants.RELEASE_VERSION)
  parser.add_option("--require-authentication", dest="reqauth",
                    default=False, action="store_true",
                    help=("Disable anonymous HTTP requests and require"
                          " authentication"))

  daemon.GenericMain(constants.RAPI, parser, CheckRapi, PrepRapi, ExecRapi,
                     default_ssl_cert=pathutils.RAPI_CERT_FILE,
                     default_ssl_key=pathutils.RAPI_CERT_FILE)
