#
#

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


"""Base class for all hypervisors

The syntax for the _CHECK variables and the contents of the PARAMETERS
dict is the same, see the docstring for L{BaseHypervisor.PARAMETERS}.

@var _FILE_CHECK: stub for file checks, without the required flag
@var _DIR_CHECK: stub for directory checks, without the required flag
@var REQ_FILE_CHECK: mandatory file parameter
@var OPT_FILE_CHECK: optional file parameter
@var REQ_DIR_CHECK: mandatory directory parametr
@var OPT_DIR_CHECK: optional directory parameter
@var NO_CHECK: parameter without any checks at all
@var REQUIRED_CHECK: parameter required to exist (and non-false), but
    without other checks; beware that this can't be used for boolean
    parameters, where you should use NO_CHECK or a custom checker

"""

import os
import re
import logging


from ganeti import errors
from ganeti import utils
from ganeti import constants


def _IsCpuMaskWellFormed(cpu_mask):
  """Verifies if the given single CPU mask is valid

  The single CPU mask should be in the form "a,b,c,d", where each
  letter is a positive number or range.

  """
  try:
    cpu_list = utils.ParseCpuMask(cpu_mask)
  except errors.ParseError, _:
    return False
  return isinstance(cpu_list, list) and len(cpu_list) > 0


def _IsMultiCpuMaskWellFormed(cpu_mask):
  """Verifies if the given multiple CPU mask is valid

  A valid multiple CPU mask is in the form "a:b:c:d", where each
  letter is a single CPU mask.

  """
  try:
    utils.ParseMultiCpuMask(cpu_mask)
  except errors.ParseError, _:
    return False

  return True


# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
# _CHECK values

# must be afile
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
               os.path.isfile, "not found or not a file")

# must be a directory
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
              os.path.isdir, "not found or not a directory")

# CPU mask must be well-formed
# TODO: implement node level check for the CPU mask
_CPU_MASK_CHECK = (_IsCpuMaskWellFormed,
                   "CPU mask definition is not well-formed",
                   None, None)

# Multiple CPU mask must be well-formed
_MULTI_CPU_MASK_CHECK = (_IsMultiCpuMaskWellFormed,
                         "Multiple CPU mask definition is not well-formed",
                         None, None)

# Check for validity of port number
_NET_PORT_CHECK = (lambda x: 0 < x < 65535, "invalid port number",
                   None, None)

# Check that an integer is non negative
_NONNEGATIVE_INT_CHECK = (lambda x: x >= 0, "cannot be negative", None, None)

# nice wrappers for users
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
REQ_DIR_CHECK = (True, ) + _DIR_CHECK
OPT_DIR_CHECK = (False, ) + _DIR_CHECK
REQ_NET_PORT_CHECK = (True, ) + _NET_PORT_CHECK
OPT_NET_PORT_CHECK = (False, ) + _NET_PORT_CHECK
REQ_CPU_MASK_CHECK = (True, ) + _CPU_MASK_CHECK
OPT_CPU_MASK_CHECK = (False, ) + _CPU_MASK_CHECK
REQ_MULTI_CPU_MASK_CHECK = (True, ) + _MULTI_CPU_MASK_CHECK
OPT_MULTI_CPU_MASK_CHECK = (False, ) + _MULTI_CPU_MASK_CHECK
REQ_NONNEGATIVE_INT_CHECK = (True, ) + _NONNEGATIVE_INT_CHECK
OPT_NONNEGATIVE_INT_CHECK = (False, ) + _NONNEGATIVE_INT_CHECK

# no checks at all
NO_CHECK = (False, None, None, None, None)

# required, but no other checks
REQUIRED_CHECK = (True, None, None, None, None)

# migration type
MIGRATION_MODE_CHECK = (True, lambda x: x in constants.HT_MIGRATION_MODES,
                        "invalid migration mode", None, None)


def ParamInSet(required, my_set):
  """Builds parameter checker for set membership.

  @type required: boolean
  @param required: whether this is a required parameter
  @type my_set: tuple, list or set
  @param my_set: allowed values set

  """
  fn = lambda x: x in my_set
  err = ("The value must be one of: %s" % utils.CommaJoin(my_set))
  return (required, fn, err, None, None)


class BaseHypervisor(object):
  """Abstract virtualisation technology interface

  The goal is that all aspects of the virtualisation technology are
  abstracted away from the rest of code.

  @cvar PARAMETERS: a dict of parameter name: check type; the check type is
      a five-tuple containing:
          - the required flag (boolean)
          - a function to check for syntax, that will be used in
            L{CheckParameterSyntax}, in the master daemon process
          - an error message for the above function
          - a function to check for parameter validity on the remote node,
            in the L{ValidateParameters} function
          - an error message for the above function
  @type CAN_MIGRATE: boolean
  @cvar CAN_MIGRATE: whether this hypervisor can do migration (either
      live or non-live)

  """
  PARAMETERS = {}
  ANCILLARY_FILES = []
  ANCILLARY_FILES_OPT = []
  CAN_MIGRATE = False

  def StartInstance(self, instance, block_devices, startup_paused):
    """Start an instance."""
    raise NotImplementedError

  def StopInstance(self, instance, force=False, retry=False, name=None,
                   timeout=None):
    """Stop an instance

    @type instance: L{objects.Instance}
    @param instance: instance to stop
    @type force: boolean
    @param force: whether to do a "hard" stop (destroy)
    @type retry: boolean
    @param retry: whether this is just a retry call
    @type name: string or None
    @param name: if this parameter is passed, the the instance object
        should not be used (will be passed as None), and the shutdown
        must be done by name only
    @type timeout: int or None
    @param timeout: if the parameter is not None, a soft shutdown operation will
        be killed after the specified number of seconds. A hard (forced)
        shutdown cannot have a timeout

    """
    raise NotImplementedError

  def CleanupInstance(self, instance_name):
    """Cleanup after a stopped instance

    This is an optional method, used by hypervisors that need to cleanup after
    an instance has been stopped.

    @type instance_name: string
    @param instance_name: instance name to cleanup after

    """
    pass

  def RebootInstance(self, instance):
    """Reboot an instance."""
    raise NotImplementedError

  def ListInstances(self, hvparams=None):
    """Get the list of running instances."""
    raise NotImplementedError

  def GetInstanceInfo(self, instance_name, hvparams=None):
    """Get instance properties.

    @type instance_name: string
    @param instance_name: the instance name
    @type hvparams: dict of strings
    @param hvparams: hvparams to be used with this instance

    @return: tuple (name, id, memory, vcpus, state, times)

    """
    raise NotImplementedError

  def GetAllInstancesInfo(self, hvparams=None):
    """Get properties of all instances.

    @type hvparams: dict of strings
    @param hvparams: hypervisor parameter
    @return: list of tuples (name, id, memory, vcpus, stat, times)

    """
    raise NotImplementedError

  def GetNodeInfo(self, hvparams=None):
    """Return information about the node.

    @type hvparams: dict of strings
    @param hvparams: hypervisor parameters

    @return: a dict with at least the following keys (memory values in MiB):
          - memory_total: the total memory size on the node
          - memory_free: the available memory on the node for instances
          - memory_dom0: the memory used by the node itself, if available
          - cpu_total: total number of CPUs
          - cpu_dom0: number of CPUs used by the node OS
          - cpu_nodes: number of NUMA domains
          - cpu_sockets: number of physical CPU sockets

    """
    raise NotImplementedError

  @classmethod
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
    """Return information for connecting to the console of an instance.

    """
    raise NotImplementedError

  @classmethod
  def GetAncillaryFiles(cls):
    """Return a list of ancillary files to be copied to all nodes as ancillary
    configuration files.

    @rtype: (list of absolute paths, list of absolute paths)
    @return: (all files, optional files)

    """
    # By default we return a member variable, so that if an hypervisor has just
    # a static list of files it doesn't have to override this function.
    assert set(cls.ANCILLARY_FILES).issuperset(cls.ANCILLARY_FILES_OPT), \
      "Optional ancillary files must be a subset of ancillary files"

    return (cls.ANCILLARY_FILES, cls.ANCILLARY_FILES_OPT)

  def Verify(self, hvparams=None):
    """Verify the hypervisor.

    @type hvparams: dict of strings
    @param hvparams: hypervisor parameters to be verified against

    @return: Problem description if something is wrong, C{None} otherwise

    """
    raise NotImplementedError

  def MigrationInfo(self, instance): # pylint: disable=R0201,W0613
    """Get instance information to perform a migration.

    By default assume no information is needed.

    @type instance: L{objects.Instance}
    @param instance: instance to be migrated
    @rtype: string/data (opaque)
    @return: instance migration information - serialized form

    """
    return ""

  def AcceptInstance(self, instance, info, target):
    """Prepare to accept an instance.

    By default assume no preparation is needed.

    @type instance: L{objects.Instance}
    @param instance: instance to be accepted
    @type info: string/data (opaque)
    @param info: migration information, from the source node
    @type target: string
    @param target: target host (usually ip), on this node

    """
    pass

  def BalloonInstanceMemory(self, instance, mem):
    """Balloon an instance memory to a certain value.

    @type instance: L{objects.Instance}
    @param instance: instance to be accepted
    @type mem: int
    @param mem: actual memory size to use for instance runtime

    """
    raise NotImplementedError

  def FinalizeMigrationDst(self, instance, info, success):
    """Finalize the instance migration on the target node.

    Should finalize or revert any preparation done to accept the instance.
    Since by default we do no preparation, we also don't have anything to do

    @type instance: L{objects.Instance}
    @param instance: instance whose migration is being finalized
    @type info: string/data (opaque)
    @param info: migration information, from the source node
    @type success: boolean
    @param success: whether the migration was a success or a failure

    """
    pass

  def MigrateInstance(self, cluster_name, instance, target, live):
    """Migrate an instance.

    @type cluster_name: string
    @param cluster_name: name of the cluster
    @type instance: L{objects.Instance}
    @param instance: the instance to be migrated
    @type target: string
    @param target: hostname (usually ip) of the target node
    @type live: boolean
    @param live: whether to do a live or non-live migration

    """
    raise NotImplementedError

  def FinalizeMigrationSource(self, instance, success, live):
    """Finalize the instance migration on the source node.

    @type instance: L{objects.Instance}
    @param instance: the instance that was migrated
    @type success: bool
    @param success: whether the migration succeeded or not
    @type live: bool
    @param live: whether the user requested a live migration or not

    """
    pass

  def GetMigrationStatus(self, instance):
    """Get the migration status

    @type instance: L{objects.Instance}
    @param instance: the instance that is being migrated
    @rtype: L{objects.MigrationStatus}
    @return: the status of the current migration (one of
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
             progress info that can be retrieved from the hypervisor

    """
    raise NotImplementedError

  def _InstanceStartupMemory(self, instance):
    """Get the correct startup memory for an instance

    This function calculates how much memory an instance should be started
    with, making sure it's a value between the minimum and the maximum memory,
    but also trying to use no more than the current free memory on the node.

    @type instance: L{objects.Instance}
    @param instance: the instance that is being started
    @rtype: integer
    @return: memory the instance should be started with

    """
    free_memory = self.GetNodeInfo(hvparams=instance.hvparams)["memory_free"]
    max_start_mem = min(instance.beparams[constants.BE_MAXMEM], free_memory)
    start_mem = max(instance.beparams[constants.BE_MINMEM], max_start_mem)
    return start_mem

  @classmethod
  def CheckParameterSyntax(cls, hvparams):
    """Check the given parameters for validity.

    This should check the passed set of parameters for
    validity. Classes should extend, not replace, this function.

    @type hvparams:  dict
    @param hvparams: dictionary with parameter names/value
    @raise errors.HypervisorError: when a parameter is not valid

    """
    for key in hvparams:
      if key not in cls.PARAMETERS:
        raise errors.HypervisorError("Parameter '%s' is not supported" % key)

    # cheap tests that run on the master, should not access the world
    for name, (required, check_fn, errstr, _, _) in cls.PARAMETERS.items():
      if name not in hvparams:
        raise errors.HypervisorError("Parameter '%s' is missing" % name)
      value = hvparams[name]
      if not required and not value:
        continue
      if not value:
        raise errors.HypervisorError("Parameter '%s' is required but"
                                     " is currently not defined" % (name, ))
      if check_fn is not None and not check_fn(value):
        raise errors.HypervisorError("Parameter '%s' fails syntax"
                                     " check: %s (current value: '%s')" %
                                     (name, errstr, value))

  @classmethod
  def ValidateParameters(cls, hvparams):
    """Check the given parameters for validity.

    This should check the passed set of parameters for
    validity. Classes should extend, not replace, this function.

    @type hvparams:  dict
    @param hvparams: dictionary with parameter names/value
    @raise errors.HypervisorError: when a parameter is not valid

    """
    for name, (required, _, _, check_fn, errstr) in cls.PARAMETERS.items():
      value = hvparams[name]
      if not required and not value:
        continue
      if check_fn is not None and not check_fn(value):
        raise errors.HypervisorError("Parameter '%s' fails"
                                     " validation: %s (current value: '%s')" %
                                     (name, errstr, value))

  @classmethod
  def PowercycleNode(cls, hvparams=None):
    """Hard powercycle a node using hypervisor specific methods.

    This method should hard powercycle the node, using whatever
    methods the hypervisor provides. Note that this means that all
    instances running on the node must be stopped too.

    @type hvparams: dict of strings
    @param hvparams: hypervisor params to be used on this node

    """
    raise NotImplementedError

  @staticmethod
  def GetLinuxNodeInfo(meminfo="/proc/meminfo", cpuinfo="/proc/cpuinfo"):
    """For linux systems, return actual OS information.

    This is an abstraction for all non-hypervisor-based classes, where
    the node actually sees all the memory and CPUs via the /proc
    interface and standard commands. The other case if for example
    xen, where you only see the hardware resources via xen-specific
    tools.

    @param meminfo: name of the file containing meminfo
    @type meminfo: string
    @param cpuinfo: name of the file containing cpuinfo
    @type cpuinfo: string
    @return: a dict with the following keys (values in MiB):
          - memory_total: the total memory size on the node
          - memory_free: the available memory on the node for instances
          - memory_dom0: the memory used by the node itself, if available
          - cpu_total: total number of CPUs
          - cpu_dom0: number of CPUs used by the node OS
          - cpu_nodes: number of NUMA domains
          - cpu_sockets: number of physical CPU sockets

    """
    try:
      data = utils.ReadFile(meminfo).splitlines()
    except EnvironmentError, err:
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))

    result = {}
    sum_free = 0
    try:
      for line in data:
        splitfields = line.split(":", 1)

        if len(splitfields) > 1:
          key = splitfields[0].strip()
          val = splitfields[1].strip()
          if key == "MemTotal":
            result["memory_total"] = int(val.split()[0]) / 1024
          elif key in ("MemFree", "Buffers", "Cached"):
            sum_free += int(val.split()[0]) / 1024
          elif key == "Active":
            result["memory_dom0"] = int(val.split()[0]) / 1024
    except (ValueError, TypeError), err:
      raise errors.HypervisorError("Failed to compute memory usage: %s" %
                                   (err,))
    result["memory_free"] = sum_free

    cpu_total = 0
    try:
      fh = open(cpuinfo)
      try:
        cpu_total = len(re.findall(r"(?m)^processor\s*:\s*[0-9]+\s*$",
                                   fh.read()))
      finally:
        fh.close()
    except EnvironmentError, err:
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
    result["cpu_total"] = cpu_total
    # We assume that the node OS can access all the CPUs
    result["cpu_dom0"] = cpu_total
    # FIXME: export correct data here
    result["cpu_nodes"] = 1
    result["cpu_sockets"] = 1

    return result

  @classmethod
  def LinuxPowercycle(cls):
    """Linux-specific powercycle method.

    """
    try:
      fd = os.open("/proc/sysrq-trigger", os.O_WRONLY)
      try:
        os.write(fd, "b")
      finally:
        fd.close()
    except OSError:
      logging.exception("Can't open the sysrq-trigger file")
      result = utils.RunCmd(["reboot", "-n", "-f"])
      if not result:
        logging.error("Can't run shutdown: %s", result.output)

  @staticmethod
  def _FormatVerifyResults(msgs):
    """Formats the verification results, given a list of errors.

    @param msgs: list of errors, possibly empty
    @return: overall problem description if something is wrong,
        C{None} otherwise

    """
    if msgs:
      return "; ".join(msgs)
    else:
      return None
