Package Products :: Package ZenRRD :: Package parsers :: Module Nagios |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenRRD.parsers.Nagios

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2008, 2009, all rights reserved.
      4  #
      5  # This content is made available according to terms specified in
      6  # License.zenoss under the directory where your Zenoss product is installed.
      7  #
      8  ##############################################################################
      9
     10
     11  """Nagios
     12
     13  Uses the Nagios API defintions from
     14  http://nagios.sourceforge.net/docs/3_0/pluginapi.html and from
     15  http://nagiosplug.sourceforge.net/developer-guidelines.html#PLUGOUTPUT
     16  """
     17
     18  import re
     19
     20  from Products.ZenUtils.Utils import getExitMessage
     21  from Products.ZenRRD.CommandParser import CommandParser
     22
     23  # Performance datapoints syntax
     24  # Matches substrings having the form <key>=<value> with optional trailing
     25  # whitespace.  E.g. if this is the perf data:
     26  #
     27  #     rta=0.337000ms;180.000000;300.000000;0.000000 pl=0%;100;100;0.
     28  #
     29  # this is the output (using findall()):
     30  #
     31  # [('rta=0.337000ms;180.000000;300.000000;0.000000', 'rta', '', '0.337000'),
     32  #  ('pl=0%;100;100;0', 'pl', '', '0')]
     33  #
     34  perfParser = re.compile(r"""(([^ =']+|'([^']+)')=([-0-9.eE]+)\S*)""")
     35
     36
     37 -class _BadData(Exception):
     38      """
     39      Raised by splitMultLine when plugin output is not parseable.
     40      """
     41
     42
     43 -class Nagios(CommandParser):
     44
     45      @staticmethod
     46 -    def splitMultiLine(output):
     47          """
     48          Convert the plugin output into component parts:
     49               summary, performance_data
     50          Empty output or no performance data raises a _BadData exception.
     51          """
     52          output = output.strip()
     53          if not output:
     54              raise _BadData("No output from plugin")
     55
     56          # Expected format is:
     57          #
     58          #    <text>|<perf data>
     59          #    <extra text>
     60          #    <extra text>|<extra perf data>
     61          #    <extra perf data>
     62          #
     63          # The first line has text and, optionally, perf data.  Subsequent
     64          # lines will have the format of <text>|<perf> across multiple lines.
     65          lines = output.splitlines()
     66          firstLine = lines[0].strip()
     67          additionalLines = ' '.join(lines[1:])
     68          text, perf = [], []
     69          # Extract text and data from first line
     70          segments = firstLine.split('|')
     71          # If there are any segments, the first segment is text.
     72          if segments:
     73              text.append(segments.pop(0))
     74          # Extract additional text (due to bad pipe usage)
     75          while len(segments) > 1:
     76              text.append(segments.pop(0))
     77          # Extract the perf data (if exists)
     78          if segments:
     79              perf.append(segments.pop(0))
     80          # Now extract any additional data that may exist.
     81          if additionalLines:
     82              # Split text and perf data apart
     83              segments = additionalLines.split('|')
     84              # Extract text data (if any)
     85              if segments:
     86                  text.extend(segments.pop(0).splitlines())
     87              # Extract perf data (if any)
     88              if segments:
     89                  perf.extend(segments.pop(0).splitlines())
     90
     91          # No perf data is an error
     92          if not perf:
     93              raise _BadData("No performance data from plugin")
     94
     95          return text, perf
     96
     97 -    def processPerfData(self, rawPerfData):
     98          """
     99          Create a dictionary of datapoint:value entries from
    100          the plugin output.
    101          This funtion removes a ' (represented as '' in the label)
    102          from the label.  There's just too much opportunity to mess
    103          something up by keeping a shell meta-character.
    104          """
    105          perfData = {}
    106          all_data = ' '.join(rawPerfData)
    107          # Strip out all '' strings
    108          all_data = all_data.replace("''", "")
    109
    110          for _, label, quote_label, value in perfParser.findall(all_data):
    111              if quote_label:
    112                  label = quote_label
    113              try:
    114                  value = float(value.strip())
    115              except:
    116                  value = 'U'
    117              perfData[label] = value
    118
    119          return perfData
    120
    121 -    def processResults(self, cmd, result):
    122          output = cmd.result.output
    123          exitCode = cmd.result.exitCode
    124          severity = cmd.severity
    125          if exitCode == 0:
    126              severity = 0
    127          elif exitCode == 2:
    128              severity = min(severity + 1, 5)
    129
    130          evt = {
    131                  "device": cmd.deviceConfig.device,
    132                  "message": output,
    133                  "severity": severity,
    134                  "component": cmd.component,
    135                  "eventKey": cmd.eventKey,
    136                  "eventClass": cmd.eventClass,
    137              }
    138          try:
    139              summary, rawPerfData = self.splitMultiLine(output)
    140          except _BadData as ex:
    141              evt.update({
    142                  "error_codes": "Datasource: %s - Code: %s - Msg: %s" % (
    143                     cmd.name, exitCode, getExitMessage(exitCode)
    144                  ),
    145                  "performanceData": None,
    146                  "summary": str(ex),
    147              })
    148          else:
    149              evt.update({
    150                  "performanceData": rawPerfData,
    151                  "summary": summary,
    152              })
    153              perfData = self.processPerfData(rawPerfData)
    154              for dp in cmd.points:
    155                  if dp.id in perfData:
    156                      result.values.append((dp, perfData[dp.id]))
    157          result.events.append(evt)
    158