#
#

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


"""Block device abstraction.

"""

import re
import stat
import os
import logging
import math

from ganeti import utils
from ganeti import errors
from ganeti import constants
from ganeti import objects
from ganeti import compat
from ganeti import serializer
from ganeti.storage import base
from ganeti.storage import drbd
from ganeti.storage.filestorage import FileStorage
from ganeti.storage.gluster import GlusterStorage
from ganeti.storage.extstorage import ExtStorageDevice


class RbdShowmappedJsonError(Exception):
  """`rbd showmmapped' JSON formatting error Exception class.

  """
  pass


def _CheckResult(result):
  """Throws an error if the given result is a failed one.

  @param result: result from RunCmd

  """
  if result.failed:
    base.ThrowError("Command: %s error: %s - %s",
                    result.cmd, result.fail_reason, result.output)


class LogicalVolume(base.BlockDev):
  """Logical Volume block device.

  """
  _VALID_NAME_RE = re.compile("^[a-zA-Z0-9+_.-]*$")
  _PARSE_PV_DEV_RE = re.compile(r"^([^ ()]+)\([0-9]+\)$")
  _INVALID_NAMES = compat.UniqueFrozenset([".", "..", "snapshot", "pvmove"])
  _INVALID_SUBSTRINGS = compat.UniqueFrozenset(["_mlog", "_mimage"])

  def __init__(self, unique_id, children, size, params, dyn_params, **kwargs):
    """Attaches to a LV device.

    The unique_id is a tuple (vg_name, lv_name)

    """
    super(LogicalVolume, self).__init__(unique_id, children, size, params,
                                        dyn_params, **kwargs)
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
      raise ValueError("Invalid configuration data %s" % str(unique_id))
    self._vg_name, self._lv_name = unique_id
    self._ValidateName(self._vg_name)
    self._ValidateName(self._lv_name)
    self.dev_path = utils.PathJoin("/dev", self._vg_name, self._lv_name)
    self._degraded = True
    self.major = self.minor = self.pe_size = self.stripe_count = None
    self.pv_names = None
    lvs_cache = kwargs.get("lvs_cache")
    if lvs_cache:
      lv_info = lvs_cache.get(self.dev_path)
      self.Attach(lv_info=lv_info)
    else:
      self.Attach()

  @staticmethod
  def _GetStdPvSize(pvs_info):
    """Return the the standard PV size (used with exclusive storage).

    @param pvs_info: list of objects.LvmPvInfo, cannot be empty
    @rtype: float
    @return: size in MiB

    """
    assert len(pvs_info) > 0
    smallest = min([pv.size for pv in pvs_info])
    return smallest / (1 + constants.PART_MARGIN + constants.PART_RESERVED)

  @staticmethod
  def _ComputeNumPvs(size, pvs_info):
    """Compute the number of PVs needed for an LV (with exclusive storage).

    @type size: float
    @param size: LV size in MiB
    @param pvs_info: list of objects.LvmPvInfo, cannot be empty
    @rtype: integer
    @return: number of PVs needed
    """
    assert len(pvs_info) > 0
    pv_size = float(LogicalVolume._GetStdPvSize(pvs_info))
    return int(math.ceil(float(size) / pv_size))

  @staticmethod
  def _GetEmptyPvNames(pvs_info, max_pvs=None):
    """Return a list of empty PVs, by name.

    """
    empty_pvs = filter(objects.LvmPvInfo.IsEmpty, pvs_info)
    if max_pvs is not None:
      empty_pvs = empty_pvs[:max_pvs]
    return [pv.name for pv in empty_pvs]

  @classmethod
  def Create(cls, unique_id, children, size, spindles, params, excl_stor,
             dyn_params, **kwargs):
    """Create a new logical volume.

    """
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
      raise errors.ProgrammerError("Invalid configuration data %s" %
                                   str(unique_id))
    vg_name, lv_name = unique_id
    cls._ValidateName(vg_name)
    cls._ValidateName(lv_name)
    pvs_info = cls.GetPVInfo([vg_name])
    if not pvs_info:
      if excl_stor:
        msg = "No (empty) PVs found"
      else:
        msg = "Can't compute PV info for vg %s" % vg_name
      base.ThrowError(msg)
    pvs_info.sort(key=(lambda pv: pv.free), reverse=True)

    pvlist = [pv.name for pv in pvs_info]
    if compat.any(":" in v for v in pvlist):
      base.ThrowError("Some of your PVs have the invalid character ':' in their"
                      " name, this is not supported - please filter them out"
                      " in lvm.conf using either 'filter' or 'preferred_names'")

    current_pvs = len(pvlist)
    desired_stripes = params[constants.LDP_STRIPES]
    stripes = min(current_pvs, desired_stripes)

    if excl_stor:
      if spindles is None:
        base.ThrowError("Unspecified number of spindles: this is required"
                        "when exclusive storage is enabled, try running"
                        " gnt-cluster repair-disk-sizes")
      (err_msgs, _) = utils.LvmExclusiveCheckNodePvs(pvs_info)
      if err_msgs:
        for m in err_msgs:
          logging.warning(m)
      req_pvs = cls._ComputeNumPvs(size, pvs_info)
      if spindles < req_pvs:
        base.ThrowError("Requested number of spindles (%s) is not enough for"
                        " a disk of %d MB (at least %d spindles needed)",
                        spindles, size, req_pvs)
      else:
        req_pvs = spindles
      pvlist = cls._GetEmptyPvNames(pvs_info, req_pvs)
      current_pvs = len(pvlist)
      if current_pvs < req_pvs:
        base.ThrowError("Not enough empty PVs (spindles) to create a disk of %d"
                        " MB: %d available, %d needed",
                        size, current_pvs, req_pvs)
      assert current_pvs == len(pvlist)
      # We must update stripes to be sure to use all the desired spindles
      stripes = current_pvs
      if stripes > desired_stripes:
        # Don't warn when lowering stripes, as it's no surprise
        logging.warning("Using %s stripes instead of %s, to be able to use"
                        " %s spindles", stripes, desired_stripes, current_pvs)

    else:
      if stripes < desired_stripes:
        logging.warning("Could not use %d stripes for VG %s, as only %d PVs are"
                        " available.", desired_stripes, vg_name, current_pvs)
      free_size = sum([pv.free for pv in pvs_info])
      # The size constraint should have been checked from the master before
      # calling the create function.
      if free_size < size:
        base.ThrowError("Not enough free space: required %s,"
                        " available %s", size, free_size)

    # If the free space is not well distributed, we won't be able to
    # create an optimally-striped volume; in that case, we want to try
    # with N, N-1, ..., 2, and finally 1 (non-stripped) number of
    # stripes
    cmd = ["lvcreate", "-L%dm" % size, "-n%s" % lv_name]
    for stripes_arg in range(stripes, 0, -1):
      result = utils.RunCmd(cmd + ["-i%d" % stripes_arg] + [vg_name] + pvlist)
      if not result.failed:
        break
    if result.failed:
      base.ThrowError("LV create failed (%s): %s",
                      result.fail_reason, result.output)
    return LogicalVolume(unique_id, children, size, params,
                         dyn_params, **kwargs)

  @staticmethod
  def _GetVolumeInfo(lvm_cmd, fields):
    """Returns LVM Volume infos using lvm_cmd

    @param lvm_cmd: Should be one of "pvs", "vgs" or "lvs"
    @param fields: Fields to return
    @return: A list of dicts each with the parsed fields

    """
    if not fields:
      raise errors.ProgrammerError("No fields specified")

    sep = "|"
    cmd = [lvm_cmd, "--noheadings", "--nosuffix", "--units=m", "--unbuffered",
           "--separator=%s" % sep, "-o%s" % ",".join(fields)]

    result = utils.RunCmd(cmd)
    if result.failed:
      raise errors.CommandError("Can't get the volume information: %s - %s" %
                                (result.fail_reason, result.output))

    data = []
    for line in result.stdout.splitlines():
      splitted_fields = line.strip().split(sep)

      if len(fields) != len(splitted_fields):
        raise errors.CommandError("Can't parse %s output: line '%s'" %
                                  (lvm_cmd, line))

      data.append(splitted_fields)

    return data

  @classmethod
  def GetPVInfo(cls, vg_names, filter_allocatable=True, include_lvs=False):
    """Get the free space info for PVs in a volume group.

    @param vg_names: list of volume group names, if empty all will be returned
    @param filter_allocatable: whether to skip over unallocatable PVs
    @param include_lvs: whether to include a list of LVs hosted on each PV

    @rtype: list
    @return: list of objects.LvmPvInfo objects

    """
    # We request "lv_name" field only if we care about LVs, so we don't get
    # a long list of entries with many duplicates unless we really have to.
    # The duplicate "pv_name" field will be ignored.
    if include_lvs:
      lvfield = "lv_name"
    else:
      lvfield = "pv_name"
    try:
      info = cls._GetVolumeInfo("pvs", ["pv_name", "vg_name", "pv_free",
                                        "pv_attr", "pv_size", lvfield])
    except errors.GenericError, err:
      logging.error("Can't get PV information: %s", err)
      return None

    # When asked for LVs, "pvs" may return multiple entries for the same PV-LV
    # pair. We sort entries by PV name and then LV name, so it's easy to weed
    # out duplicates.
    if include_lvs:
      info.sort(key=(lambda i: (i[0], i[5])))
    data = []
    lastpvi = None
    for (pv_name, vg_name, pv_free, pv_attr, pv_size, lv_name) in info:
      # (possibly) skip over pvs which are not allocatable
      if filter_allocatable and pv_attr[0] != "a":
        continue
      # (possibly) skip over pvs which are not in the right volume group(s)
      if vg_names and vg_name not in vg_names:
        continue
      # Beware of duplicates (check before inserting)
      if lastpvi and lastpvi.name == pv_name:
        if include_lvs and lv_name:
          if not lastpvi.lv_list or lastpvi.lv_list[-1] != lv_name:
            lastpvi.lv_list.append(lv_name)
      else:
        if include_lvs and lv_name:
          lvl = [lv_name]
        else:
          lvl = []
        lastpvi = objects.LvmPvInfo(name=pv_name, vg_name=vg_name,
                                    size=float(pv_size), free=float(pv_free),
                                    attributes=pv_attr, lv_list=lvl)
        data.append(lastpvi)

    return data

  @classmethod
  def _GetRawFreePvInfo(cls, vg_name):
    """Return info (size/free) about PVs.

    @type vg_name: string
    @param vg_name: VG name
    @rtype: tuple
    @return: (standard_pv_size_in_MiB, number_of_free_pvs, total_number_of_pvs)

    """
    pvs_info = cls.GetPVInfo([vg_name])
    if not pvs_info:
      pv_size = 0.0
      free_pvs = 0
      num_pvs = 0
    else:
      pv_size = cls._GetStdPvSize(pvs_info)
      free_pvs = len(cls._GetEmptyPvNames(pvs_info))
      num_pvs = len(pvs_info)
    return (pv_size, free_pvs, num_pvs)

  @classmethod
  def _GetExclusiveStorageVgFree(cls, vg_name):
    """Return the free disk space in the given VG, in exclusive storage mode.

    @type vg_name: string
    @param vg_name: VG name
    @rtype: float
    @return: free space in MiB
    """
    (pv_size, free_pvs, _) = cls._GetRawFreePvInfo(vg_name)
    return pv_size * free_pvs

  @classmethod
  def GetVgSpindlesInfo(cls, vg_name):
    """Get the free space info for specific VGs.

    @param vg_name: volume group name
    @rtype: tuple
    @return: (free_spindles, total_spindles)

    """
    (_, free_pvs, num_pvs) = cls._GetRawFreePvInfo(vg_name)
    return (free_pvs, num_pvs)

  @classmethod
  def GetVGInfo(cls, vg_names, excl_stor, filter_readonly=True):
    """Get the free space info for specific VGs.

    @param vg_names: list of volume group names, if empty all will be returned
    @param excl_stor: whether exclusive_storage is enabled
    @param filter_readonly: whether to skip over readonly VGs

    @rtype: list
    @return: list of tuples (free_space, total_size, name) with free_space in
             MiB

    """
    try:
      info = cls._GetVolumeInfo("vgs", ["vg_name", "vg_free", "vg_attr",
                                        "vg_size"])
    except errors.GenericError, err:
      logging.error("Can't get VG information: %s", err)
      return None

    data = []
    for vg_name, vg_free, vg_attr, vg_size in info:
      # (possibly) skip over vgs which are not writable
      if filter_readonly and vg_attr[0] == "r":
        continue
      # (possibly) skip over vgs which are not in the right volume group(s)
      if vg_names and vg_name not in vg_names:
        continue
      # Exclusive storage needs a different concept of free space
      if excl_stor:
        es_free = cls._GetExclusiveStorageVgFree(vg_name)
        assert es_free <= vg_free
        vg_free = es_free
      data.append((float(vg_free), float(vg_size), vg_name))

    return data

  @classmethod
  def _ValidateName(cls, name):
    """Validates that a given name is valid as VG or LV name.

    The list of valid characters and restricted names is taken out of
    the lvm(8) manpage, with the simplification that we enforce both
    VG and LV restrictions on the names.

    """
    if (not cls._VALID_NAME_RE.match(name) or
        name in cls._INVALID_NAMES or
        compat.any(substring in name for substring in cls._INVALID_SUBSTRINGS)):
      base.ThrowError("Invalid LVM name '%s'", name)

  def Remove(self):
    """Remove this logical volume.

    """
    if not self.minor and not self.Attach():
      # the LV does not exist
      return
    result = utils.RunCmd(["lvremove", "-f", "%s/%s" %
                           (self._vg_name, self._lv_name)])
    if result.failed:
      base.ThrowError("Can't lvremove: %s - %s",
                      result.fail_reason, result.output)

  def Rename(self, new_id):
    """Rename this logical volume.

    """
    if not isinstance(new_id, (tuple, list)) or len(new_id) != 2:
      raise errors.ProgrammerError("Invalid new logical id '%s'" % new_id)
    new_vg, new_name = new_id
    if new_vg != self._vg_name:
      raise errors.ProgrammerError("Can't move a logical volume across"
                                   " volume groups (from %s to to %s)" %
                                   (self._vg_name, new_vg))
    result = utils.RunCmd(["lvrename", new_vg, self._lv_name, new_name])
    if result.failed:
      base.ThrowError("Failed to rename the logical volume: %s", result.output)
    self._lv_name = new_name
    self.dev_path = utils.PathJoin("/dev", self._vg_name, self._lv_name)

  @staticmethod
  def _ParseLvInfoLine(line, sep):
    """Parse one line of the lvs output used in L{GetLvGlobalInfo}.

    """
    elems = line.strip().split(sep)

    # The previous iteration of code here assumed that LVM might put another
    # separator to the right of the output. The PV info might be empty for
    # thin volumes, so stripping off the separators might cut off the last
    # empty element - do this instead.
    if len(elems) == 9 and elems[-1] == "":
      elems.pop()

    if len(elems) != 8:
      base.ThrowError("Can't parse LVS output, len(%s) != 8", str(elems))

    (vg_name, lv_name, status, major, minor, pe_size, stripes, pvs) = elems
    path = os.path.join(os.environ.get('DM_DEV_DIR', '/dev'), vg_name, lv_name)
    if len(status) < 6:
      base.ThrowError("lvs lv_attr is not at least 6 characters (%s)", status)

    try:
      major = int(major)
      minor = int(minor)
    except (TypeError, ValueError), err:
      base.ThrowError("lvs major/minor cannot be parsed: %s", str(err))

    try:
      pe_size = int(float(pe_size))
    except (TypeError, ValueError), err:
      base.ThrowError("Can't parse vg extent size: %s", err)

    try:
      stripes = int(stripes)
    except (TypeError, ValueError), err:
      base.ThrowError("Can't parse the number of stripes: %s", err)

    pv_names = []
    if pvs != "":
      for pv in pvs.split(","):
        m = re.match(LogicalVolume._PARSE_PV_DEV_RE, pv)
        if not m:
          base.ThrowError("Can't parse this device list: %s", pvs)
        pv_names.append(m.group(1))

    return (path, (status, major, minor, pe_size, stripes, pv_names))

  @staticmethod
  def GetLvGlobalInfo(_run_cmd=utils.RunCmd):
    """Obtain the current state of the existing LV disks.

    @return: a dict containing the state of each disk with the disk path as key

    """
    sep = "|"
    result = _run_cmd(["lvs", "--noheadings", "--separator=%s" % sep,
                       "--units=k", "--nosuffix",
                       "-ovg_name,lv_name,lv_attr,lv_kernel_major,"
                       "lv_kernel_minor,vg_extent_size,stripes,devices"])
    if result.failed:
      logging.warning("lvs command failed, the LV cache will be empty!")
      logging.info("lvs failure: %r", result.stderr)
      return {}
    out = result.stdout.splitlines()
    if not out:
      logging.warning("lvs command returned an empty output, the LV cache will"
                      "be empty!")
      return {}
    return dict([LogicalVolume._ParseLvInfoLine(line, sep) for line in out])

  def Attach(self, lv_info=None, **kwargs):
    """Attach to an existing LV.

    This method will try to see if an existing and active LV exists
    which matches our name. If so, its major/minor will be
    recorded.

    """
    self.attached = False
    if not lv_info:
      lv_info = LogicalVolume.GetLvGlobalInfo().get(self.dev_path)
    if not lv_info:
      return False
    (status, major, minor, pe_size, stripes, pv_names) = lv_info

    self.major = major
    self.minor = minor
    self.pe_size = pe_size
    self.stripe_count = stripes
    self._degraded = status[0] == "v" # virtual volume, i.e. doesn't backing
                                      # storage
    self.pv_names = pv_names
    self.attached = True
    return True

  def Assemble(self):
    """Assemble the device.

    We always run `lvchange -ay` on the LV to ensure it's active before
    use, as there were cases when xenvg was not active after boot
    (also possibly after disk issues).

    """
    result = utils.RunCmd(["lvchange", "-ay", self.dev_path])
    if result.failed:
      base.ThrowError("Can't activate lv %s: %s", self.dev_path, result.output)

  def Shutdown(self):
    """Shutdown the device.

    This is a no-op for the LV device type, as we don't deactivate the
    volumes on shutdown.

    """
    pass

  def GetSyncStatus(self):
    """Returns the sync status of the device.

    If this device is a mirroring device, this function returns the
    status of the mirror.

    For logical volumes, sync_percent and estimated_time are always
    None (no recovery in progress, as we don't handle the mirrored LV
    case). The is_degraded parameter is the inverse of the ldisk
    parameter.

    For the ldisk parameter, we check if the logical volume has the
    'virtual' type, which means it's not backed by existing storage
    anymore (read from it return I/O error). This happens after a
    physical disk failure and subsequent 'vgreduce --removemissing' on
    the volume group.

    The status was already read in Attach, so we just return it.

    @rtype: objects.BlockDevStatus

    """
    if self._degraded:
      ldisk_status = constants.LDS_FAULTY
    else:
      ldisk_status = constants.LDS_OKAY

    return objects.BlockDevStatus(dev_path=self.dev_path,
                                  major=self.major,
                                  minor=self.minor,
                                  sync_percent=None,
                                  estimated_time=None,
                                  is_degraded=self._degraded,
                                  ldisk_status=ldisk_status)

  def Open(self, force=False, exclusive=True):
    """Make the device ready for I/O.

    This is a no-op for the LV device type.

    """
    pass

  def Close(self):
    """Notifies that the device will no longer be used for I/O.

    This is a no-op for the LV device type.

    """
    pass

  def Snapshot(self, snap_name=None, snap_size=None):
    """Create a snapshot copy of an lvm block device.

    @returns: tuple (vg, lv)

    """
    if not snap_name:
      snap_name = self._lv_name + ".snap"

    if not snap_size:
      # FIXME: choose a saner value for the snapshot size
      # let's stay on the safe side and ask for the full size, for now
      snap_size = self.size

    # remove existing snapshot if found
    snap = LogicalVolume((self._vg_name, snap_name), None, snap_size,
                         self.params, self.dyn_params)
    base.IgnoreError(snap.Remove)

    vg_info = self.GetVGInfo([self._vg_name], False)
    if not vg_info:
      base.ThrowError("Can't compute VG info for vg %s", self._vg_name)
    free_size, _, _ = vg_info[0]
    if free_size < snap_size:
      base.ThrowError("Not enough free space: required %s,"
                      " available %s", snap_size, free_size)

    _CheckResult(utils.RunCmd(["lvcreate", "-L%dm" % snap_size, "-s",
                               "-n%s" % snap_name, self.dev_path]))

    return (self._vg_name, snap_name)

  def _RemoveOldInfo(self):
    """Try to remove old tags from the lv.

    """
    result = utils.RunCmd(["lvs", "-o", "tags", "--noheadings", "--nosuffix",
                           self.dev_path])
    _CheckResult(result)

    raw_tags = result.stdout.strip()
    if raw_tags:
      for tag in raw_tags.split(","):
        _CheckResult(utils.RunCmd(["lvchange", "--deltag",
                                   tag.strip(), self.dev_path]))

  def SetInfo(self, text):
    """Update metadata with info text.

    """
    base.BlockDev.SetInfo(self, text)

    self._RemoveOldInfo()

    # Replace invalid characters
    text = re.sub("^[^A-Za-z0-9_+.]", "_", text)
    text = re.sub("[^-A-Za-z0-9_+.]", "_", text)

    # Only up to 128 characters are allowed
    text = text[:128]

    _CheckResult(utils.RunCmd(["lvchange", "--addtag", text, self.dev_path]))

  def _GetGrowthAvaliabilityExclStor(self):
    """Return how much the disk can grow with exclusive storage.

    @rtype: float
    @return: available space in Mib

    """
    pvs_info = self.GetPVInfo([self._vg_name])
    if not pvs_info:
      base.ThrowError("Cannot get information about PVs for %s", self.dev_path)
    std_pv_size = self._GetStdPvSize(pvs_info)
    free_space = sum(pvi.free - (pvi.size - std_pv_size)
                        for pvi in pvs_info
                        if pvi.name in self.pv_names)
    return free_space

  def Grow(self, amount, dryrun, backingstore, excl_stor):
    """Grow the logical volume.

    """
    if not backingstore:
      return
    if self.pe_size is None or self.stripe_count is None:
      if not self.Attach():
        base.ThrowError("Can't attach to LV during Grow()")
    full_stripe_size = self.pe_size * self.stripe_count
    # pe_size is in KB
    amount *= 1024
    rest = amount % full_stripe_size
    if rest != 0:
      amount += full_stripe_size - rest
    cmd = ["lvextend", "-L", "+%dk" % amount]
    if dryrun:
      cmd.append("--test")
    if excl_stor:
      free_space = self._GetGrowthAvaliabilityExclStor()
      # amount is in KiB, free_space in MiB
      if amount > free_space * 1024:
        base.ThrowError("Not enough free space to grow %s: %d MiB required,"
                        " %d available", self.dev_path, amount / 1024,
                        free_space)
      # Disk growth doesn't grow the number of spindles, so we must stay within
      # our assigned volumes
      pvlist = list(self.pv_names)
    else:
      pvlist = []
    # we try multiple algorithms since the 'best' ones might not have
    # space available in the right place, but later ones might (since
    # they have less constraints); also note that only recent LVM
    # supports 'cling'
    for alloc_policy in "contiguous", "cling", "normal":
      result = utils.RunCmd(cmd + ["--alloc", alloc_policy, self.dev_path] +
                            pvlist)
      if not result.failed:
        return
    base.ThrowError("Can't grow LV %s: %s", self.dev_path, result.output)

  def GetActualSpindles(self):
    """Return the number of spindles used.

    """
    assert self.attached, "BlockDevice not attached in GetActualSpindles()"
    return len(self.pv_names)


class PersistentBlockDevice(base.BlockDev):
  """A block device with persistent node

  May be either directly attached, or exposed through DM (e.g. dm-multipath).
  udev helpers are probably required to give persistent, human-friendly
  names.

  For the time being, pathnames are required to lie under /dev.

  """
  def __init__(self, unique_id, children, size, params, dyn_params, **kwargs):
    """Attaches to a static block device.

    The unique_id is a path under /dev.

    """
    super(PersistentBlockDevice, self).__init__(unique_id, children, size,
                                                params, dyn_params, **kwargs)
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
      raise ValueError("Invalid configuration data %s" % str(unique_id))
    self.dev_path = unique_id[1]
    if not os.path.realpath(self.dev_path).startswith("/dev/"):
      raise ValueError("Full path '%s' lies outside /dev" %
                              os.path.realpath(self.dev_path))
    # TODO: this is just a safety guard checking that we only deal with devices
    # we know how to handle. In the future this will be integrated with
    # external storage backends and possible values will probably be collected
    # from the cluster configuration.
    if unique_id[0] != constants.BLOCKDEV_DRIVER_MANUAL:
      raise ValueError("Got persistent block device of invalid type: %s" %
                       unique_id[0])

    self.major = self.minor = None
    self.Attach()

  @classmethod
  def Create(cls, unique_id, children, size, spindles, params, excl_stor,
             dyn_params, **kwargs):
    """Create a new device

    This is a noop, we only return a PersistentBlockDevice instance

    """
    if excl_stor:
      raise errors.ProgrammerError("Persistent block device requested with"
                                   " exclusive_storage")
    return PersistentBlockDevice(unique_id, children, 0, params, dyn_params,
                                 **kwargs)

  def Remove(self):
    """Remove a device

    This is a noop

    """
    pass

  def Rename(self, new_id):
    """Rename this device.

    """
    base.ThrowError("Rename is not supported for PersistentBlockDev storage")

  def Attach(self):
    """Attach to an existing block device.

    """
    self.attached = False
    try:
      st = os.stat(self.dev_path)
    except OSError, err:
      logging.error("Error stat()'ing %s: %s", self.dev_path, str(err))
      return False

    if not stat.S_ISBLK(st.st_mode):
      logging.error("%s is not a block device", self.dev_path)
      return False

    self.major = os.major(st.st_rdev)
    self.minor = utils.osminor(st.st_rdev)
    self.attached = True

    return True

  def Assemble(self):
    """Assemble the device.

    """
    pass

  def Shutdown(self):
    """Shutdown the device.

    """
    pass

  def Open(self, force=False, exclusive=True):
    """Make the device ready for I/O.

    """
    pass

  def Close(self):
    """Notifies that the device will no longer be used for I/O.

    """
    pass

  def Grow(self, amount, dryrun, backingstore, excl_stor):
    """Grow the logical volume.

    """
    base.ThrowError("Grow is not supported for PersistentBlockDev storage")

  def Import(self):
    """Builds the shell command for importing data to device.

    @see: L{BlockDev.Import} for details

    """
    base.ThrowError("Importing data is not supported for the"
                    " PersistentBlockDevice template")


class RADOSBlockDevice(base.BlockDev):
  """A RADOS Block Device (rbd).

  This class implements the RADOS Block Device for the backend. You need
  the rbd kernel driver, the RADOS Tools and a working RADOS cluster for
  this to be functional.

  """
  def __init__(self, unique_id, children, size, params, dyn_params, **kwargs):
    """Attaches to an rbd device.

    """
    super(RADOSBlockDevice, self).__init__(unique_id, children, size, params,
                                           dyn_params, **kwargs)
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
      raise ValueError("Invalid configuration data %s" % str(unique_id))

    self.driver, self.rbd_name = unique_id
    self.rbd_pool = params[constants.LDP_POOL]

    self.major = self.minor = None
    self.Attach()

  @classmethod
  def Create(cls, unique_id, children, size, spindles, params, excl_stor,
             dyn_params, **kwargs):
    """Create a new rbd device.

    Provision a new rbd volume inside a RADOS pool.

    """
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
      raise errors.ProgrammerError("Invalid configuration data %s" %
                                   str(unique_id))
    if excl_stor:
      raise errors.ProgrammerError("RBD device requested with"
                                   " exclusive_storage")
    rbd_pool = params[constants.LDP_POOL]
    rbd_name = unique_id[1]

    # Provision a new rbd volume (Image) inside the RADOS cluster.
    cmd = [constants.RBD_CMD, "create", "-p", rbd_pool,
           rbd_name, "--size", "%s" % size]
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("rbd creation failed (%s): %s",
                      result.fail_reason, result.output)

    return RADOSBlockDevice(unique_id, children, size, params, dyn_params,
                            **kwargs)

  def Remove(self):
    """Remove the rbd device.

    """
    rbd_pool = self.params[constants.LDP_POOL]
    rbd_name = self.unique_id[1]

    if not self.minor and not self.Attach():
      # The rbd device doesn't exist.
      return

    # First shutdown the device (remove mappings).
    self.Shutdown()

    # Remove the actual Volume (Image) from the RADOS cluster.
    cmd = [constants.RBD_CMD, "rm", "-p", rbd_pool, rbd_name]
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("Can't remove Volume from cluster with rbd rm: %s - %s",
                      result.fail_reason, result.output)

  def Rename(self, new_id):
    """Rename this device.

    """
    pass

  def Attach(self):
    """Attach to an existing rbd device.

    This method maps the rbd volume that matches our name with
    an rbd device and then attaches to this device.

    """
    self.attached = False

    # Map the rbd volume to a block device under /dev
    self.dev_path = self._MapVolumeToBlockdev(self.unique_id)

    try:
      st = os.stat(self.dev_path)
    except OSError, err:
      logging.error("Error stat()'ing %s: %s", self.dev_path, str(err))
      return False

    if not stat.S_ISBLK(st.st_mode):
      logging.error("%s is not a block device", self.dev_path)
      return False

    self.major = os.major(st.st_rdev)
    self.minor = utils.osminor(st.st_rdev)
    self.attached = True

    return True

  def _MapVolumeToBlockdev(self, unique_id):
    """Maps existing rbd volumes to block devices.

    This method should be idempotent if the mapping already exists.

    @rtype: string
    @return: the block device path that corresponds to the volume

    """
    pool = self.params[constants.LDP_POOL]
    name = unique_id[1]

    # Check if the mapping already exists.
    rbd_dev = self._VolumeToBlockdev(pool, name)
    if rbd_dev:
      # The mapping exists. Return it.
      return rbd_dev

    # The mapping doesn't exist. Create it.
    map_cmd = [constants.RBD_CMD, "map", "-p", pool, name]
    result = utils.RunCmd(map_cmd)
    if result.failed:
      base.ThrowError("rbd map failed (%s): %s",
                      result.fail_reason, result.output)

    # Find the corresponding rbd device.
    rbd_dev = self._VolumeToBlockdev(pool, name)
    if not rbd_dev:
      base.ThrowError("rbd map succeeded, but could not find the rbd block"
                      " device in output of showmapped, for volume: %s", name)

    # The device was successfully mapped. Return it.
    return rbd_dev

  @classmethod
  def _VolumeToBlockdev(cls, pool, volume_name):
    """Do the 'volume name'-to-'rbd block device' resolving.

    @type pool: string
    @param pool: RADOS pool to use
    @type volume_name: string
    @param volume_name: the name of the volume whose device we search for
    @rtype: string or None
    @return: block device path if the volume is mapped, else None

    """
    try:
      # Newer versions of the rbd tool support json output formatting. Use it
      # if available.
      showmap_cmd = [
        constants.RBD_CMD,
        "showmapped",
        "-p",
        pool,
        "--format",
        "json"
        ]
      result = utils.RunCmd(showmap_cmd)
      if result.failed:
        logging.error("rbd JSON output formatting returned error (%s): %s,"
                      "falling back to plain output parsing",
                      result.fail_reason, result.output)
        raise RbdShowmappedJsonError

      return cls._ParseRbdShowmappedJson(result.output, volume_name)
    except RbdShowmappedJsonError:
      # For older versions of rbd, we have to parse the plain / text output
      # manually.
      showmap_cmd = [constants.RBD_CMD, "showmapped", "-p", pool]
      result = utils.RunCmd(showmap_cmd)
      if result.failed:
        base.ThrowError("rbd showmapped failed (%s): %s",
                        result.fail_reason, result.output)

      return cls._ParseRbdShowmappedPlain(result.output, volume_name)

  @staticmethod
  def _ParseRbdShowmappedJson(output, volume_name):
    """Parse the json output of `rbd showmapped'.

    This method parses the json output of `rbd showmapped' and returns the rbd
    block device path (e.g. /dev/rbd0) that matches the given rbd volume.

    @type output: string
    @param output: the json output of `rbd showmapped'
    @type volume_name: string
    @param volume_name: the name of the volume whose device we search for
    @rtype: string or None
    @return: block device path if the volume is mapped, else None

    """
    try:
      devices = serializer.LoadJson(output)
    except ValueError, err:
      base.ThrowError("Unable to parse JSON data: %s" % err)

    rbd_dev = None
    for d in devices.values(): # pylint: disable=E1103
      try:
        name = d["name"]
      except KeyError:
        base.ThrowError("'name' key missing from json object %s", devices)

      if name == volume_name:
        if rbd_dev is not None:
          base.ThrowError("rbd volume %s is mapped more than once", volume_name)

        rbd_dev = d["device"]

    return rbd_dev

  @staticmethod
  def _ParseRbdShowmappedPlain(output, volume_name):
    """Parse the (plain / text) output of `rbd showmapped'.

    This method parses the output of `rbd showmapped' and returns
    the rbd block device path (e.g. /dev/rbd0) that matches the
    given rbd volume.

    @type output: string
    @param output: the plain text output of `rbd showmapped'
    @type volume_name: string
    @param volume_name: the name of the volume whose device we search for
    @rtype: string or None
    @return: block device path if the volume is mapped, else None

    """
    allfields = 5
    volumefield = 2
    devicefield = 4

    lines = output.splitlines()

    # Try parsing the new output format (ceph >= 0.55).
    splitted_lines = [l.split() for l in lines]

    # Check for empty output.
    if not splitted_lines:
      return None

    # Check showmapped output, to determine number of fields.
    field_cnt = len(splitted_lines[0])
    if field_cnt != allfields:
      # Parsing the new format failed. Fallback to parsing the old output
      # format (< 0.55).
      splitted_lines = [l.split("\t") for l in lines]
      if field_cnt != allfields:
        base.ThrowError("Cannot parse rbd showmapped output expected %s fields,"
                        " found %s", allfields, field_cnt)

    matched_lines = \
      filter(lambda l: len(l) == allfields and l[volumefield] == volume_name,
             splitted_lines)

    if len(matched_lines) > 1:
      base.ThrowError("rbd volume %s mapped more than once", volume_name)

    if matched_lines:
      # rbd block device found. Return it.
      rbd_dev = matched_lines[0][devicefield]
      return rbd_dev

    # The given volume is not mapped.
    return None

  def Assemble(self):
    """Assemble the device.

    """
    pass

  def Shutdown(self):
    """Shutdown the device.

    """
    if not self.minor and not self.Attach():
      # The rbd device doesn't exist.
      return

    # Unmap the block device from the Volume.
    self._UnmapVolumeFromBlockdev(self.unique_id)

    self.minor = None
    self.dev_path = None

  def _UnmapVolumeFromBlockdev(self, unique_id):
    """Unmaps the rbd device from the Volume it is mapped.

    Unmaps the rbd device from the Volume it was previously mapped to.
    This method should be idempotent if the Volume isn't mapped.

    """
    pool = self.params[constants.LDP_POOL]
    name = unique_id[1]

    # Check if the mapping already exists.
    rbd_dev = self._VolumeToBlockdev(pool, name)

    if rbd_dev:
      # The mapping exists. Unmap the rbd device.
      unmap_cmd = [constants.RBD_CMD, "unmap", "%s" % rbd_dev]
      result = utils.RunCmd(unmap_cmd)
      if result.failed:
        base.ThrowError("rbd unmap failed (%s): %s",
                        result.fail_reason, result.output)

  def Open(self, force=False, exclusive=True):
    """Make the device ready for I/O.

    """
    pass

  def Close(self):
    """Notifies that the device will no longer be used for I/O.

    """
    pass

  def Grow(self, amount, dryrun, backingstore, excl_stor):
    """Grow the Volume.

    @type amount: integer
    @param amount: the amount (in mebibytes) to grow with
    @type dryrun: boolean
    @param dryrun: whether to execute the operation in simulation mode
        only, without actually increasing the size

    """
    if not backingstore:
      return
    if not self.Attach():
      base.ThrowError("Can't attach to rbd device during Grow()")

    if dryrun:
      # the rbd tool does not support dry runs of resize operations.
      # Since rbd volumes are thinly provisioned, we assume
      # there is always enough free space for the operation.
      return

    rbd_pool = self.params[constants.LDP_POOL]
    rbd_name = self.unique_id[1]
    new_size = self.size + amount

    # Resize the rbd volume (Image) inside the RADOS cluster.
    cmd = [constants.RBD_CMD, "resize", "-p", rbd_pool,
           rbd_name, "--size", "%s" % new_size]
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("rbd resize failed (%s): %s",
                      result.fail_reason, result.output)

  def Import(self):
    """Builds the shell command for importing data to device.

    @see: L{BlockDev.Import} for details

    """
    if not self.minor and not self.Attach():
      # The rbd device doesn't exist.
      base.ThrowError("Can't attach to rbd device during Import()")

    rbd_pool = self.params[constants.LDP_POOL]
    rbd_name = self.unique_id[1]

    # Currently, the 'rbd import' command imports data only to non-existing
    # volumes. If the rbd volume exists the command will fail.
    # The disk conversion mechanism though, has already created the new rbd
    # volume at the time we perform the data copy, so we have to first remove
    # the volume before starting to import its data. The 'rbd import' will
    # re-create the rbd volume. We choose to remove manually the rbd device
    # instead of calling its 'Remove()' method to avoid affecting the 'self.'
    # parameters of the device. Also, this part of the removal code will go
    # away once 'rbd import' has support for importing into an existing volume.
    # TODO: update this method when the 'rbd import' command supports the
    # '--force' option, which will allow importing to an existing volume.

    # Unmap the block device from the Volume.
    self._UnmapVolumeFromBlockdev(self.unique_id)

    # Remove the actual Volume (Image) from the RADOS cluster.
    cmd = [constants.RBD_CMD, "rm", "-p", rbd_pool, rbd_name]
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("Can't remove Volume from cluster with rbd rm: %s - %s",
                      result.fail_reason, result.output)

    # We use "-" for importing from stdin
    return [constants.RBD_CMD, "import",
            "-p", rbd_pool,
            "-", rbd_name]

  def Export(self):
    """Builds the shell command for exporting data from device.

    @see: L{BlockDev.Export} for details

    """
    if not self.minor and not self.Attach():
      # The rbd device doesn't exist.
      base.ThrowError("Can't attach to rbd device during Export()")

    rbd_pool = self.params[constants.LDP_POOL]
    rbd_name = self.unique_id[1]

    # We use "-" for exporting to stdout.
    return [constants.RBD_CMD, "export",
            "-p", rbd_pool,
            rbd_name, "-"]

  def GetUserspaceAccessUri(self, hypervisor):
    """Generate KVM userspace URIs to be used as `-drive file` settings.

    @see: L{BlockDev.GetUserspaceAccessUri}

    """
    if hypervisor == constants.HT_KVM:
      return "rbd:" + self.rbd_pool + "/" + self.rbd_name
    else:
      base.ThrowError("Hypervisor %s doesn't support RBD userspace access" %
                      hypervisor)


def _VerifyDiskType(dev_type):
  if dev_type not in DEV_MAP:
    raise errors.ProgrammerError("Invalid block device type '%s'" % dev_type)


def _VerifyDiskParams(disk):
  """Verifies if all disk parameters are set.

  """
  missing = set(constants.DISK_LD_DEFAULTS[disk.dev_type]) - set(disk.params)
  if missing:
    raise errors.ProgrammerError("Block device is missing disk parameters: %s" %
                                 missing)


def FindDevice(disk, children, **kwargs):
  """Search for an existing, assembled device.

  This will succeed only if the device exists and is assembled, but it
  does not do any actions in order to activate the device.

  @type disk: L{objects.Disk}
  @param disk: the disk object to find
  @type children: list of L{bdev.BlockDev}
  @param children: the list of block devices that are children of the device
                  represented by the disk parameter

  """
  _VerifyDiskType(disk.dev_type)
  device = DEV_MAP[disk.dev_type](disk.logical_id, children, disk.size,
                                  disk.params, disk.dynamic_params,
                                  name=disk.name, uuid=disk.uuid, **kwargs)
  if not device.attached:
    return None
  return device


def Assemble(disk, children):
  """Try to attach or assemble an existing device.

  This will attach to assemble the device, as needed, to bring it
  fully up. It must be safe to run on already-assembled devices.

  @type disk: L{objects.Disk}
  @param disk: the disk object to assemble
  @type children: list of L{bdev.BlockDev}
  @param children: the list of block devices that are children of the device
                  represented by the disk parameter

  """
  _VerifyDiskType(disk.dev_type)
  _VerifyDiskParams(disk)
  device = DEV_MAP[disk.dev_type](disk.logical_id, children, disk.size,
                                  disk.params, disk.dynamic_params,
                                  name=disk.name, uuid=disk.uuid)
  device.Assemble()
  return device


def Create(disk, children, excl_stor):
  """Create a device.

  @type disk: L{objects.Disk}
  @param disk: the disk object to create
  @type children: list of L{bdev.BlockDev}
  @param children: the list of block devices that are children of the device
                  represented by the disk parameter
  @type excl_stor: boolean
  @param excl_stor: Whether exclusive_storage is active
  @rtype: L{bdev.BlockDev}
  @return: the created device, or C{None} in case of an error

  """
  _VerifyDiskType(disk.dev_type)
  _VerifyDiskParams(disk)
  device = DEV_MAP[disk.dev_type].Create(disk.logical_id, children, disk.size,
                                         disk.spindles, disk.params, excl_stor,
                                         disk.dynamic_params,
                                         name=disk.name, uuid=disk.uuid)
  return device

# Please keep this at the bottom of the file for visibility.
DEV_MAP = {
  constants.DT_PLAIN: LogicalVolume,
  constants.DT_DRBD8: drbd.DRBD8Dev,
  constants.DT_BLOCK: PersistentBlockDevice,
  constants.DT_RBD: RADOSBlockDevice,
  constants.DT_EXT: ExtStorageDevice,
  constants.DT_FILE: FileStorage,
  constants.DT_SHARED_FILE: FileStorage,
  constants.DT_GLUSTER: GlusterStorage,
}
"""Map disk types to disk type classes.

@see: L{Assemble}, L{FindDevice}, L{Create}.""" # pylint: disable=W0105
