#
#

# 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 map(lambda x: x + suffix, 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) = map(lambda s: s.strip(), 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()
