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

# Source Code for Module Products.ZenModel.BasicDataSource

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