#
#

# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 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.


"""Xen hypervisors

"""

import logging
import errno
import string # pylint: disable=W0402
import shutil
import time
from cStringIO import StringIO

from ganeti import constants
from ganeti import errors
from ganeti import utils
from ganeti.hypervisor import hv_base
from ganeti import netutils
from ganeti import objects
from ganeti import pathutils


XEND_CONFIG_FILE = utils.PathJoin(pathutils.XEN_CONFIG_DIR, "xend-config.sxp")
XL_CONFIG_FILE = utils.PathJoin(pathutils.XEN_CONFIG_DIR, "xen/xl.conf")
VIF_BRIDGE_SCRIPT = utils.PathJoin(pathutils.XEN_CONFIG_DIR,
                                   "scripts/vif-bridge")
_DOM0_NAME = "Domain-0"
_DISK_LETTERS = string.ascii_lowercase

_FILE_DRIVER_MAP = {
  constants.FD_LOOP: "file",
  constants.FD_BLKTAP: "tap:aio",
  constants.FD_BLKTAP2: "tap2:tapdisk:aio",
  }


def _CreateConfigCpus(cpu_mask):
  """Create a CPU config string for Xen's config file.

  """
  # Convert the string CPU mask to a list of list of int's
  cpu_list = utils.ParseMultiCpuMask(cpu_mask)

  if len(cpu_list) == 1:
    all_cpu_mapping = cpu_list[0]
    if all_cpu_mapping == constants.CPU_PINNING_OFF:
      # If CPU pinning has 1 entry that's "all", then remove the
      # parameter from the config file
      return None
    else:
      # If CPU pinning has one non-all entry, mapping all vCPUS (the entire
      # VM) to one physical CPU, using format 'cpu = "C"'
      return "cpu = \"%s\"" % ",".join(map(str, all_cpu_mapping))
  else:

    def _GetCPUMap(vcpu):
      if vcpu[0] == constants.CPU_PINNING_ALL_VAL:
        cpu_map = constants.CPU_PINNING_ALL_XEN
      else:
        cpu_map = ",".join(map(str, vcpu))
      return "\"%s\"" % cpu_map

    # build the result string in format 'cpus = [ "c", "c", "c" ]',
    # where each c is a physical CPU number, a range, a list, or any
    # combination
    return "cpus = [ %s ]" % ", ".join(map(_GetCPUMap, cpu_list))


def _RunInstanceList(fn, instance_list_errors):
  """Helper function for L{_GetAllInstanceList} to retrieve the list
  of instances from xen.

  @type fn: callable
  @param fn: Function to query xen for the list of instances
  @type instance_list_errors: list
  @param instance_list_errors: Error list
  @rtype: list

  """
  result = fn()
  if result.failed:
    logging.error("Retrieving the instance list from xen failed (%s): %s",
                  result.fail_reason, result.output)
    instance_list_errors.append(result)
    raise utils.RetryAgain()

  # skip over the heading
  return result.stdout.splitlines()


class _InstanceCrashed(errors.GenericError):
  """Instance has reached a violent ending.

  This is raised within the Xen hypervisor only, and should not be seen or used
  outside.

  """


def _ParseInstanceList(lines, include_node):
  """Parses the output of listing instances by xen.

  @type lines: list
  @param lines: Result of retrieving the instance list from xen
  @type include_node: boolean
  @param include_node: If True, return information for Dom0
  @return: list of tuple containing (name, id, memory, vcpus, state, time
    spent)

  """
  result = []

  # Iterate through all lines while ignoring header
  for line in lines[1:]:
    # The format of lines is:
    # Name      ID Mem(MiB) VCPUs State  Time(s)
    # Domain-0   0  3418     4 r-----    266.2
    data = line.split()
    if len(data) != 6:
      raise errors.HypervisorError("Can't parse instance list,"
                                   " line: %s" % line)
    try:
      data[1] = int(data[1])
      data[2] = int(data[2])
      data[3] = int(data[3])
      data[4] = _XenToHypervisorInstanceState(data[4])
      data[5] = float(data[5])
    except (TypeError, ValueError), err:
      raise errors.HypervisorError("Can't parse instance list,"
                                   " line: %s, error: %s" % (line, err))
    except _InstanceCrashed:
      # The crashed instance can be interpreted as being down, so we omit it
      # from the instance list.
      continue

    # skip the Domain-0 (optional)
    if include_node or data[0] != _DOM0_NAME:
      result.append(data)

  return result


def _GetAllInstanceList(fn, include_node, delays, timeout):
  """Return the list of instances including running and shutdown.

  See L{_RunInstanceList} and L{_ParseInstanceList} for parameter details.

  """
  instance_list_errors = []
  try:
    lines = utils.Retry(_RunInstanceList, delays, timeout,
                        args=(fn, instance_list_errors))
  except utils.RetryTimeout:
    if instance_list_errors:
      instance_list_result = instance_list_errors.pop()

      errmsg = ("listing instances failed, timeout exceeded (%s): %s" %
                (instance_list_result.fail_reason, instance_list_result.output))
    else:
      errmsg = "listing instances failed"

    raise errors.HypervisorError(errmsg)

  return _ParseInstanceList(lines, include_node)


def _IsInstanceRunning(instance_info):
  """Determine whether an instance is running.

  An instance is running if it is in the following Xen states:
  running, blocked, paused, or dying (about to be destroyed / shutdown).

  For some strange reason, Xen once printed 'rb----' which does not make any
  sense because an instance cannot be both running and blocked.  Fortunately,
  for Ganeti 'running' or 'blocked' is the same as 'running'.

  A state of nothing '------' means that the domain is runnable but it is not
  currently running.  That means it is in the queue behind other domains waiting
  to be scheduled to run.
  http://old-list-archives.xenproject.org/xen-users/2007-06/msg00849.html

  A dying instance is about to be removed, but it is still consuming resources,
  and counts as running.

  @type instance_info: string
  @param instance_info: Information about instance, as supplied by Xen.
  @rtype: bool
  @return: Whether an instance is running.

  """
  allowable_running_prefixes = [
    "r--",
    "rb-",
    "-b-",
    "---",
  ]

  def _RunningWithSuffix(suffix):
    return [x + suffix for x in allowable_running_prefixes]

  # The shutdown suspend ("ss") state is encountered during migration, where
  # the instance is still considered to be running.
  # The shutdown restart ("sr") is probably encountered during restarts - still
  # running.
  # See Xen commit e1475a6693aac8cddc4bdd456548aa05a625556b
  return instance_info in _RunningWithSuffix("---") \
      or instance_info in _RunningWithSuffix("ss-") \
      or instance_info in _RunningWithSuffix("sr-") \
      or instance_info == "-----d"


def _IsInstanceShutdown(instance_info):
  """Determine whether the instance is shutdown.

  An instance is shutdown when a user shuts it down from within, and we do not
  remove domains to be able to detect that.

  The dying state has been added as a precaution, as Xen's status reporting is
  weird.

  """
  return instance_info == "---s--" \
      or instance_info == "---s-d"


def _IgnorePaused(instance_info):
  """Removes information about whether a Xen state is paused from the state.

  As it turns out, an instance can be reported as paused in almost any
  condition. Paused instances can be paused, running instances can be paused for
  scheduling, and any other condition can appear to be paused as a result of
  races or improbable conditions in Xen's status reporting.
  As we do not use Xen's pause commands in any way at the time, we can simply
  ignore the paused field and save ourselves a lot of trouble.

  Should we ever use the pause commands, several samples would be needed before
  we could confirm the domain as paused.

  """
  return instance_info.replace('p', '-')


def _IsCrashed(instance_info):
  """Returns whether an instance is in the crashed Xen state.

  When a horrible misconfiguration happens to a Xen domain, it can crash,
  meaning that it encounters a violent ending. While this state usually flashes
  only temporarily before the domain is restarted, being able to check for it
  allows Ganeti not to act confused and do something about it.

  """
  return instance_info.count('c') > 0


def _XenToHypervisorInstanceState(instance_info):
  """Maps Xen states to hypervisor states.

  @type instance_info: string
  @param instance_info: Information about instance, as supplied by Xen.
  @rtype: L{hv_base.HvInstanceState}

  """
  instance_info = _IgnorePaused(instance_info)

  if _IsCrashed(instance_info):
    raise _InstanceCrashed("Instance detected as crashed, should be omitted")

  if _IsInstanceRunning(instance_info):
    return hv_base.HvInstanceState.RUNNING
  elif _IsInstanceShutdown(instance_info):
    return hv_base.HvInstanceState.SHUTDOWN
  else:
    raise errors.HypervisorError("hv_xen._XenToHypervisorInstanceState:"
                                 " unhandled Xen instance state '%s'" %
                                   instance_info)


def _GetRunningInstanceList(fn, include_node, delays, timeout):
  """Return the list of running instances.

  See L{_GetAllInstanceList} for parameter details.

  """
  instances = _GetAllInstanceList(fn, include_node, delays, timeout)
  return [i for i in instances if hv_base.HvInstanceState.IsRunning(i[4])]


def _GetShutdownInstanceList(fn, include_node, delays, timeout):
  """Return the list of shutdown instances.

  See L{_GetAllInstanceList} for parameter details.

  """
  instances = _GetAllInstanceList(fn, include_node, delays, timeout)
  return [i for i in instances if hv_base.HvInstanceState.IsShutdown(i[4])]


def _ParseNodeInfo(info):
  """Return information about the node.

  @return: a dict with 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
        - nr_cpus: total number of CPUs
        - nr_nodes: in a NUMA system, the number of domains
        - nr_sockets: the number of physical CPU sockets in the node
        - hv_version: the hypervisor version in the form (major, minor)

  """
  result = {}
  cores_per_socket = threads_per_core = nr_cpus = None
  xen_major, xen_minor = None, None
  memory_total = None
  memory_free = None

  for line in info.splitlines():
    fields = line.split(":", 1)

    if len(fields) < 2:
      continue

    (key, val) = (s.strip() for s in fields)

    # Note: in Xen 3, memory has changed to total_memory
    if key in ("memory", "total_memory"):
      memory_total = int(val)
    elif key == "free_memory":
      memory_free = int(val)
    elif key == "nr_cpus":
      nr_cpus = result["cpu_total"] = int(val)
    elif key == "nr_nodes":
      result["cpu_nodes"] = int(val)
    elif key == "cores_per_socket":
      cores_per_socket = int(val)
    elif key == "threads_per_core":
      threads_per_core = int(val)
    elif key == "xen_major":
      xen_major = int(val)
    elif key == "xen_minor":
      xen_minor = int(val)

  if None not in [cores_per_socket, threads_per_core, nr_cpus]:
    result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)

  if memory_free is not None:
    result["memory_free"] = memory_free

  if memory_total is not None:
    result["memory_total"] = memory_total

  if not (xen_major is None or xen_minor is None):
    result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor)

  return result


def _MergeInstanceInfo(info, instance_list):
  """Updates node information from L{_ParseNodeInfo} with instance info.

  @type info: dict
  @param info: Result from L{_ParseNodeInfo}
  @type instance_list: list of tuples
  @param instance_list: list of instance information; one tuple per instance
  @rtype: dict

  """
  total_instmem = 0

  for (name, _, mem, vcpus, _, _) in instance_list:
    if name == _DOM0_NAME:
      info["memory_dom0"] = mem
      info["cpu_dom0"] = vcpus

    # Include Dom0 in total memory usage
    total_instmem += mem

  memory_free = info.get("memory_free")
  memory_total = info.get("memory_total")

  # Calculate memory used by hypervisor
  if None not in [memory_total, memory_free, total_instmem]:
    info["memory_hv"] = memory_total - memory_free - total_instmem

  return info


def _GetNodeInfo(info, instance_list):
  """Combines L{_MergeInstanceInfo} and L{_ParseNodeInfo}.

  @type instance_list: list of tuples
  @param instance_list: list of instance information; one tuple per instance

  """
  return _MergeInstanceInfo(_ParseNodeInfo(info), instance_list)


def _GetConfigFileDiskData(block_devices, blockdev_prefix,
                           _letters=_DISK_LETTERS):
  """Get disk directives for Xen config file.

  This method builds the xen config disk directive according to the
  given disk_template and block_devices.

  @param block_devices: list of tuples (cfdev, rldev):
      - cfdev: dict containing ganeti config disk part
      - rldev: ganeti.block.bdev.BlockDev object
  @param blockdev_prefix: a string containing blockdevice prefix,
                          e.g. "sd" for /dev/sda

  @return: string containing disk directive for xen instance config file

  """
  if len(block_devices) > len(_letters):
    raise errors.HypervisorError("Too many disks")

  disk_data = []

  for sd_suffix, (cfdev, dev_path, _) in zip(_letters, block_devices):
    sd_name = blockdev_prefix + sd_suffix

    if cfdev.mode == constants.DISK_RDWR:
      mode = "w"
    else:
      mode = "r"

    if cfdev.dev_type in constants.DTS_FILEBASED:
      driver = _FILE_DRIVER_MAP[cfdev.logical_id[0]]
    else:
      driver = "phy"

    disk_data.append("'%s:%s,%s,%s'" % (driver, dev_path, sd_name, mode))

  return disk_data


def _QuoteCpuidField(data):
  """Add quotes around the CPUID field only if necessary.

  Xen CPUID fields come in two shapes: LIBXL strings, which need quotes around
  them, and lists of XEND strings, which don't.

  @param data: Either type of parameter.
  @return: The quoted version thereof.

  """
  return "'%s'" % data if data.startswith("host") else data


def _ConfigureNIC(instance, seq, nic, tap):
  """Run the network configuration script for a specified NIC

  See L{hv_base.ConfigureNIC}.

  @type instance: instance object
  @param instance: instance we're acting on
  @type seq: int
  @param seq: nic sequence number
  @type nic: nic object
  @param nic: nic we're acting on
  @type tap: str
  @param tap: the host's tap interface this NIC corresponds to

  """
  hv_base.ConfigureNIC(pathutils.XEN_IFUP_OS, instance, seq, nic, tap)


class XenHypervisor(hv_base.BaseHypervisor):
  """Xen generic hypervisor interface

  This is the Xen base class used for both Xen PVM and HVM. It contains
  all the functionality that is identical for both.

  """
  CAN_MIGRATE = True
  REBOOT_RETRY_COUNT = 60
  REBOOT_RETRY_INTERVAL = 10
  _ROOT_DIR = pathutils.RUN_DIR + "/xen-hypervisor"
  # contains NICs' info
  _NICS_DIR = _ROOT_DIR + "/nic"
  # contains the pidfiles of socat processes used to migrate instaces under xl
  _MIGRATION_DIR = _ROOT_DIR + "/migration"
  _DIRS = [_ROOT_DIR, _NICS_DIR, _MIGRATION_DIR]

  _INSTANCE_LIST_DELAYS = (0.3, 1.5, 1.0)
  _INSTANCE_LIST_TIMEOUT = 5

  ANCILLARY_FILES = [
    XEND_CONFIG_FILE,
    XL_CONFIG_FILE,
    VIF_BRIDGE_SCRIPT,
    ]
  ANCILLARY_FILES_OPT = [
    XEND_CONFIG_FILE,
    XL_CONFIG_FILE,
    ]

  def __init__(self, _cfgdir=None, _run_cmd_fn=None, _cmd=None):
    hv_base.BaseHypervisor.__init__(self)

    if _cfgdir is None:
      self._cfgdir = pathutils.XEN_CONFIG_DIR
    else:
      self._cfgdir = _cfgdir

    if _run_cmd_fn is None:
      self._run_cmd_fn = utils.RunCmd
    else:
      self._run_cmd_fn = _run_cmd_fn

    self._cmd = _cmd

  @staticmethod
  def _GetCommandFromHvparams(hvparams):
    """Returns the Xen command extracted from the given hvparams.

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

    """
    if hvparams is None or constants.HV_XEN_CMD not in hvparams:
      raise errors.HypervisorError("Cannot determine xen command.")
    else:
      return hvparams[constants.HV_XEN_CMD]

  def _GetCommand(self, hvparams):
    """Returns Xen command to use.

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

    """
    if self._cmd is None:
      cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
    else:
      cmd = self._cmd

    if cmd not in constants.KNOWN_XEN_COMMANDS:
      raise errors.ProgrammerError("Unknown Xen command '%s'" % cmd)

    return cmd

  def _RunXen(self, args, hvparams, timeout=None):
    """Wrapper around L{utils.process.RunCmd} to run Xen command.

    @type hvparams: dict of strings
    @param hvparams: dictionary of hypervisor params
    @type timeout: int or None
    @param timeout: if a timeout (in seconds) is specified, the command will be
                    terminated after that number of seconds.
    @see: L{utils.process.RunCmd}

    """
    cmd = []

    if timeout is not None:
      cmd.extend(["timeout", str(timeout)])

    cmd.extend([self._GetCommand(hvparams)])
    cmd.extend(args)

    return self._run_cmd_fn(cmd)

  def _ConfigFileName(self, instance_name):
    """Get the config file name for an instance.

    @param instance_name: instance name
    @type instance_name: str
    @return: fully qualified path to instance config file
    @rtype: str

    """
    return utils.PathJoin(self._cfgdir, instance_name)

  @classmethod
  def _EnsureDirs(cls, extra_dirs=None):
    """Makes sure that the directories needed by the hypervisor exist.

    @type extra_dirs: list of string or None
    @param extra_dirs: Additional directories which ought to exist.

    """
    if extra_dirs is None:
      extra_dirs = []
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in
            (cls._DIRS + extra_dirs)]
    utils.EnsureDirs(dirs)

  @classmethod
  def _WriteNICInfoFile(cls, instance, idx, nic):
    """Write the Xen config file for the instance.

    This version of the function just writes the config file from static data.

    """
    instance_name = instance.name
    cls._EnsureDirs(extra_dirs=[cls._InstanceNICDir(instance_name)])

    cfg_file = cls._InstanceNICFile(instance_name, idx)
    data = StringIO()

    data.write("TAGS=\"%s\"\n" % r"\ ".join(instance.GetTags()))
    if nic.netinfo:
      netinfo = objects.Network.FromDict(nic.netinfo)
      for k, v in netinfo.HooksDict().iteritems():
        data.write("%s=\"%s\"\n" % (k, v))

    data.write("MAC=%s\n" % nic.mac)
    if nic.ip:
      data.write("IP=%s\n" % nic.ip)
    data.write("INTERFACE_INDEX=%s\n" % str(idx))
    if nic.name:
      data.write("INTERFACE_NAME=%s\n" % nic.name)
    data.write("INTERFACE_UUID=%s\n" % nic.uuid)
    data.write("MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
    data.write("LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
    data.write("VLAN=%s\n" % nic.nicparams[constants.NIC_VLAN])

    try:
      utils.WriteFile(cfg_file, data=data.getvalue())
    except EnvironmentError, err:
      raise errors.HypervisorError("Cannot write Xen instance configuration"
                                   " file %s: %s" % (cfg_file, err))

  @staticmethod
  def VersionsSafeForMigration(src, target):
    """Decide if migration is likely to suceed for hypervisor versions.

    Given two versions of a hypervisor, give a guess whether live migration
    from the one version to the other version is likely to succeed. For Xen,
    the heuristics is, that an increase by one on the second digit is OK. This
    fits with the current numbering scheme.

    @type src: list or tuple
    @type target: list or tuple
    @rtype: bool
    """
    if src == target:
      return True

    if len(src) < 2 or len(target) < 2:
      return False

    return src[0] == target[0] and target[1] in [src[1], src[1] + 1]

  @classmethod
  def _InstanceNICDir(cls, instance_name):
    """Returns the directory holding the tap device files for a given instance.

    """
    return utils.PathJoin(cls._NICS_DIR, instance_name)

  @classmethod
  def _InstanceNICFile(cls, instance_name, seq):
    """Returns the name of the file containing the tap device for a given NIC

    """
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))

  @classmethod
  def _InstanceMigrationPidfile(cls, _instance_name):
    """Returns the name of the pid file for a socat process used to migrate.

    """
    #TODO(riba): At the moment, we are using a single pidfile because we
    # use a single port for migrations at the moment. This is because we do not
    # allow more migrations, so dynamic port selection and the needed port
    # modifications are not needed.
    # The _instance_name parameter has been left here for future use.
    return utils.PathJoin(cls._MIGRATION_DIR, constants.XL_MIGRATION_PIDFILE)

  @classmethod
  def _GetConfig(cls, instance, startup_memory, block_devices):
    """Build Xen configuration for an instance.

    """
    raise NotImplementedError

  def _WriteNicConfig(self, config, instance, hvp):
    vif_data = []

    # only XenHvmHypervisor has these hvparams
    nic_type = hvp.get(constants.HV_NIC_TYPE, None)
    vif_type = hvp.get(constants.HV_VIF_TYPE, None)
    nic_type_str = ""
    if nic_type or vif_type:
      if nic_type is None:
        if vif_type:
          nic_type_str = ", type=%s" % vif_type
      elif nic_type == constants.HT_NIC_PARAVIRTUAL:
        nic_type_str = ", type=paravirtualized"
      else:
        # parameter 'model' is only valid with type 'ioemu'
        nic_type_str = ", model=%s, type=%s" % \
          (nic_type, constants.HT_HVM_VIF_IOEMU)

    for idx, nic in enumerate(instance.nics):
      nic_args = {}
      nic_args["mac"] = "%s%s" % (nic.mac, nic_type_str)

      if nic.name and \
            nic.name.startswith(constants.INSTANCE_COMMUNICATION_NIC_PREFIX):
        tap = hv_base.GenerateTapName()
        nic_args["vifname"] = tap
        nic_args["script"] = pathutils.XEN_VIF_METAD_SETUP
        nic.name = tap
      else:
        ip = getattr(nic, "ip", None)
        if ip is not None:
          nic_args["ip"] = ip

        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
          nic_args["bridge"] = nic.nicparams[constants.NIC_LINK]
        elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_OVS:
          nic_args["bridge"] = nic.nicparams[constants.NIC_LINK]
          if nic.nicparams[constants.NIC_VLAN]:
            nic_args["bridge"] += nic.nicparams[constants.NIC_VLAN]

        if hvp[constants.HV_VIF_SCRIPT]:
          nic_args["script"] = hvp[constants.HV_VIF_SCRIPT]

      nic_str = ", ".join(["%s=%s" % p for p in nic_args.items()])
      vif_data.append("'%s'" % (nic_str, ))
      self._WriteNICInfoFile(instance, idx, nic)

    config.write("vif = [%s]\n" % ",".join(vif_data))

  def _WriteConfigFile(self, instance_name, data):
    """Write the Xen config file for the instance.

    This version of the function just writes the config file from static data.

    """
    # just in case it exists
    utils.RemoveFile(utils.PathJoin(self._cfgdir, "auto", instance_name))

    cfg_file = self._ConfigFileName(instance_name)
    try:
      utils.WriteFile(cfg_file, data=data)
    except EnvironmentError, err:
      raise errors.HypervisorError("Cannot write Xen instance configuration"
                                   " file %s: %s" % (cfg_file, err))

  def _ReadConfigFile(self, instance_name):
    """Returns the contents of the instance config file.

    """
    filename = self._ConfigFileName(instance_name)

    try:
      file_content = utils.ReadFile(filename)
    except EnvironmentError, err:
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)

    return file_content

  def _RemoveConfigFile(self, instance_name):
    """Remove the xen configuration file.

    """
    utils.RemoveFile(self._ConfigFileName(instance_name))
    try:
      shutil.rmtree(self._InstanceNICDir(instance_name))
    except OSError, err:
      if err.errno != errno.ENOENT:
        raise

  def _StashConfigFile(self, instance_name):
    """Move the Xen config file to the log directory and return its new path.

    """
    old_filename = self._ConfigFileName(instance_name)
    base = ("%s-%s" %
            (instance_name, utils.TimestampForFilename()))
    new_filename = utils.PathJoin(pathutils.LOG_XEN_DIR, base)
    utils.RenameFile(old_filename, new_filename)
    return new_filename

  def _GetInstanceList(self, include_node, hvparams):
    """Wrapper around module level L{_GetAllInstanceList}.

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

    """
    return _GetAllInstanceList(lambda: self._RunXen(["list"], hvparams),
                               include_node, delays=self._INSTANCE_LIST_DELAYS,
                               timeout=self._INSTANCE_LIST_TIMEOUT)

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

    @type hvparams: dict of strings
    @param hvparams: the instance's hypervisor params

    @rtype: list of strings
    @return: names of running instances

    """
    instance_list = _GetRunningInstanceList(
      lambda: self._RunXen(["list"], hvparams),
      False, delays=self._INSTANCE_LIST_DELAYS,
      timeout=self._INSTANCE_LIST_TIMEOUT)
    return [info[0] for info in instance_list]

  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: the instance's hypervisor params

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

    """
    instance_list = self._GetInstanceList(instance_name == _DOM0_NAME, hvparams)
    result = None
    for data in instance_list:
      if data[0] == instance_name:
        result = data
        break
    return result

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

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

    @rtype: (string, string, int, int, HypervisorInstanceState, int)
    @return: list of tuples (name, id, memory, vcpus, state, times)

    """
    return self._GetInstanceList(False, hvparams)

  def _MakeConfigFile(self, instance, startup_memory, block_devices):
    """Gather configuration details and write to disk.

    See L{_GetConfig} for arguments.

    """
    buf = StringIO()
    buf.write("# Automatically generated by Ganeti. Do not edit!\n")
    buf.write("\n")
    buf.write(self._GetConfig(instance, startup_memory, block_devices))
    buf.write("\n")

    self._WriteConfigFile(instance.name, buf.getvalue())

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

    """
    startup_memory = self._InstanceStartupMemory(instance)

    self._MakeConfigFile(instance, startup_memory, block_devices)

    cmd = ["create"]
    if startup_paused:
      cmd.append("-p")
    cmd.append(self._ConfigFileName(instance.name))

    result = self._RunXen(cmd, instance.hvparams)
    if result.failed:
      # Move the Xen configuration file to the log directory to avoid
      # leaving a stale config file behind.
      stashed_config = self._StashConfigFile(instance.name)
      raise errors.HypervisorError("Failed to start instance %s: %s (%s). Moved"
                                   " config file to %s" %
                                   (instance.name, result.fail_reason,
                                    result.output, stashed_config))

    for nic_seq, nic in enumerate(instance.nics):
      if nic.name and nic.name.startswith("gnt.com."):
        _ConfigureNIC(instance, nic_seq, nic, nic.name)

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

    A soft shutdown can be interrupted. A hard shutdown tries forever.

    """
    assert(timeout is None or force is not None)

    if name is None:
      name = instance.name

    return self._StopInstance(name, force, instance.hvparams, timeout)

  def _ShutdownInstance(self, name, hvparams, timeout):
    """Shutdown an instance if the instance is running.

    The '-w' flag waits for shutdown to complete which avoids the need
    to poll in the case where we want to destroy the domain
    immediately after shutdown.

    @type name: string
    @param name: name of the instance to stop
    @type hvparams: dict of string
    @param hvparams: hypervisor parameters of the instance
    @type timeout: int or None
    @param timeout: a timeout after which the shutdown command should be killed,
                    or None for no timeout

    """
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)

    if instance_info is None or _IsInstanceShutdown(instance_info[4]):
      logging.info("Failed to shutdown instance %s, not running", name)
      return None

    return self._RunXen(["shutdown", "-w", name], hvparams, timeout)

  def _DestroyInstance(self, name, hvparams):
    """Destroy an instance if the instance if the instance exists.

    @type name: string
    @param name: name of the instance to destroy
    @type hvparams: dict of string
    @param hvparams: hypervisor parameters of the instance

    """
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)

    if instance_info is None:
      logging.info("Failed to destroy instance %s, does not exist", name)
      return None

    return self._RunXen(["destroy", name], hvparams)

  # Destroy a domain only if necessary
  #
  # This method checks if the domain has already been destroyed before
  # issuing the 'destroy' command.  This step is necessary to handle
  # domains created by other versions of Ganeti.  For example, an
  # instance created with 2.10 will be destroy by the
  # '_ShutdownInstance', thus not requiring an additional destroy,
  # which would cause an error if issued.  See issue 619.
  def _DestroyInstanceIfAlive(self, name, hvparams):
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)

    if instance_info is None:
      raise errors.HypervisorError("Failed to destroy instance %s, already"
                                   " destroyed" % name)
    else:
      self._DestroyInstance(name, hvparams)

  def _StopInstance(self, name, force, hvparams, timeout):
    """Stop an instance.

    @type name: string
    @param name: name of the instance to destroy

    @type force: boolean
    @param force: whether to do a "hard" stop (destroy)

    @type hvparams: dict of string
    @param hvparams: hypervisor parameters of the instance

    @type timeout: int or None
    @param timeout: a timeout after which the shutdown command should be killed,
                    or None for no timeout

    """
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)

    if instance_info is None:
      raise errors.HypervisorError("Failed to shutdown instance %s,"
                                   " not running" % name)

    if not force:
      self._ShutdownInstance(name, hvparams, timeout)

    # TODO: Xen does always destroy the instnace after trying a gracefull
    # shutdown. That means doing another attempt with force=True will not make
    # any difference. This differs in behaviour from other hypervisors and
    # should be cleaned up.
    result = self._DestroyInstanceIfAlive(name, hvparams)
    if result is not None and result.failed and \
          self.GetInstanceInfo(name, hvparams=hvparams) is not None:
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
                                   (name, result.fail_reason, result.output))

    # Remove configuration file if stopping/starting instance was successful
    self._RemoveConfigFile(name)

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

    """
    ini_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)

    if ini_info is None:
      raise errors.HypervisorError("Failed to reboot instance %s,"
                                   " not running" % instance.name)

    result = self._RunXen(["reboot", instance.name], instance.hvparams)
    if result.failed:
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
                                   (instance.name, result.fail_reason,
                                    result.output))

    def _CheckInstance():
      new_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)

      # check if the domain ID has changed or the run time has decreased
      if (new_info is not None and
          (new_info[1] != ini_info[1] or new_info[5] < ini_info[5])):
        return

      raise utils.RetryAgain()

    try:
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
    except utils.RetryTimeout:
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
                                   " did not reboot in the expected interval" %
                                   (instance.name, ))

  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

    """
    result = self._RunXen(["mem-set", instance.name, mem], instance.hvparams)
    if result.failed:
      raise errors.HypervisorError("Failed to balloon instance %s: %s (%s)" %
                                   (instance.name, result.fail_reason,
                                    result.output))

    # Update configuration file
    cmd = ["sed", "-ie", "s/^memory.*$/memory = %s/" % mem]
    cmd.append(self._ConfigFileName(instance.name))

    result = utils.RunCmd(cmd)
    if result.failed:
      raise errors.HypervisorError("Failed to update memory for %s: %s (%s)" %
                                   (instance.name, result.fail_reason,
                                    result.output))

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

    @see: L{_GetNodeInfo} and L{_ParseNodeInfo}

    """
    result = self._RunXen(["info"], hvparams)
    if result.failed:
      logging.error("Can't retrieve xen hypervisor information (%s): %s",
                    result.fail_reason, result.output)
      return None

    instance_list = self._GetInstanceList(True, hvparams)
    return _GetNodeInfo(result.stdout, instance_list)

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

    """
    xen_cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
    ndparams = node_group.FillND(primary_node)
    return objects.InstanceConsole(instance=instance.name,
                                   kind=constants.CONS_SSH,
                                   host=primary_node.name,
                                   port=ndparams.get(constants.ND_SSH_PORT),
                                   user=constants.SSH_CONSOLE_USER,
                                   command=[pathutils.XEN_CONSOLE_WRAPPER,
                                            xen_cmd, instance.name])

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

    For Xen, this verifies that the xend process is running.

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

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

    """
    if hvparams is None:
      return "Could not verify the hypervisor, because no hvparams were" \
             " provided."

    if constants.HV_XEN_CMD in hvparams:
      xen_cmd = hvparams[constants.HV_XEN_CMD]
      try:
        self._CheckToolstack(xen_cmd)
      except errors.HypervisorError:
        return "The configured xen toolstack '%s' is not available on this" \
               " node." % xen_cmd

    result = self._RunXen(["info"], hvparams)
    if result.failed:
      return "Retrieving information from xen failed: %s, %s" % \
        (result.fail_reason, result.output)

    return None

  def MigrationInfo(self, instance):
    """Get instance information to perform a migration.

    @type instance: L{objects.Instance}
    @param instance: instance to be migrated
    @rtype: string
    @return: content of the xen config file

    """
    return self._ReadConfigFile(instance.name)

  def _UseMigrationDaemon(self, hvparams):
    """Whether to start a socat daemon when accepting an instance.

    @rtype: bool

    """
    return self._GetCommand(hvparams) == constants.XEN_CMD_XL

  @classmethod
  def _KillMigrationDaemon(cls, instance):
    """Kills the migration daemon if present.

    """
    pidfile = cls._InstanceMigrationPidfile(instance.name)
    read_pid = utils.ReadPidFile(pidfile)

    # There is no pidfile, hence nothing for us to do
    if read_pid == 0:
      return

    if utils.IsProcessAlive(read_pid):
      # If the process is alive, let's make sure we are killing the right one
      cmdline = ' '.join(utils.GetProcCmdline(read_pid))
      if cmdline.count("xl migrate-receive") > 0:
        utils.KillProcess(read_pid)

    # By this point the process is not running, whether killed or initially
    # nonexistent, so it is safe to remove the pidfile.
    utils.RemoveFile(pidfile)

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

    @type instance: L{objects.Instance}
    @param instance: instance to be accepted
    @type info: string
    @param info: content of the xen config file on the source node
    @type target: string
    @param target: target host (usually ip), on this node

    """
    if self._UseMigrationDaemon(instance.hvparams):
      port = instance.hvparams[constants.HV_MIGRATION_PORT]

      # Make sure there is somewhere to put the pidfile.
      XenHypervisor._EnsureDirs()
      pidfile = XenHypervisor._InstanceMigrationPidfile(instance.name)

      # And try and kill a previous daemon
      XenHypervisor._KillMigrationDaemon(instance)

      listening_arg = "TCP-LISTEN:%d,bind=%s,reuseaddr" % (port, target)
      socat_pid = utils.StartDaemon(["socat", "-b524288", listening_arg,
                                     "SYSTEM:'xl migrate-receive'"],
                                     pidfile=pidfile)

      # Wait for a while to make sure the socat process has successfully started
      # listening
      time.sleep(1)
      if not utils.IsProcessAlive(socat_pid):
        raise errors.HypervisorError("Could not start receiving socat process"
                                     " on port %d: check if port is available" %
                                     port)

  def FinalizeMigrationDst(self, instance, info, success):
    """Finalize an instance migration.

    After a successful migration we write the xen config file.
    We do nothing on a failure, as we did not change anything at accept time.

    @type instance: L{objects.Instance}
    @param instance: instance whose migration is being finalized
    @type info: string
    @param info: content of the xen config file on the source node
    @type success: boolean
    @param success: whether the migration was a success or a failure

    """
    if success:
      self._WriteConfigFile(instance.name, info)
    elif self._UseMigrationDaemon(instance.hvparams):
      XenHypervisor._KillMigrationDaemon(instance)

  def MigrateInstance(self, _cluster_name, instance, target, live):
    """Migrate an instance to a target node.

    The migration will not be attempted if the instance is not
    currently running.

    @type instance: L{objects.Instance}
    @param instance: the instance to be migrated
    @type target: string
    @param target: ip address of the target node
    @type live: boolean
    @param live: perform a live migration

    """
    port = instance.hvparams[constants.HV_MIGRATION_PORT]

    return self._MigrateInstance(instance.name, target, port, live,
                                 instance.hvparams)

  def _MigrateInstance(self, instance_name, target, port, live, hvparams,
                       _ping_fn=netutils.TcpPing):
    """Migrate an instance to a target node.

    @see: L{MigrateInstance} for details

    """
    if hvparams is None:
      raise errors.HypervisorError("No hvparams provided.")

    if self.GetInstanceInfo(instance_name, hvparams=hvparams) is None:
      raise errors.HypervisorError("Instance not running, cannot migrate")

    cmd = self._GetCommand(hvparams)

    args = ["migrate"]

    if cmd == constants.XEN_CMD_XM:
      # Try and see if xm is listening on the specified port
      if not _ping_fn(target, port, live_port_needed=True):
        raise errors.HypervisorError("Remote host %s not listening on port"
                                     " %s, cannot migrate" % (target, port))

      args.extend(["-p", "%d" % port])
      if live:
        args.append("-l")

    elif cmd == constants.XEN_CMD_XL:
      # Rather than using SSH, use socat as Ganeti cannot guarantee the presence
      # of usable SSH keys as of 2.13
      args.extend([
        "-s", constants.XL_SOCAT_CMD % (target, port),
        "-C", self._ConfigFileName(instance_name),
        ])

    else:
      raise errors.HypervisorError("Unsupported Xen command: %s" % cmd)

    args.extend([instance_name, target])

    result = self._RunXen(args, hvparams)
    if result.failed:
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
                                   (instance_name, result.output))

  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

    """
    # pylint: disable=W0613
    if success:
      # remove old xen file after migration succeeded
      try:
        self._RemoveConfigFile(instance.name)
      except EnvironmentError:
        logging.exception("Failure while removing instance config file")

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

    As MigrateInstance for Xen is still blocking, if this method is called it
    means that MigrateInstance has completed successfully. So we can safely
    assume that the migration was successful and notify this fact to the client.

    @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

    """
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)

  def PowercycleNode(self, hvparams=None):
    """Xen-specific powercycle.

    This first does a Linux reboot (which triggers automatically a Xen
    reboot), and if that fails it tries to do a Xen reboot. The reason
    we don't try a Xen reboot first is that the xen reboot launches an
    external command which connects to the Xen hypervisor, and that
    won't work in case the root filesystem is broken and/or the xend
    daemon is not working.

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

    """
    try:
      self.LinuxPowercycle()
    finally:
      xen_cmd = self._GetCommand(hvparams)
      utils.RunCmd([xen_cmd, "debug", "R"])

  def _CheckToolstack(self, xen_cmd):
    """Check whether the given toolstack is available on the node.

    @type xen_cmd: string
    @param xen_cmd: xen command (e.g. 'xm' or 'xl')

    """
    binary_found = self._CheckToolstackBinary(xen_cmd)
    if not binary_found:
      raise errors.HypervisorError("No '%s' binary found on node." % xen_cmd)
    elif xen_cmd == constants.XEN_CMD_XL:
      if not self._CheckToolstackXlConfigured():
        raise errors.HypervisorError("Toolstack '%s' is not enabled on this"
                                     "node." % xen_cmd)

  def _CheckToolstackBinary(self, xen_cmd):
    """Checks whether the xen command's binary is found on the machine.

    """
    if xen_cmd not in constants.KNOWN_XEN_COMMANDS:
      raise errors.HypervisorError("Unknown xen command '%s'." % xen_cmd)
    result = self._run_cmd_fn(["which", xen_cmd])
    return not result.failed

  def _CheckToolstackXlConfigured(self):
    """Checks whether xl is enabled on an xl-capable node.

    @rtype: bool
    @returns: C{True} if 'xl' is enabled, C{False} otherwise

    """
    result = self._run_cmd_fn([constants.XEN_CMD_XL, "help"])
    if not result.failed:
      return True
    elif result.failed:
      if "toolstack" in result.stderr:
        return False
      # xl fails for some other reason than the toolstack
      else:
        raise errors.HypervisorError("Cannot run xen ('%s'). Error: %s."
                                     % (constants.XEN_CMD_XL, result.stderr))


def WriteXenConfigEvents(config, hvp):
  config.write("on_poweroff = 'preserve'\n")
  if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
    config.write("on_reboot = 'restart'\n")
  else:
    config.write("on_reboot = 'destroy'\n")
  config.write("on_crash = 'restart'\n")


class XenPvmHypervisor(XenHypervisor):
  """Xen PVM hypervisor interface"""

  PARAMETERS = {
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
    constants.HV_REBOOT_BEHAVIOR:
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
    constants.HV_CPU_CAP: hv_base.OPT_NONNEGATIVE_INT_CHECK,
    constants.HV_CPU_WEIGHT:
      (False, lambda x: 0 < x < 65536, "invalid weight", None, None),
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
    constants.HV_XEN_CMD:
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
    constants.HV_XEN_CPUID: hv_base.NO_CHECK,
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
    }

  def _GetConfig(self, instance, startup_memory, block_devices):
    """Write the Xen config file for the instance.

    """
    hvp = instance.hvparams
    config = StringIO()
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")

    # if bootloader is True, use bootloader instead of kernel and ramdisk
    # parameters.
    if hvp[constants.HV_USE_BOOTLOADER]:
      # bootloader handling
      bootloader_path = hvp[constants.HV_BOOTLOADER_PATH]
      if bootloader_path:
        config.write("bootloader = '%s'\n" % bootloader_path)
      else:
        raise errors.HypervisorError("Bootloader enabled, but missing"
                                     " bootloader path")

      bootloader_args = hvp[constants.HV_BOOTLOADER_ARGS]
      if bootloader_args:
        config.write("bootargs = '%s'\n" % bootloader_args)
    else:
      # kernel handling
      kpath = hvp[constants.HV_KERNEL_PATH]
      config.write("kernel = '%s'\n" % kpath)

      # initrd handling
      initrd_path = hvp[constants.HV_INITRD_PATH]
      if initrd_path:
        config.write("ramdisk = '%s'\n" % initrd_path)

    # rest of the settings
    config.write("memory = %d\n" % startup_memory)
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
    if cpu_pinning:
      config.write("%s\n" % cpu_pinning)
    cpu_cap = hvp[constants.HV_CPU_CAP]
    if cpu_cap:
      config.write("cpu_cap=%d\n" % cpu_cap)
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
    if cpu_weight:
      config.write("cpu_weight=%d\n" % cpu_weight)

    config.write("name = '%s'\n" % instance.name)

    self._WriteNicConfig(config, instance, hvp)

    disk_data = \
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
    config.write("disk = [%s]\n" % ",".join(disk_data))

    if hvp[constants.HV_ROOT_PATH]:
      config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])

    WriteXenConfigEvents(config, hvp)
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])

    cpuid = hvp[constants.HV_XEN_CPUID]
    if cpuid:
      config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))

    if hvp[constants.HV_SOUNDHW]:
      config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])

    return config.getvalue()


class XenHvmHypervisor(XenHypervisor):
  """Xen HVM hypervisor interface"""

  ANCILLARY_FILES = XenHypervisor.ANCILLARY_FILES + [
    pathutils.VNC_PASSWORD_FILE,
    ]
  ANCILLARY_FILES_OPT = XenHypervisor.ANCILLARY_FILES_OPT + [
    pathutils.VNC_PASSWORD_FILE,
    ]

  PARAMETERS = {
    constants.HV_ACPI: hv_base.NO_CHECK,
    constants.HV_BOOT_ORDER: (True, ) +
      (lambda x: x and len(x.strip("acdn")) == 0,
       "Invalid boot order specified, must be one or more of [acdn]",
       None, None),
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
    constants.HV_DISK_TYPE:
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_DISK_TYPES),
    constants.HV_NIC_TYPE:
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_NIC_TYPES),
    constants.HV_PAE: hv_base.NO_CHECK,
    constants.HV_VNC_BIND_ADDRESS:
      (False, netutils.IP4Address.IsValid,
       "VNC bind address is not a valid IP address", None, None),
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
    constants.HV_DEVICE_MODEL: hv_base.REQ_FILE_CHECK,
    constants.HV_VNC_PASSWORD_FILE: hv_base.REQ_FILE_CHECK,
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
    # Add PCI passthrough
    constants.HV_PASSTHROUGH: hv_base.NO_CHECK,
    constants.HV_REBOOT_BEHAVIOR:
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
    constants.HV_CPU_CAP: hv_base.NO_CHECK,
    constants.HV_CPU_WEIGHT:
      (False, lambda x: 0 < x < 65535, "invalid weight", None, None),
    constants.HV_VIF_TYPE:
      hv_base.ParamInSet(False, constants.HT_HVM_VALID_VIF_TYPES),
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
    constants.HV_VIRIDIAN: hv_base.NO_CHECK,
    constants.HV_XEN_CMD:
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
    constants.HV_XEN_CPUID: hv_base.NO_CHECK,
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
    }

  def _GetConfig(self, instance, startup_memory, block_devices):
    """Create a Xen 3.1 HVM config file.

    """
    hvp = instance.hvparams

    config = StringIO()

    # kernel handling
    kpath = hvp[constants.HV_KERNEL_PATH]
    config.write("kernel = '%s'\n" % kpath)

    config.write("builder = 'hvm'\n")
    config.write("memory = %d\n" % startup_memory)
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
    if cpu_pinning:
      config.write("%s\n" % cpu_pinning)
    cpu_cap = hvp[constants.HV_CPU_CAP]
    if cpu_cap:
      config.write("cpu_cap=%d\n" % cpu_cap)
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
    if cpu_weight:
      config.write("cpu_weight=%d\n" % cpu_weight)

    config.write("name = '%s'\n" % instance.name)
    if hvp[constants.HV_PAE]:
      config.write("pae = 1\n")
    else:
      config.write("pae = 0\n")
    if hvp[constants.HV_ACPI]:
      config.write("acpi = 1\n")
    else:
      config.write("acpi = 0\n")
    if hvp[constants.HV_VIRIDIAN]:
      config.write("viridian = 1\n")
    else:
      config.write("viridian = 0\n")

    config.write("apic = 1\n")
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
    config.write("sdl = 0\n")
    config.write("usb = 1\n")
    config.write("usbdevice = 'tablet'\n")
    config.write("vnc = 1\n")
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
    else:
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])

    if instance.network_port > constants.VNC_BASE_PORT:
      display = instance.network_port - constants.VNC_BASE_PORT
      config.write("vncdisplay = %s\n" % display)
      config.write("vncunused = 0\n")
    else:
      config.write("# vncdisplay = 1\n")
      config.write("vncunused = 1\n")

    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
    try:
      password = utils.ReadFile(vnc_pwd_file)
    except EnvironmentError, err:
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
                                   (vnc_pwd_file, err))

    config.write("vncpasswd = '%s'\n" % password.rstrip())

    config.write("serial = 'pty'\n")
    if hvp[constants.HV_USE_LOCALTIME]:
      config.write("localtime = 1\n")

    self._WriteNicConfig(config, instance, hvp)

    disk_data = \
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])

    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
    if iso_path:
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
      disk_data.append(iso)

    config.write("disk = [%s]\n" % (",".join(disk_data)))
    # Add PCI passthrough
    pci_pass_arr = []
    pci_pass = hvp[constants.HV_PASSTHROUGH]
    if pci_pass:
      pci_pass_arr = pci_pass.split(";")
      config.write("pci = %s\n" % pci_pass_arr)

    WriteXenConfigEvents(config, hvp)

    cpuid = hvp[constants.HV_XEN_CPUID]
    if cpuid:
      config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))

    if hvp[constants.HV_SOUNDHW]:
      config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])

    return config.getvalue()
