#
#

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


"""DRBD information parsing utilities"""

import errno
import pyparsing as pyp
import re

from ganeti import constants
from ganeti import utils
from ganeti import errors
from ganeti import compat
from ganeti.storage import base


class DRBD8Status(object): # pylint: disable=R0902
  """A DRBD status representation class.

  Note that this class is meant to be used to parse one of the entries returned
  from L{DRBD8Info._JoinLinesPerMinor}.

  """
  UNCONF_RE = re.compile(r"\s*[0-9]+:\s*cs:Unconfigured$")
  LINE_RE = re.compile(r"\s*[0-9]+:\s*cs:(\S+)\s+(?:st|ro):([^/]+)/(\S+)"
                       r"\s+ds:([^/]+)/(\S+)\s+.*$")
  SYNC_RE = re.compile(r"^.*\ssync'ed:\s*([0-9.]+)%.*"
                       # Due to a bug in drbd in the kernel, introduced in
                       # commit 4b0715f096 (still unfixed as of 2011-08-22)
                       r"(?:\s|M)"
                       r"finish: ([0-9]+):([0-9]+):([0-9]+)\s.*$")

  CS_UNCONFIGURED = "Unconfigured"
  CS_STANDALONE = "StandAlone"
  CS_WFCONNECTION = "WFConnection"
  CS_WFREPORTPARAMS = "WFReportParams"
  CS_CONNECTED = "Connected"
  CS_STARTINGSYNCS = "StartingSyncS"
  CS_STARTINGSYNCT = "StartingSyncT"
  CS_WFBITMAPS = "WFBitMapS"
  CS_WFBITMAPT = "WFBitMapT"
  CS_WFSYNCUUID = "WFSyncUUID"
  CS_SYNCSOURCE = "SyncSource"
  CS_SYNCTARGET = "SyncTarget"
  CS_PAUSEDSYNCS = "PausedSyncS"
  CS_PAUSEDSYNCT = "PausedSyncT"
  CSET_SYNC = compat.UniqueFrozenset([
    CS_WFREPORTPARAMS,
    CS_STARTINGSYNCS,
    CS_STARTINGSYNCT,
    CS_WFBITMAPS,
    CS_WFBITMAPT,
    CS_WFSYNCUUID,
    CS_SYNCSOURCE,
    CS_SYNCTARGET,
    CS_PAUSEDSYNCS,
    CS_PAUSEDSYNCT,
    ])

  DS_DISKLESS = "Diskless"
  DS_ATTACHING = "Attaching" # transient state
  DS_FAILED = "Failed" # transient state, next: diskless
  DS_NEGOTIATING = "Negotiating" # transient state
  DS_INCONSISTENT = "Inconsistent" # while syncing or after creation
  DS_OUTDATED = "Outdated"
  DS_DUNKNOWN = "DUnknown" # shown for peer disk when not connected
  DS_CONSISTENT = "Consistent"
  DS_UPTODATE = "UpToDate" # normal state

  RO_PRIMARY = "Primary"
  RO_SECONDARY = "Secondary"
  RO_UNKNOWN = "Unknown"

  def __init__(self, procline):
    u = self.UNCONF_RE.match(procline)
    if u:
      self.cstatus = self.CS_UNCONFIGURED
      self.lrole = self.rrole = self.ldisk = self.rdisk = None
    else:
      m = self.LINE_RE.match(procline)
      if not m:
        raise errors.BlockDeviceError("Can't parse input data '%s'" % procline)
      self.cstatus = m.group(1)
      self.lrole = m.group(2)
      self.rrole = m.group(3)
      self.ldisk = m.group(4)
      self.rdisk = m.group(5)

    # end reading of data from the LINE_RE or UNCONF_RE

    self.is_standalone = self.cstatus == self.CS_STANDALONE
    self.is_wfconn = self.cstatus == self.CS_WFCONNECTION
    self.is_connected = self.cstatus == self.CS_CONNECTED
    self.is_unconfigured = self.cstatus == self.CS_UNCONFIGURED
    self.is_primary = self.lrole == self.RO_PRIMARY
    self.is_secondary = self.lrole == self.RO_SECONDARY
    self.peer_primary = self.rrole == self.RO_PRIMARY
    self.peer_secondary = self.rrole == self.RO_SECONDARY
    self.both_primary = self.is_primary and self.peer_primary
    self.both_secondary = self.is_secondary and self.peer_secondary

    self.is_diskless = self.ldisk == self.DS_DISKLESS
    self.is_disk_uptodate = self.ldisk == self.DS_UPTODATE
    self.peer_disk_uptodate = self.rdisk == self.DS_UPTODATE

    self.is_in_resync = self.cstatus in self.CSET_SYNC
    self.is_in_use = self.cstatus != self.CS_UNCONFIGURED

    m = self.SYNC_RE.match(procline)
    if m:
      self.sync_percent = float(m.group(1))
      hours = int(m.group(2))
      minutes = int(m.group(3))
      seconds = int(m.group(4))
      self.est_time = hours * 3600 + minutes * 60 + seconds
    else:
      # we have (in this if branch) no percent information, but if
      # we're resyncing we need to 'fake' a sync percent information,
      # as this is how cmdlib determines if it makes sense to wait for
      # resyncing or not
      if self.is_in_resync:
        self.sync_percent = 0
      else:
        self.sync_percent = None
      self.est_time = None

  def __repr__(self):
    return ("<%s: cstatus=%s, lrole=%s, rrole=%s, ldisk=%s, rdisk=%s>" %
            (self.__class__, self.cstatus, self.lrole, self.rrole,
             self.ldisk, self.rdisk))


class DRBD8Info(object):
  """Represents information DRBD exports (usually via /proc/drbd).

  An instance of this class is created by one of the CreateFrom... methods.

  """

  _VERSION_RE = re.compile(r"^version: (\d+)\.(\d+)\.(\d+)(?:\.(\d+))?"
                           r" \(api:(\d+)/proto:(\d+)(?:-(\d+))?\)")
  _VALID_LINE_RE = re.compile("^ *([0-9]+): cs:([^ ]+).*$")

  def __init__(self, lines):
    self._version = self._ParseVersion(lines)
    self._minors, self._line_per_minor = self._JoinLinesPerMinor(lines)

  def GetVersion(self):
    """Return the DRBD version.

    This will return a dict with keys:
      - k_major
      - k_minor
      - k_point
      - k_fix (only on some drbd versions)
      - api
      - proto
      - proto2 (only on drbd > 8.2.X)

    """
    return self._version

  def GetVersionString(self):
    """Return the DRBD version as a single string.

    """
    version = self.GetVersion()
    retval = "%d.%d.%d" % \
             (version["k_major"], version["k_minor"], version["k_point"])
    if "k_fix" in version:
      retval += ".%s" % version["k_fix"]

    retval += " (api:%d/proto:%d" % (version["api"], version["proto"])
    if "proto2" in version:
      retval += "-%s" % version["proto2"]
    retval += ")"
    return retval

  def GetMinors(self):
    """Return a list of minor for which information is available.

    This list is ordered in exactly the order which was found in the underlying
    data.

    """
    return self._minors

  def HasMinorStatus(self, minor):
    return minor in self._line_per_minor

  def GetMinorStatus(self, minor):
    return DRBD8Status(self._line_per_minor[minor])

  def _ParseVersion(self, lines):
    first_line = lines[0].strip()
    version = self._VERSION_RE.match(first_line)
    if not version:
      raise errors.BlockDeviceError("Can't parse DRBD version from '%s'" %
                                    first_line)

    values = version.groups()
    retval = {
      "k_major": int(values[0]),
      "k_minor": int(values[1]),
      "k_point": int(values[2]),
      "api": int(values[4]),
      "proto": int(values[5]),
      }
    if values[3] is not None:
      retval["k_fix"] = values[3]
    if values[6] is not None:
      retval["proto2"] = values[6]

    return retval

  def _JoinLinesPerMinor(self, lines):
    """Transform the raw lines into a dictionary based on the minor.

    @return: a dictionary of minor: joined lines from /proc/drbd
        for that minor

    """
    minors = []
    results = {}
    old_minor = old_line = None
    for line in lines:
      if not line: # completely empty lines, as can be returned by drbd8.0+
        continue
      lresult = self._VALID_LINE_RE.match(line)
      if lresult is not None:
        if old_minor is not None:
          minors.append(old_minor)
          results[old_minor] = old_line
        old_minor = int(lresult.group(1))
        old_line = line
      else:
        if old_minor is not None:
          old_line += " " + line.strip()
    # add last line
    if old_minor is not None:
      minors.append(old_minor)
      results[old_minor] = old_line
    return minors, results

  @staticmethod
  def CreateFromLines(lines):
    return DRBD8Info(lines)

  @staticmethod
  def CreateFromFile(filename=constants.DRBD_STATUS_FILE):
    try:
      lines = utils.ReadFile(filename).splitlines()
    except EnvironmentError, err:
      if err.errno == errno.ENOENT:
        base.ThrowError("The file %s cannot be opened, check if the module"
                        " is loaded (%s)", filename, str(err))
      else:
        base.ThrowError("Can't read the DRBD proc file %s: %s",
                        filename, str(err))
    if not lines:
      base.ThrowError("Can't read any data from %s", filename)
    return DRBD8Info.CreateFromLines(lines)


class BaseShowInfo(object):
  """Base class for parsing the `drbdsetup show` output.

  Holds various common pyparsing expressions which are used by subclasses. Also
  provides caching of the constructed parser.

  """
  _PARSE_SHOW = None

  # pyparsing setup
  _lbrace = pyp.Literal("{").suppress()
  _rbrace = pyp.Literal("}").suppress()
  _lbracket = pyp.Literal("[").suppress()
  _rbracket = pyp.Literal("]").suppress()
  _semi = pyp.Literal(";").suppress()
  _colon = pyp.Literal(":").suppress()
  # this also converts the value to an int
  _number = pyp.Word(pyp.nums).setParseAction(lambda s, l, t: int(t[0]))

  _comment = pyp.Literal("#") + pyp.Optional(pyp.restOfLine)
  _defa = pyp.Literal("_is_default").suppress()
  _dbl_quote = pyp.Literal('"').suppress()

  _keyword = pyp.Word(pyp.alphanums + "-")

  # value types
  _value = pyp.Word(pyp.alphanums + "_-/.:")
  _quoted = _dbl_quote + pyp.CharsNotIn('"') + _dbl_quote
  _ipv4_addr = (pyp.Optional(pyp.Literal("ipv4")).suppress() +
                pyp.Word(pyp.nums + ".") + _colon + _number)
  _ipv6_addr = (pyp.Optional(pyp.Literal("ipv6")).suppress() +
                pyp.Optional(_lbracket) + pyp.Word(pyp.hexnums + ":") +
                pyp.Optional(_rbracket) + _colon + _number)
  # meta device, extended syntax
  _meta_value = ((_value ^ _quoted) + _lbracket + _number + _rbracket)
  # device name, extended syntax
  _device_value = pyp.Literal("minor").suppress() + _number

  # a statement
  _stmt = (~_rbrace + _keyword + ~_lbrace +
           pyp.Optional(_ipv4_addr ^ _ipv6_addr ^ _value ^ _quoted ^
                        _meta_value ^ _device_value) +
           pyp.Optional(_defa) + _semi +
           pyp.Optional(pyp.restOfLine).suppress())

  @classmethod
  def GetDevInfo(cls, show_data):
    """Parse details about a given DRBD minor.

    This returns, if available, the local backing device (as a path)
    and the local and remote (ip, port) information from a string
    containing the output of the `drbdsetup show` command as returned
    by DRBD8Dev._GetShowData.

    This will return a dict with keys:
      - local_dev
      - meta_dev
      - meta_index
      - local_addr
      - remote_addr

    """
    if not show_data:
      return {}

    try:
      # run pyparse
      results = (cls._GetShowParser()).parseString(show_data)
    except pyp.ParseException, err:
      base.ThrowError("Can't parse drbdsetup show output: %s", str(err))

    return cls._TransformParseResult(results)

  @classmethod
  def _TransformParseResult(cls, parse_result):
    raise NotImplementedError

  @classmethod
  def _GetShowParser(cls):
    """Return a parser for `drbd show` output.

    This will either create or return an already-created parser for the
    output of the command `drbd show`.

    """
    if cls._PARSE_SHOW is None:
      cls._PARSE_SHOW = cls._ConstructShowParser()

    return cls._PARSE_SHOW

  @classmethod
  def _ConstructShowParser(cls):
    raise NotImplementedError


class DRBD83ShowInfo(BaseShowInfo):
  @classmethod
  def _ConstructShowParser(cls):
    # an entire section
    section_name = pyp.Word(pyp.alphas + "_")
    section = section_name + \
              cls._lbrace + \
              pyp.ZeroOrMore(pyp.Group(cls._stmt)) + \
              cls._rbrace

    bnf = pyp.ZeroOrMore(pyp.Group(section ^ cls._stmt))
    bnf.ignore(cls._comment)

    return bnf

  @classmethod
  def _TransformParseResult(cls, parse_result):
    retval = {}
    for section in parse_result:
      sname = section[0]
      if sname == "_this_host":
        for lst in section[1:]:
          if lst[0] == "disk":
            retval["local_dev"] = lst[1]
          elif lst[0] == "meta-disk":
            retval["meta_dev"] = lst[1]
            retval["meta_index"] = lst[2]
          elif lst[0] == "address":
            retval["local_addr"] = tuple(lst[1:])
      elif sname == "_remote_host":
        for lst in section[1:]:
          if lst[0] == "address":
            retval["remote_addr"] = tuple(lst[1:])
    return retval


class DRBD84ShowInfo(BaseShowInfo):
  @classmethod
  def _ConstructShowParser(cls):
    # an entire section (sections can be nested in DRBD 8.4, and there exist
    # sections like "volume 0")
    section_name = pyp.Word(pyp.alphas + "_") + \
                   pyp.Optional(pyp.Word(pyp.nums)).suppress() # skip volume idx
    section = pyp.Forward()
    # pylint: disable=W0106
    section << (section_name +
                cls._lbrace +
                pyp.ZeroOrMore(pyp.Group(cls._stmt ^ section)) +
                cls._rbrace)

    resource_name = pyp.Word(pyp.alphanums + "_-.")
    resource = (pyp.Literal("resource") + resource_name).suppress() + \
               cls._lbrace + \
               pyp.ZeroOrMore(pyp.Group(section)) + \
               cls._rbrace

    resource.ignore(cls._comment)

    return resource

  @classmethod
  def _TransformVolumeSection(cls, vol_content, retval):
    for entry in vol_content:
      if entry[0] == "disk" and len(entry) == 2 and \
          isinstance(entry[1], basestring):
        retval["local_dev"] = entry[1]
      elif entry[0] == "meta-disk":
        if len(entry) > 1:
          retval["meta_dev"] = entry[1]
        if len(entry) > 2:
          retval["meta_index"] = entry[2]

  @classmethod
  def _TransformParseResult(cls, parse_result):
    retval = {}
    for section in parse_result:
      sname = section[0]
      if sname == "_this_host":
        for lst in section[1:]:
          if lst[0] == "address":
            retval["local_addr"] = tuple(lst[1:])
          elif lst[0] == "volume":
            cls._TransformVolumeSection(lst[1:], retval)
      elif sname == "_remote_host":
        for lst in section[1:]:
          if lst[0] == "address":
            retval["remote_addr"] = tuple(lst[1:])
    return retval
