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

# Source Code for Module Products.ZenRRD.ComponentCommandParser

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2008, 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  from Products.ZenRRD.CommandParser import CommandParser
     12  from Products.ZenUtils.Utils import prepId as globalPrepId
     13  import re
     14  from pprint import pformat
     15  import logging
     16
     17  log = logging.getLogger("zen.ComponentCommandParser")
     18
     19  # A 'dp' proxy object from the COMMAND zenhub service CommandPerformanceConfig
     20  # contains:
     21  #
     22  # id                   - name of the datapoint
     23  # component            - name of the component
     24  # rrdPath              - path to filename
     25  # rrdType              - eg GAUGE, DERIVE
     26  # rrdCreateCommand     - how to create the RRD file if there isn't one
     27  # rrdMin               - min value
     28  # rrdMax               - max value
     29  # data                 - result of parser.dataForParser(comp, dp)
     30
     31 -class ComponentCommandParser(CommandParser):
     32
     33      # This default equates a 'part' of the output as being a line.
     34      # In other words, assume one line has data about one component.
     35      componentSplit = '\n'
     36
     37      # This item helps to find the component name in a 'part' (ie a line)
     38      # This MUST contain a regex which has a regex item called 'component'.
     39      #
     40      # eg     componentScanner = '% (?P<component>/.*)'
     41      #
     42      # The above says that a component entry starts with a '%'
     43      componentScanner = ''
     44
     45      # Once we've found a part that contains component data, a scanner
     46      # regex is used to match the part and return the name of the datapoint
     47      # to which the value should be stored.
     48      #
     49      # Scanners are regexes with regex search matches. eg
     50      #   r' (?P<totalBlocks>\d+) +(?P<usedBlocks>\d+) '
     51      scanners = ()
     52
     53      # What is the attribute of the component that matches the name from the command?
     54      # This will be used in the zenhub service to grab the attribute value.
     55      #
     56      # If this is 'id', then run prepId on the command output to match the name in ZODB.
     57      # Otherwise, the component name is assumed to not require cleaning.
     58      # Components with non-HTML friendly bits in them (eg ':?%/') will
     59      # need to be cleaned.  Examples are things like filesystems.
     60      componentScanValue = 'id'
     61
     62 -    def prepId(self, id, subchar='_'):
     63          return globalPrepId(id, subchar)
     64
     65 -    def dataForParser(self, context, dp):
     66          # This runs in the zenhub service, so it has access to the actual ZODB object
     67          return dict(componentScanValue = getattr(context, self.componentScanValue))
     68
     69 -    def processResults(self, cmd, result):
     70
     71          # Use the data from our proxy object to create a mapping from
     72          # the component name to datapoints.
     73          ifs = {}
     74          for dp in cmd.points:
     75              dp.component = dp.data['componentScanValue']
     76              points = ifs.setdefault(dp.component, {})
     77              points[dp.id] = dp
     78
     79          # Split command output into parts (typically lines)
     80          parts = cmd.result.output.split(self.componentSplit)
     81
     82          for part in parts:
     83              # Does this part (eg line) contain a component or not?
     84              match = re.search(self.componentScanner, part)
     85              if not match:
     86                  continue
     87
     88              # Search for the componentScanner regex 'component' item
     89              component = match.groupdict()['component'].strip()
     90              if self.componentScanValue == 'id':
     91                  component = self.prepId(component)
     92
     93              points = ifs.get(component, None)
     94              if not points:
     95                  continue
     96
     97              # Use the scanners to search for datapoints
     98              for search in self.scanners:
     99                  match = re.search(search, part)
    100                  if match:
    101                      for name, value in match.groupdict().items():
    102                          dp = points.get(name, None)
    103                          if dp is not None:
    104                              if value in ('-', ''): value = 0
    105                              result.values.append( (dp, float(value) ) )
    106
    107          log.debug(pformat(result))
    108          return result
    109