#
#

# Copyright (C) 2010, 2013, 2014, 2015 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.


"""LXC hypervisor

"""

import errno
import os
import os.path
import logging
import sys
import re

from ganeti import constants
from ganeti import errors # pylint: disable=W0611
from ganeti import utils
from ganeti import objects
from ganeti import pathutils
from ganeti import serializer
from ganeti.hypervisor import hv_base
from ganeti.errors import HypervisorError


def _CreateBlankFile(path, mode):
  """Create blank file.

  Create a blank file for the path with specified mode.
  An existing file will be overwritten.

  """
  try:
    utils.WriteFile(path, data="", mode=mode)
  except EnvironmentError, err:
    raise HypervisorError("Failed to create file %s: %s" % (path, err))


class LXCVersion(tuple): # pylint: disable=R0924
  """LXC version class.

  """
  # Let beta version following micro version, but don't care about it
  _VERSION_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)")

  @classmethod
  def _Parse(cls, version_string):
    """Parse a passed string as an LXC version string.

    @param version_string: a valid LXC version string
    @type version_string: string
    @raise ValueError: if version_string is an invalid LXC version string
    @rtype tuple(int, int, int)
    @return (major_num, minor_num, micro_num)

    """
    match = cls._VERSION_RE.match(version_string)
    if match:
      return tuple(map(int, match.groups()))
    else:
      raise ValueError("'%s' is not a valid LXC version string" %
                       version_string)

  def __new__(cls, version_string):
    version = super(LXCVersion, cls).__new__(cls, cls._Parse(version_string))
    version.original_string = version_string
    return version

  def __str__(self):
    return self.original_string


class LXCHypervisor(hv_base.BaseHypervisor):
  """LXC-based virtualization.

  """
  _ROOT_DIR = pathutils.RUN_DIR + "/lxc"
  _LOG_DIR = pathutils.LOG_DIR + "/lxc"

  # The instance directory has to be structured in a way that would allow it to
  # be passed as an argument of the --lxcpath option in lxc- commands.
  # This means that:
  # Each LXC instance should have a directory carrying their name under this
  # directory.
  # Each instance directory should contain the "config" file that contains the
  # LXC container configuration of an instance.
  #
  # Therefore the structure of the directory tree should be:
  #
  #   _INSTANCE_DIR
  #   \_ instance1
  #      \_ config
  #   \_ instance2
  #      \_ config
  #
  # Other instance specific files can also be placed under an instance
  # directory.
  _INSTANCE_DIR = _ROOT_DIR + "/instance"

  _CGROUP_ROOT_DIR = _ROOT_DIR + "/cgroup"
  _PROC_CGROUPS_FILE = "/proc/cgroups"
  _PROC_SELF_CGROUP_FILE = "/proc/self/cgroup"

  _LXC_MIN_VERSION_REQUIRED = LXCVersion("1.0.0")
  _LXC_COMMANDS_REQUIRED = [
    "lxc-console",
    "lxc-ls",
    "lxc-start",
    "lxc-stop",
    "lxc-wait",
    ]

  _DIR_MODE = 0755
  _STASH_KEY_ALLOCATED_LOOP_DEV = "allocated_loopdev"

  _MEMORY_PARAMETER = "memory.limit_in_bytes"
  _MEMORY_SWAP_PARAMETER = "memory.memsw.limit_in_bytes"

  PARAMETERS = {
    constants.HV_CPU_MASK: hv_base.OPT_CPU_MASK_CHECK,
    constants.HV_LXC_DEVICES: hv_base.NO_CHECK,
    constants.HV_LXC_DROP_CAPABILITIES: hv_base.NO_CHECK,
    constants.HV_LXC_EXTRA_CGROUPS: hv_base.NO_CHECK,
    constants.HV_LXC_EXTRA_CONFIG: hv_base.NO_CHECK,
    constants.HV_LXC_NUM_TTYS: hv_base.REQ_NONNEGATIVE_INT_CHECK,
    constants.HV_LXC_STARTUP_TIMEOUT: hv_base.OPT_NONNEGATIVE_INT_CHECK,
    }

  _REBOOT_TIMEOUT = 120 # secs
  _REQUIRED_CGROUP_SUBSYSTEMS = [
    "cpuset",
    "memory",
    "devices",
    "cpuacct",
    ]

  def __init__(self):
    hv_base.BaseHypervisor.__init__(self)
    self._EnsureDirectoryExistence()

  @classmethod
  def _InstanceDir(cls, instance_name):
    """Return the root directory for an instance.

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

  @classmethod
  def _InstanceConfFilePath(cls, instance_name):
    """Return the configuration file for an instance.

    """
    return utils.PathJoin(cls._InstanceDir(instance_name), "config")

  @classmethod
  def _InstanceLogFilePath(cls, instance):
    """Return the log file for an instance.

    @type instance: L{objects.Instance}

    """
    filename = "%s.%s.log" % (instance.name, instance.uuid)
    return utils.PathJoin(cls._LOG_DIR, filename)

  @classmethod
  def _InstanceConsoleLogFilePath(cls, instance_name):
    """Return the console log file path for an instance.

    """
    return utils.PathJoin(cls._InstanceDir(instance_name), "console.log")

  @classmethod
  def _InstanceStashFilePath(cls, instance_name):
    """Return the stash file path for an instance.

    The stash file is used to keep information needed to clean up after the
    destruction of the instance.

    """
    return utils.PathJoin(cls._InstanceDir(instance_name), "stash")

  def _EnsureDirectoryExistence(self):
    """Ensures all the directories needed for LXC use exist.

    """
    utils.EnsureDirs([
      (self._ROOT_DIR, self._DIR_MODE),
      (self._LOG_DIR, 0750),
      (self._INSTANCE_DIR, 0750),
      ])

  def _SaveInstanceStash(self, instance_name, data):
    """Save data to the instance stash file in serialized format.

    """
    stash_file = self._InstanceStashFilePath(instance_name)
    serialized = serializer.Dump(data)
    try:
      utils.WriteFile(stash_file, data=serialized,
                      mode=constants.SECURE_FILE_MODE)
    except EnvironmentError, err:
      raise HypervisorError("Failed to save instance stash file %s : %s" %
                            (stash_file, err))

  def _LoadInstanceStash(self, instance_name):
    """Load information stashed in file which was created by
    L{_SaveInstanceStash}.

    """
    stash_file = self._InstanceStashFilePath(instance_name)
    try:
      return serializer.Load(utils.ReadFile(stash_file))
    except (EnvironmentError, ValueError), err:
      raise HypervisorError("Failed to load instance stash file %s : %s" %
                            (stash_file, err))

  @classmethod
  def _MountCgroupSubsystem(cls, subsystem):
    """Mount the cgroup subsystem fs under the cgroup root dir.

    @type subsystem: string
    @param subsystem: cgroup subsystem name to mount
    @rtype string
    @return path of subsystem mount point

    """
    subsys_dir = utils.PathJoin(cls._GetCgroupMountPoint(), subsystem)
    if not os.path.isdir(subsys_dir):
      try:
        os.makedirs(subsys_dir)
      except EnvironmentError, err:
        raise HypervisorError("Failed to create directory %s: %s" %
                              (subsys_dir, err))

    mount_cmd = ["mount", "-t", "cgroup", "-o", subsystem, subsystem,
                 subsys_dir]
    result = utils.RunCmd(mount_cmd)
    if result.failed:
      raise HypervisorError("Failed to mount cgroup subsystem '%s': %s" %
                            (subsystem, result.output))

    return subsys_dir

  def _CleanupInstance(self, instance_name, stash):
    """Actual implementation of the instance cleanup procedure.

    @type instance_name: string
    @param instance_name: instance name
    @type stash: dict(string:any)
    @param stash: dict that contains desired information for instance cleanup

    """
    try:
      if self._STASH_KEY_ALLOCATED_LOOP_DEV in stash:
        loop_dev_path = stash[self._STASH_KEY_ALLOCATED_LOOP_DEV]
        utils.ReleaseBdevPartitionMapping(loop_dev_path)
    except errors.CommandError, err:
      raise HypervisorError("Failed to cleanup partition mapping : %s" % err)

    utils.RemoveFile(self._InstanceStashFilePath(instance_name))

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

    """
    stash = self._LoadInstanceStash(instance_name)
    self._CleanupInstance(instance_name, stash)

  @classmethod
  def _GetCgroupMountPoint(cls):
    """Return the directory that should be the base of cgroup fs.

    """
    return cls._CGROUP_ROOT_DIR

  @classmethod
  def _GetOrPrepareCgroupSubsysMountPoint(cls, subsystem):
    """Prepare cgroup subsystem mount point.

    @type subsystem: string
    @param subsystem: cgroup subsystem name to mount
    @rtype string
    @return path of subsystem mount point

    """
    for _, mpoint, fstype, options in utils.GetMounts():
      if fstype == "cgroup" and subsystem in options.split(","):
        return mpoint

    return cls._MountCgroupSubsystem(subsystem)

  @classmethod
  def _GetCurrentCgroupSubsysGroups(cls):
    """Return the dict of cgroup subsystem hierarchies this process belongs to.

    The dictionary has the cgroup subsystem as a key and its hierarchy as a
    value.
    Information is read from /proc/self/cgroup.

    """
    try:
      cgroup_list = utils.ReadFile(cls._PROC_SELF_CGROUP_FILE)
    except EnvironmentError, err:
      raise HypervisorError("Failed to read %s : %s" %
                            (cls._PROC_SELF_CGROUP_FILE, err))

    cgroups = {}
    for line in filter(None, cgroup_list.split("\n")):
      _, subsystems, hierarchy = line.split(":")
      for subsys in subsystems.split(","):
        cgroups[subsys] = hierarchy[1:] # discard first '/'

    return cgroups

  @classmethod
  def _GetCgroupSubsysDir(cls, subsystem):
    """Return the directory of the cgroup subsystem we use.

    @type subsystem: string
    @param subsystem: cgroup subsystem name
    @rtype: string
    @return: path of the hierarchy directory for the subsystem

    """
    subsys_dir = cls._GetOrPrepareCgroupSubsysMountPoint(subsystem)
    base_group = cls._GetCurrentCgroupSubsysGroups().get(subsystem, "")

    return utils.PathJoin(subsys_dir, base_group, "lxc")

  @classmethod
  def _GetCgroupParamPath(cls, param_name, instance_name=None):
    """Return the path of the specified cgroup parameter file.

    @type param_name: string
    @param param_name: cgroup subsystem parameter name
    @rtype: string
    @return: path of the cgroup subsystem parameter file

    """
    subsystem = param_name.split(".", 1)[0]
    subsys_dir = cls._GetCgroupSubsysDir(subsystem)
    if instance_name is not None:
      return utils.PathJoin(subsys_dir, instance_name, param_name)
    else:
      return utils.PathJoin(subsys_dir, param_name)

  @classmethod
  def _GetCgroupInstanceValue(cls, instance_name, param_name):
    """Return the value of the specified cgroup parameter.

    @type instance_name: string
    @param instance_name: instance name
    @type param_name: string
    @param param_name: cgroup subsystem parameter name
    @rtype string
    @return value read from cgroup subsystem fs

    """
    param_path = cls._GetCgroupParamPath(param_name,
                                         instance_name=instance_name)
    return utils.ReadFile(param_path).rstrip("\n")

  @classmethod
  def _SetCgroupInstanceValue(cls, instance_name, param_name, param_value):
    """Set the value to the specified instance cgroup parameter.

    @type instance_name: string
    @param instance_name: instance name
    @type param_name: string
    @param param_name: cgroup subsystem parameter name
    @type param_value: string
    @param param_value: cgroup subsystem parameter value to be set

    """
    param_path = cls._GetCgroupParamPath(param_name,
                                         instance_name=instance_name)
    # When interacting with cgroup fs, errno is quite important information
    # to see what happened when setting a cgroup parameter, so just throw
    # an error to the upper level.
    # e.g., we could know that the container can't reclaim its memory by
    #       checking if the errno is EBUSY when setting the
    #       memory.memsw.limit_in_bytes.
    fd = -1
    try:
      fd = os.open(param_path, os.O_WRONLY)
      os.write(fd, param_value)
    finally:
      if fd != -1:
        os.close(fd)

  @classmethod
  def _IsCgroupParameterPresent(cls, parameter, hvparams=None):
    """Return whether a cgroup parameter can be used.

    This is checked by seeing whether there is a file representation of the
    parameter in the location where the cgroup is mounted.

    @type parameter: string
    @param parameter: The name of the parameter.
    @param hvparams: dict
    @param hvparams: The hypervisor parameters, optional.
    @rtype: boolean

    """
    cls._EnsureCgroupMounts(hvparams)
    param_path = cls._GetCgroupParamPath(parameter)

    return os.path.exists(param_path)

  @classmethod
  def _GetCgroupCpuList(cls, instance_name):
    """Return the list of CPU ids for an instance.

    """
    try:
      cpumask = cls._GetCgroupInstanceValue(instance_name, "cpuset.cpus")
    except EnvironmentError, err:
      raise errors.HypervisorError("Getting CPU list for instance"
                                   " %s failed: %s" % (instance_name, err))

    return utils.ParseCpuMask(cpumask)

  @classmethod
  def _GetCgroupCpuUsage(cls, instance_name):
    """Return the CPU usage of an instance.

    """
    try:
      cputime_ns = cls._GetCgroupInstanceValue(instance_name, "cpuacct.usage")
    except EnvironmentError, err:
      raise HypervisorError("Failed to get the cpu usage of %s: %s" %
                            (instance_name, err))

    return float(cputime_ns) / 10 ** 9 # nano secs to float secs

  @classmethod
  def _GetCgroupMemoryLimit(cls, instance_name):
    """Return the memory limit for an instance

    """
    try:
      mem_limit = cls._GetCgroupInstanceValue(instance_name,
                                              "memory.limit_in_bytes")
      return int(mem_limit)
    except EnvironmentError, err:
      raise HypervisorError("Can't get instance memory limit of %s: %s" %
                            (instance_name, err))

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

    """
    return self._ListAliveInstances()

  @classmethod
  def _IsInstanceAlive(cls, instance_name):
    """Return True if instance is alive.

    """
    result = utils.RunCmd(["lxc-ls", "--running", re.escape(instance_name)])
    if result.failed:
      raise HypervisorError("Failed to get running LXC containers list: %s" %
                            result.output)

    return instance_name in result.stdout.split()

  @classmethod
  def _ListAliveInstances(cls):
    """Return list of alive instances.

    """
    result = utils.RunCmd(["lxc-ls", "--running"])
    if result.failed:
      raise HypervisorError("Failed to get running LXC containers list: %s" %
                            result.output)

    return result.stdout.split()

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

    @type instance_name: string
    @param instance_name: the instance name
    @type hvparams: dict of strings
    @param hvparams: hvparams to be used with this instance
    @rtype: tuple of strings
    @return: (name, id, memory, vcpus, stat, times)

    """
    if not self._IsInstanceAlive(instance_name):
      return None

    return self._GetInstanceInfoInner(instance_name)

  def _GetInstanceInfoInner(self, instance_name):
    """Get instance properties.

    @type instance_name: string
    @param instance_name: the instance name
    @rtype: tuple of strings
    @return: (name, id, memory, vcpus, stat, times)

    """

    cpu_list = self._GetCgroupCpuList(instance_name)
    memory = self._GetCgroupMemoryLimit(instance_name) / (1024 ** 2)
    cputime = self._GetCgroupCpuUsage(instance_name)
    return (instance_name, 0, memory, len(cpu_list),
            hv_base.HvInstanceState.RUNNING, cputime)

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

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

    """
    data = []
    running_instances = self._ListAliveInstances()
    filter_fn = lambda x: os.path.isdir(utils.PathJoin(self._INSTANCE_DIR, x))
    for dirname in filter(filter_fn, os.listdir(self._INSTANCE_DIR)):
      if dirname not in running_instances:
        continue
      try:
        info = self._GetInstanceInfoInner(dirname)
      except errors.HypervisorError:
        continue
      if info:
        data.append(info)
    return data

  @classmethod
  def _GetInstanceDropCapabilities(cls, hvparams):
    """Get and parse the drop capabilities list from the instance hvparams.

    @type hvparams: dict of strings
    @param hvparams: instance hvparams
    @rtype list(string)
    @return list of drop capabilities

    """
    drop_caps = hvparams[constants.HV_LXC_DROP_CAPABILITIES]
    return drop_caps.split(",")

  def _CreateConfigFile(self, instance, sda_dev_path):
    """Create an lxc.conf file for an instance.

    """
    out = []
    # hostname
    out.append("lxc.utsname = %s" % instance.name)

    # separate pseudo-TTY instances
    out.append("lxc.pts = 255")
    # standard TTYs
    num_ttys = instance.hvparams[constants.HV_LXC_NUM_TTYS]
    if num_ttys: # if it is the number greater than 0
      out.append("lxc.tty = %s" % num_ttys)

    # console log file
    # After the following patch was applied, we lost the console log file output
    # until the lxc.console.logfile parameter was introduced in 1.0.6.
    # https://
    # lists.linuxcontainers.org/pipermail/lxc-devel/2014-March/008470.html
    lxc_version = self._GetLXCVersionFromCmd("lxc-start")
    if lxc_version >= LXCVersion("1.0.6"):
      console_log_path = self._InstanceConsoleLogFilePath(instance.name)
      _CreateBlankFile(console_log_path, constants.SECURE_FILE_MODE)
      out.append("lxc.console.logfile = %s" % console_log_path)
    else:
      logging.warn("Console log file is not supported in LXC version %s,"
                   " disabling.", lxc_version)

    # root FS
    out.append("lxc.rootfs = %s" % sda_dev_path)

    # Necessary file systems
    out.append("lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0")
    out.append("lxc.mount.entry = sysfs sys sysfs defaults 0 0")

    # CPUs
    if instance.hvparams[constants.HV_CPU_MASK]:
      cpu_list = utils.ParseCpuMask(instance.hvparams[constants.HV_CPU_MASK])
      cpus_in_mask = len(cpu_list)
      if cpus_in_mask != instance.beparams["vcpus"]:
        raise errors.HypervisorError("Number of VCPUs (%d) doesn't match"
                                     " the number of CPUs in the"
                                     " cpu_mask (%d)" %
                                     (instance.beparams["vcpus"],
                                      cpus_in_mask))
      out.append("lxc.cgroup.cpuset.cpus = %s" %
                 instance.hvparams[constants.HV_CPU_MASK])

    # Memory
    out.append("lxc.cgroup.memory.limit_in_bytes = %dM" %
               instance.beparams[constants.BE_MAXMEM])
    if LXCHypervisor._IsCgroupParameterPresent(self._MEMORY_SWAP_PARAMETER,
                                               instance.hvparams):
      out.append("lxc.cgroup.memory.memsw.limit_in_bytes = %dM" %
                 instance.beparams[constants.BE_MAXMEM])

    # Device control
    # deny direct device access
    out.append("lxc.cgroup.devices.deny = a")
    dev_specs = instance.hvparams[constants.HV_LXC_DEVICES]
    for dev_spec in dev_specs.split(","):
      out.append("lxc.cgroup.devices.allow = %s" % dev_spec)

    # Networking
    for idx, nic in enumerate(instance.nics):
      out.append("# NIC %d" % idx)
      mode = nic.nicparams[constants.NIC_MODE]
      link = nic.nicparams[constants.NIC_LINK]
      if mode == constants.NIC_MODE_BRIDGED:
        out.append("lxc.network.type = veth")
        out.append("lxc.network.link = %s" % link)
      else:
        raise errors.HypervisorError("LXC hypervisor only supports"
                                     " bridged mode (NIC %d has mode %s)" %
                                     (idx, mode))
      out.append("lxc.network.hwaddr = %s" % nic.mac)
      out.append("lxc.network.flags = up")

    # Capabilities
    for cap in self._GetInstanceDropCapabilities(instance.hvparams):
      out.append("lxc.cap.drop = %s" % cap)

    # Extra config
    # TODO: Currently a configuration parameter that includes comma
    # in its value can't be added via this parameter.
    # Make this parameter able to read from a file once the
    # "parameter from a file" feature added.
    extra_configs = instance.hvparams[constants.HV_LXC_EXTRA_CONFIG]
    if extra_configs:
      out.append("# User defined configs")
      out.extend(extra_configs.split(","))

    return "\n".join(out) + "\n"

  @classmethod
  def _GetCgroupEnabledKernelSubsystems(cls):
    """Return cgroup subsystems list that are enabled in current kernel.

    """
    try:
      subsys_table = utils.ReadFile(cls._PROC_CGROUPS_FILE)
    except EnvironmentError, err:
      raise HypervisorError("Failed to read cgroup info from %s: %s"
                            % (cls._PROC_CGROUPS_FILE, err))
    return [x.split(None, 1)[0] for x in subsys_table.split("\n")
            if x and not x.startswith("#")]

  @classmethod
  def _EnsureCgroupMounts(cls, hvparams=None):
    """Ensures all cgroup subsystems required to run LXC container are mounted.

    """
    # Check cgroup subsystems required by the Ganeti LXC hypervisor
    for subsystem in cls._REQUIRED_CGROUP_SUBSYSTEMS:
      cls._GetOrPrepareCgroupSubsysMountPoint(subsystem)

    # Check cgroup subsystems required by the LXC
    if hvparams is None or not hvparams[constants.HV_LXC_EXTRA_CGROUPS]:
      enable_subsystems = cls._GetCgroupEnabledKernelSubsystems()
    else:
      enable_subsystems = hvparams[constants.HV_LXC_EXTRA_CGROUPS].split(",")

    for subsystem in enable_subsystems:
      cls._GetOrPrepareCgroupSubsysMountPoint(subsystem)

  @classmethod
  def _PrepareInstanceRootFsBdev(cls, storage_path, stash):
    """Return mountable path for storage_path.

    This function creates a partition mapping for storage_path and returns the
    first partition device path as a rootfs partition, and stashes the loopback
    device path.
    If storage_path is not a multi-partition block device, just return
    storage_path.

    """
    try:
      ret = utils.CreateBdevPartitionMapping(storage_path)
    except errors.CommandError, err:
      raise HypervisorError("Failed to create partition mapping for %s"
                            ": %s" % (storage_path, err))

    if ret is None:
      return storage_path
    else:
      loop_dev_path, dm_dev_paths = ret
      stash[cls._STASH_KEY_ALLOCATED_LOOP_DEV] = loop_dev_path
      return dm_dev_paths[0]

  @classmethod
  def _WaitForInstanceState(cls, instance_name, state, timeout):
    """Wait for an instance state transition within timeout

    Return True if an instance state changed to the desired state within
    timeout secs.

    """
    result = utils.RunCmd(["lxc-wait", "-n", instance_name, "-s", state],
                          timeout=timeout)
    if result.failed_by_timeout:
      return False
    elif result.failed:
      raise HypervisorError("Failure while waiting for instance state"
                            " transition: %s" % result.output)
    else:
      return True

  def _SpawnLXC(self, instance, log_file, conf_file):
    """Execute lxc-start and wait until container health is confirmed.

    """
    lxc_start_cmd = [
      "lxc-start",
      "-n", instance.name,
      "-o", log_file,
      "-l", "DEBUG",
      "-f", conf_file,
      "-d"
      ]

    result = utils.RunCmd(lxc_start_cmd)
    if result.failed:
      raise HypervisorError("Failed to start instance %s : %s" %
                            (instance.name, result.output))

    lxc_startup_timeout = instance.hvparams[constants.HV_LXC_STARTUP_TIMEOUT]
    if not self._WaitForInstanceState(instance.name,
                                      constants.LXC_STATE_RUNNING,
                                      lxc_startup_timeout):
      raise HypervisorError("Instance %s state didn't change to RUNNING within"
                            " %s secs" % (instance.name, lxc_startup_timeout))

    # Ensure that the instance is running correctly after being daemonized
    if not self._IsInstanceAlive(instance.name):
      raise HypervisorError("Failed to start instance %s :"
                            " lxc process exited after being daemonized" %
                            instance.name)

  @classmethod
  def _VerifyDiskRequirements(cls, block_devices):
    """Insures that the disks provided work with the current implementation.

    """
    if len(block_devices) == 0:
      raise HypervisorError("LXC cannot have diskless instances.")

    if len(block_devices) > 1:
      raise HypervisorError("At the moment, LXC cannot support more than one"
                            " disk attached to it. Please create this"
                            " instance anew with fewer disks.")

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

    For LXC, we try to mount the block device and execute 'lxc-start'.
    We use volatile containers.

    """
    LXCHypervisor._VerifyDiskRequirements(block_devices)

    stash = {}

    # Since LXC version >= 1.0.0, the LXC strictly requires all cgroup
    # subsystems mounted before starting a container.
    # Try to mount all cgroup subsystems needed to start a LXC container.
    self._EnsureCgroupMounts(instance.hvparams)

    root_dir = self._InstanceDir(instance.name)
    try:
      utils.EnsureDirs([(root_dir, self._DIR_MODE)])
    except errors.GenericError, err:
      raise HypervisorError("Creating instance directory failed: %s", str(err))

    log_file = self._InstanceLogFilePath(instance)
    if not os.path.exists(log_file):
      _CreateBlankFile(log_file, constants.SECURE_FILE_MODE)

    try:
      sda_dev_path = block_devices[0][1]
      # LXC needs to use partition mapping devices to access each partition
      # of the storage
      sda_dev_path = self._PrepareInstanceRootFsBdev(sda_dev_path, stash)
      conf_file = self._InstanceConfFilePath(instance.name)
      conf = self._CreateConfigFile(instance, sda_dev_path)
      utils.WriteFile(conf_file, data=conf)

      logging.info("Starting LXC container")
      try:
        self._SpawnLXC(instance, log_file, conf_file)
      except:
        logging.error("Failed to start instance %s. Please take a look at %s to"
                      " see LXC errors.", instance.name, log_file)
        raise
    except:
      # Save the original error
      exc_info = sys.exc_info()
      try:
        self._CleanupInstance(instance.name, stash)
      except HypervisorError, err:
        logging.warn("Cleanup for instance %s incomplete: %s",
                     instance.name, err)
      raise exc_info[0], exc_info[1], exc_info[2]

    self._SaveInstanceStash(instance.name, stash)

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

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

    if name is None:
      name = instance.name

    if self._IsInstanceAlive(instance.name):
      lxc_stop_cmd = ["lxc-stop", "-n", name]

      if force:
        lxc_stop_cmd.append("--kill")
        result = utils.RunCmd(lxc_stop_cmd, timeout=timeout)
        if result.failed:
          raise HypervisorError("Failed to kill instance %s: %s" %
                                (name, result.output))
      else:
        # The --timeout=-1 option is needed to prevent lxc-stop performs
        # hard-stop(kill) for the container after the default timing out.
        lxc_stop_cmd.extend(["--nokill", "--timeout", "-1"])
        result = utils.RunCmd(lxc_stop_cmd, timeout=timeout)
        if result.failed:
          logging.error("Failed to stop instance %s: %s", name, result.output)

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

    """
    if "sys_boot" in self._GetInstanceDropCapabilities(instance.hvparams):
      raise HypervisorError("The LXC container can't perform a reboot with the"
                            " SYS_BOOT capability dropped.")

    # We can't use the --timeout=-1 approach as same as the StopInstance due to
    # the following patch was applied in lxc-1.0.5 and we are supporting
    # LXC >= 1.0.0.
    # http://lists.linuxcontainers.org/pipermail/lxc-devel/2014-July/009742.html
    result = utils.RunCmd(["lxc-stop", "-n", instance.name, "--reboot",
                           "--timeout", str(self._REBOOT_TIMEOUT)])
    if result.failed:
      raise HypervisorError("Failed to reboot instance %s: %s" %
                            (instance.name, result.output))

  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

    """
    mem_in_bytes = mem * 1024 ** 2
    current_mem_usage = self._GetCgroupMemoryLimit(instance.name)
    shrinking = mem_in_bytes <= current_mem_usage

    # The memsw.limit_in_bytes parameter might be present depending on kernel
    # parameters.
    # If present, it has to be modified at the same time as limit_in_bytes.
    if LXCHypervisor._IsCgroupParameterPresent(self._MEMORY_SWAP_PARAMETER,
                                               instance.hvparams):
      # memory.memsw.limit_in_bytes is the superlimit of memory.limit_in_bytes
      # so the order of setting these parameters is quite important.
      cgparams = [self._MEMORY_SWAP_PARAMETER, self._MEMORY_PARAMETER]
    else:
      cgparams = [self._MEMORY_PARAMETER]

    if shrinking:
      cgparams.reverse()

    for i, cgparam in enumerate(cgparams):
      try:
        self._SetCgroupInstanceValue(instance.name, cgparam, str(mem_in_bytes))
      except EnvironmentError, err:
        if shrinking and err.errno == errno.EBUSY:
          logging.warn("Unable to reclaim memory or swap usage from instance"
                       " %s", instance.name)
        # Restore changed parameters for an atomicity
        for restore_param in cgparams[0:i]:
          try:
            self._SetCgroupInstanceValue(instance.name, restore_param,
                                         str(current_mem_usage))
          except EnvironmentError, restore_err:
            logging.warn("Can't restore the cgroup parameter %s of %s: %s",
                         restore_param, instance.name, restore_err)

        raise HypervisorError("Failed to balloon the memory of %s, can't set"
                              " cgroup parameter %s: %s" %
                              (instance.name, cgparam, err))

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

    See L{BaseHypervisor.GetLinuxNodeInfo}.

    """
    return self.GetLinuxNodeInfo()

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

    """
    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=["lxc-console", "-n", instance.name])

  @classmethod
  def _GetLXCVersionFromCmd(cls, from_cmd):
    """Return the LXC version currently used in the system.

    Version information will be retrieved by command specified by from_cmd.

    @param from_cmd: the lxc command used to retrieve version information
    @type from_cmd: string
    @rtype: L{LXCVersion}
    @return: a version object which represents the version retrieved from the
             command

    """
    result = utils.RunCmd([from_cmd, "--version"])
    if result.failed:
      raise HypervisorError("Failed to get version info from command %s: %s" %
                            (from_cmd, result.output))

    try:
      return LXCVersion(result.stdout.strip())
    except ValueError, err:
      raise HypervisorError("Can't parse LXC version from %s: %s" %
                            (from_cmd, err))

  @classmethod
  def _VerifyLXCCommands(cls):
    """Verify the validity of lxc command line tools.

    @rtype: list(str)
    @return: list of problem descriptions. the blank list will be returned if
             there is no problem.

    """
    msgs = []
    for cmd in cls._LXC_COMMANDS_REQUIRED:
      try:
        # lxc-ls needs special checking procedure.
        # there are two different version of lxc-ls, one is written in python
        # and the other is written in shell script.
        # we have to ensure the python version of lxc-ls is installed.
        if cmd == "lxc-ls":
          help_string = utils.RunCmd(["lxc-ls", "--help"]).output
          if "--running" not in help_string:
            # shell script version has no --running switch
            msgs.append("The python version of 'lxc-ls' is required."
                        " Maybe lxc was installed without --enable-python")
        else:
          try:
            version = cls._GetLXCVersionFromCmd(cmd)
          except HypervisorError, err:
            msgs.append(str(err))
            continue

          if version < cls._LXC_MIN_VERSION_REQUIRED:
            msgs.append("LXC version >= %s is required but command %s has"
                        " version %s" %
                        (cls._LXC_MIN_VERSION_REQUIRED, cmd, version))
      except errors.OpExecError:
        msgs.append("Required command %s not found" % cmd)

    return msgs

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

    For the LXC manager, it just checks the existence of the base dir.

    @type hvparams: dict of strings
    @param hvparams: hypervisor parameters to be verified against; not used here

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

    """
    msgs = []

    if not os.path.exists(self._ROOT_DIR):
      msgs.append("The required directory '%s' does not exist" %
                  self._ROOT_DIR)

    try:
      self._EnsureCgroupMounts(hvparams)
    except errors.HypervisorError, err:
      msgs.append(str(err))

    msgs.extend(self._VerifyLXCCommands())

    return self._FormatVerifyResults(msgs)

  @classmethod
  def PowercycleNode(cls, hvparams=None):
    """LXC powercycle, just a wrapper over Linux powercycle.

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

    """
    cls.LinuxPowercycle()

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

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

    """
    raise HypervisorError("Migration is not supported by the LXC hypervisor")

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

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

    """
    raise HypervisorError("Migration is not supported by the LXC hypervisor")
