Package Products :: Package ZenModel :: Module BasicDataSource |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenModel.BasicDataSource

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2007, Zenoss Inc.
      5  #
      6  # This program is free software; you can redistribute it and/or modify it
      7  # under the terms of the GNU General Public License version 2 as published by
      8  # the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     11  #
     12  ###########################################################################
     13
     14  __doc__="""BasicDataSource
     15
     16  Defines attributes for how a datasource will be graphed
     17  and builds the nessesary DEF and CDEF statements for it.
     18  """
     19
     20  from Products.ZenModel import RRDDataSource
     21  from AccessControl import ClassSecurityInfo, Permissions
     22  from Globals import InitializeClass
     23  from Products.ZenEvents.ZenEventClasses import Cmd_Fail
     24  from Products.ZenUtils.Utils import executeStreamCommand
     25  from Products.ZenWidgets import messaging
     26  from copy import copy
     27  import cgi, time
     28
     29  snmptemplate = ("snmpwalk -c%(zSnmpCommunity)s "
     30                  "-%(zSnmpVer)s %(manageIp)s %(oid)s")
     31
     32 -def checkOid(oid):
     33      import string
     34      for c in string.whitespace:
     35          oid = oid.replace(c, '')
     36      oid = oid.strip('.')
     37      numbers = oid.split('.')
     38      map(int, numbers)
     39      if len(numbers) < 3:
     40          raise ValueError("OID too short")
     41      return oid
     42
     43
     44 -class BasicDataSource(RRDDataSource.SimpleRRDDataSource):
     45
     46      __pychecker__='no-override'
     47
     48      sourcetypes = ('SNMP', 'COMMAND')
     49
     50      sourcetype = 'SNMP'
     51      eventClass = Cmd_Fail
     52      oid = ''
     53      parser = "Auto"
     54
     55      usessh = False
     56
     57      _properties = RRDDataSource.RRDDataSource._properties + (
     58          {'id':'oid', 'type':'string', 'mode':'w'},
     59          {'id':'usessh', 'type':'boolean', 'mode':'w'},
     60          {'id':'parser', 'type':'string', 'mode':'w'},
     61          )
     62
     63      _relations = RRDDataSource.RRDDataSource._relations + (
     64          )
     65
     66      # Screen action bindings (and tab definitions)
     67      factory_type_information = (
     68      {
     69          'immediate_view' : 'editBasicDataSource',
     70          'actions'        :
     71          (
     72              { 'id'            : 'edit'
     73              , 'name'          : 'Data Source'
     74              , 'action'        : 'editBasicDataSource'
     75              , 'permissions'   : ( Permissions.view, )
     76              },
     77          )
     78      },
     79      )
     80
     81      security = ClassSecurityInfo()
     82
     83 -    def addDataPoints(self):
     84          """
     85          Overrides method defined in SimpleRRDDataSource. Only sync the
     86          datapoint with the datasource if the datasource type is SNMP.
     87          """
     88          if self.sourcetype == 'SNMP':
     89              RRDDataSource.SimpleRRDDataSource.addDataPoints(self)
     90
     91 -    def getDescription(self):
     92          if self.sourcetype == "SNMP":
     93              return self.oid
     94          if self.sourcetype == "COMMAND":
     95              if self.usessh:
     96                  return self.commandTemplate + " over SSH"
     97              else:
     98                  return self.commandTemplate
     99          return RRDDataSource.RRDDataSource.getDescription(self)
    100
    101
    102 -    def useZenCommand(self):
    103          if self.sourcetype == 'COMMAND':
    104              return True
    105          return False
    106
    107
    108 -    def zmanage_editProperties(self, REQUEST=None):
    109          'add some validation'
    110          if REQUEST:
    111              oid = REQUEST.get('oid', '')
    112              if oid:
    113                  try:
    114                      REQUEST.form['oid'] = checkOid(oid)
    115                  except ValueError:
    116                      messaging.IMessageSender(self).sendToBrowser(
    117                          'Invalid OID',
    118                          "%s is an invalid OID." % oid,
    119                          priority=messaging.WARNING
    120                      )
    121                      return self.callZenScreen(REQUEST)
    122
    123          return RRDDataSource.SimpleRRDDataSource.zmanage_editProperties(
    124                                                                  self, REQUEST)
    125
    126      security.declareProtected('Change Device', 'manage_testDataSource')
    127 -    def manage_testDataSource(self, testDevice, REQUEST):
    128          ''' Test the datasource by executing the command and outputting the
    129          non-quiet results.
    130          '''
    131          out = REQUEST.RESPONSE
    132
    133          def write(lines):
    134              ''' Output (maybe partial) result text.
    135              '''
    136              # Looks like firefox renders progressive output more smoothly
    137              # if each line is stuck into a table row.
    138              startLine = '<tr><td class="tablevalues">'
    139              endLine = '</td></tr>\n'
    140              if out:
    141                  if not isinstance(lines, list):
    142                      lines = [lines]
    143                  for l in lines:
    144                      if not isinstance(l, str):
    145                          l = str(l)
    146                      l = l.strip()
    147                      l = cgi.escape(l)
    148                      l = l.replace('\n', endLine + startLine)
    149                      out.write(startLine + l + endLine)
    150
    151          # Determine which device to execute against
    152          device = None
    153          if testDevice:
    154              # Try to get specified device
    155              device = self.findDevice(testDevice)
    156              if not device:
    157                  messaging.IMessageSender(self).sendToBrowser(
    158                      'No device found',
    159                      'Cannot find device matching %s.' % testDevice,
    160                      priority=messaging.WARNING
    161                  )
    162                  return self.callZenScreen(REQUEST)
    163          elif hasattr(self, 'device'):
    164              # ds defined on a device, use that device
    165              device = self.device()
    166          elif hasattr(self, 'getSubDevicesGen'):
    167              # ds defined on a device class, use any device from the class
    168              try:
    169                  device = self.getSubDevicesGen().next()
    170              except StopIteration:
    171                  # No devices in this class, bail out
    172                  pass
    173          if not device:
    174              messaging.IMessageSender(self).sendToBrowser(
    175                  'No Testable Device',
    176                  'Cannot determine a device against which to test.',
    177                  priority=messaging.WARNING
    178              )
    179              return self.callZenScreen(REQUEST)
    180
    181          # Get the command to run
    182          command = None
    183          if self.sourcetype=='COMMAND':
    184              command = self.getCommand(device)
    185          elif self.sourcetype=='SNMP':
    186              snmpinfo = copy(device.getSnmpConnInfo().__dict__)
    187              snmpinfo['oid'] = self.getDescription()
    188              command = snmptemplate % snmpinfo
    189          else:
    190              messaging.IMessageSender(self).sendToBrowser(
    191                  'Test Failed',
    192                  'Unable to test %s datasources' % self.sourcetype,
    193                  priority=messaging.WARNING
    194              )
    195              return self.callZenScreen(REQUEST)
    196          if not command:
    197              messaging.IMessageSender(self).sendToBrowser(
    198                  'Test Failed',
    199                  'Unable to create test command.',
    200                  priority=messaging.WARNING
    201              )
    202              return self.callZenScreen(REQUEST)
    203
    204          # Render
    205          header, footer = self.commandTestOutput().split('OUTPUT_TOKEN')
    206          out.write(str(header))
    207
    208          write("Executing command\n%s\n   against %s" % (command, device.id))
    209          write('')
    210          start = time.time()
    211          try:
    212              executeStreamCommand(command, write)
    213          except:
    214              import sys
    215              write('exception while executing command')
    216              write('type: %s  value: %s' % tuple(sys.exc_info()[:2]))
    217          write('')
    218          write('')
    219          write('DONE in %s seconds' % long(time.time() - start))
    220          out.write(str(footer))
    221
    222 -    def parsers(self):
    223          from Products.DataCollector.Plugins import loadParserPlugins
    224          return sorted([p.modPath for p in loadParserPlugins(self.getDmd())])
    225
    226
    227
    228  InitializeClass(BasicDataSource)
    229