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

# Source Code for Module Products.ZenModel.RRDDataSource

      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 or (at your
      8  # option) any later version as published by the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     11  #
     12  ###########################################################################
     13  from Products.ZenUtils.Utils import binPath
     14
     15  __doc__="""RRDDataSource
     16
     17  Base class for DataSources
     18  """
     19
     20  import os
     21  import zope.component
     22
     23  from DateTime import DateTime
     24  from AccessControl import ClassSecurityInfo, Permissions
     25  from Products.ZenModel.ZenossSecurity import ZEN_MANAGE_DMD
     26
     27  from Products.PageTemplates.Expressions import getEngine
     28
     29  from Products.ZenUtils.ZenTales import talesCompile
     30  from Products.ZenRelations.RelSchema import *
     31  from Products.ZenWidgets import messaging
     32
     33  from ZenModelRM import ZenModelRM
     34  from ZenPackable import ZenPackable
     35
     36
     37 -class RRDDataSource(ZenModelRM, ZenPackable):
     38
     39      meta_type = 'RRDDataSource'
     40
     41      paramtypes = ('integer', 'string', 'float')
     42      sourcetypes = ()
     43
     44      sourcetype = None
     45      enabled = True
     46      component = ''
     47      eventClass = ''
     48      eventKey = ''
     49      severity = 3
     50      commandTemplate = ""
     51      cycletime = 300
     52
     53      _properties = (
     54          {'id':'sourcetype', 'type':'selection',
     55          'select_variable' : 'sourcetypes', 'mode':'w'},
     56          {'id':'enabled', 'type':'boolean', 'mode':'w'},
     57          {'id':'component', 'type':'string', 'mode':'w'},
     58          {'id':'eventClass', 'type':'string', 'mode':'w'},
     59          {'id':'eventKey', 'type':'string', 'mode':'w'},
     60          {'id':'severity', 'type':'int', 'mode':'w'},
     61          {'id':'commandTemplate', 'type':'string', 'mode':'w'},
     62          {'id':'cycletime', 'type':'int', 'mode':'w'},
     63          )
     64
     65      _relations = ZenPackable._relations + (
     66          ("rrdTemplate", ToOne(ToManyCont,"Products.ZenModel.RRDTemplate","datasources")),
     67          ("datapoints", ToManyCont(ToOne,"Products.ZenModel.RRDDataPoint","datasource")),
     68          )
     69
     70      # Screen action bindings (and tab definitions)
     71      factory_type_information = (
     72      {
     73          'immediate_view' : 'editRRDDataSource',
     74          'actions'        :
     75          (
     76              { 'id'            : 'edit'
     77              , 'name'          : 'Data Source'
     78              , 'action'        : 'editRRDDataSource'
     79              , 'permissions'   : ( Permissions.view, )
     80              },
     81          )
     82      },
     83      )
     84
     85      security = ClassSecurityInfo()
     86
     87
     88 -    def breadCrumbs(self, terminator='dmd'):
     89          """Return the breadcrumb links for this object add ActionRules list.
     90          [('url','id'), ...]
     91          """
     92          from RRDTemplate import crumbspath
     93          crumbs = super(RRDDataSource, self).breadCrumbs(terminator)
     94          return crumbspath(self.rrdTemplate(), crumbs, -2)
     95
     96
     97 -    def getDescription(self):
     98          return None
     99
    100
    101 -    def getRRDDataPoints(self):
    102          return self.datapoints()
    103
    104
    105 -    def useZenCommand(self):
    106          return False
    107
    108 -    def addDataPoints(self):
    109          """Abstract hook method, to be overridden in derived classes."""
    110          pass
    111
    112      security.declareProtected(ZEN_MANAGE_DMD, 'manage_addRRDDataPoint')
    113 -    def manage_addRRDDataPoint(self, id, REQUEST = None):
    114          """make a RRDDataPoint"""
    115          if not id:
    116              return self.callZenScreen(REQUEST)
    117          from Products.ZenModel.RRDDataPoint import RRDDataPoint
    118          dp = RRDDataPoint(id)
    119          self.datapoints._setObject(dp.id, dp)
    120          dp = self.datapoints._getOb(dp.id)
    121          if REQUEST:
    122              if dp:
    123                  url = '%s/datapoints/%s' % (self.getPrimaryUrlPath(), dp.id)
    124                  REQUEST['RESPONSE'].redirect(url)
    125              return self.callZenScreen(REQUEST)
    126          return dp
    127
    128
    129      security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteRRDDataPoints')
    130 -    def manage_deleteRRDDataPoints(self, ids=(), REQUEST=None):
    131          """Delete RRDDataPoints from this RRDDataSource"""
    132
    133          def clean(rel, id):
    134              for obj in rel():
    135                  if id in obj.dsnames:
    136                      obj.dsnames.remove(id)
    137                      if not obj.dsnames:
    138                          rel._delObject(obj.id)
    139
    140          if not ids: return self.callZenScreen(REQUEST)
    141          for id in ids:
    142              dp = getattr(self.datapoints,id,False)
    143              if dp:
    144                  if getattr(self, 'device', False):
    145                      perfConf = self.device().getPerformanceServer()
    146                      perfConf.deleteRRDFiles(device=self.device().id, datapoint=dp.name())
    147                  else:
    148                      for d in self.deviceClass.obj.getSubDevicesGen():
    149                          perfConf = d.getPerformanceServer()
    150                          perfConf.deleteRRDFiles(device=d.id, datapoint=dp.name())
    151
    152                  clean(self.graphs, dp.name())
    153                  clean(self.thresholds, dp.name())
    154                  self.datapoints._delObject(dp.id)
    155
    156          if REQUEST:
    157              return self.callZenScreen(REQUEST)
    158
    159
    160      security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataPointsToGraphs')
    161 -    def manage_addDataPointsToGraphs(self, ids=(), graphIds=(), REQUEST=None):
    162          """
    163          Create GraphPoints for all datapoints given datapoints (ids)
    164          in each of the graphDefs (graphIds.)
    165          If a graphpoint already exists for a datapoint in a graphDef then
    166          don't create a 2nd one.
    167          """
    168          newGps = []
    169          for graphDefId in graphIds:
    170              graphDef = self.rrdTemplate.graphDefs._getOb(graphDefId, None)
    171              if graphDef:
    172                  for dpId in ids:
    173                      dp = self.datapoints._getOb(dpId, None)
    174                      if dp and not graphDef.isDataPointGraphed(dp.name()):
    175                          newGps += graphDef.manage_addDataPointGraphPoints(
    176                                                                  [dp.name()])
    177          if REQUEST:
    178              numNew = len(newGps)
    179              messaging.IMessageSender(self).sendToBrowser(
    180                  'Graph Points Added',
    181                  '%s GraphPoint%s added' % (numNew, numNew != 1 and 's' or '')
    182              )
    183              return self.callZenScreen(REQUEST)
    184          return newGps
    185
    186
    187 -    def getCommand(self, context, cmd=None):
    188          """Return localized command target.
    189          """
    190          # Perform a TALES eval on the expression using self
    191          if cmd is None:
    192              cmd = self.commandTemplate
    193          if not cmd.startswith('string:') and not cmd.startswith('python:'):
    194              cmd = 'string:%s' % cmd
    195          compiled = talesCompile(cmd)
    196          d = context.device()
    197          environ = {'dev' : d,
    198                     'device': d,
    199                     'devname': d.id,
    200                     'ds': self,
    201                     'datasource': self,
    202                     'here' : context,
    203                     'zCommandPath' : context.zCommandPath,
    204                     'nothing' : None,
    205                     'now' : DateTime() }
    206          res = compiled(getEngine().getContext(environ))
    207          if isinstance(res, Exception):
    208              raise res
    209          res = self.checkCommandPrefix(context, res)
    210          return res
    211
    212
    213 -    def getComponent(self, context, component=None):
    214          """Return localized component.
    215          """
    216          if component is None:
    217              component = self.component
    218          if not component.startswith('string:') and \
    219                  not component.startswith('python:'):
    220              component = 'string:%s' % component
    221          compiled = talesCompile(component)
    222          d = context.device()
    223          environ = {'dev' : d,
    224                     'device': d,
    225                     'devname': d.id,
    226                     'here' : context,
    227                     'nothing' : None,
    228                     'now' : DateTime() }
    229          res = compiled(getEngine().getContext(environ))
    230          if isinstance(res, Exception):
    231              raise res
    232          return res
    233
    234 -    def checkCommandPrefix(self, context, cmd):
    235          if not cmd.startswith('/') and not cmd.startswith('$'):
    236              if context.zCommandPath and not cmd.startswith(context.zCommandPath):
    237                  cmd = os.path.join(context.zCommandPath, cmd)
    238              elif binPath(cmd.split(" ",1)[0]):
    239                  #if we get here it is because cmd is not absolute, doesn't
    240                  #start with $, zCommandPath is not set and we found cmd in
    241                  #one of the zenoss bin dirs
    242                  cmdList = cmd.split(" ",1) #split into command and args
    243                  cmd = binPath(cmdList[0])
    244                  if len(cmdList) > 1:
    245                      cmd = "%s %s" % (cmd, cmdList[1])
    246
    247          return cmd
    248
    249 -    def getSeverityString(self):
    250          return self.ZenEventManager.getSeverityString(self.severity)
    251
    252
    253 -    def zmanage_editProperties(self, REQUEST=None, ignored=None):
    254          return ZenModelRM.zmanage_editProperties(self, REQUEST)
    255
    256
    257 -class SimpleRRDDataSource(RRDDataSource):
    258      """
    259      A SimpleRRDDataSource has a single datapoint that shares the name of the
    260      data source.
    261      """
    262      security = ClassSecurityInfo()
    263
    264
    265 -    def addDataPoints(self):
    266          """
    267          Make sure there is exactly one datapoint and that it has the same name
    268          as the datasource.
    269          """
    270          dpid = self.prepId(self.id)
    271          remove = [d for d in self.datapoints() if d.id != dpid]
    272          for dp in remove:
    273              self.datapoints._delObject(dp.id)
    274          if not self.datapoints._getOb(dpid, None):
    275              self.manage_addRRDDataPoint(dpid)
    276
    277      security.declareProtected(ZEN_MANAGE_DMD, 'zmanage_editProperties')
    278 -    def zmanage_editProperties(self, REQUEST=None):
    279          """
    280          Overrides the method defined in RRDDataSource. Called when user clicks
    281          the Save button on the Data Source editor page.
    282          """
    283          self.addDataPoints()
    284
    285          if REQUEST and self.datapoints():
    286
    287              datapoint = self.soleDataPoint()
    288
    289              if REQUEST.has_key('rrdtype'):
    290                  if REQUEST['rrdtype'] in datapoint.rrdtypes:
    291                      datapoint.rrdtype = REQUEST['rrdtype']
    292                  else:
    293                      messaging.IMessageSender(self).sendToBrowser(
    294                          'Error',
    295                          "%s is an invalid Type" % rrdtype,
    296                          priority=messaging.WARNING
    297                      )
    298                      return self.callZenScreen(REQUEST)
    299
    300              if REQUEST.has_key('rrdmin'):
    301                  value = REQUEST['rrdmin']
    302                  if value != '':
    303                      try:
    304                          value = long(value)
    305                      except ValueError:
    306                          messaging.IMessageSender(self).sendToBrowser(
    307                              'Error',
    308                              "%s is an invalid RRD Min" % value,
    309                              priority=messaging.WARNING
    310                          )
    311                          return self.callZenScreen(REQUEST)
    312                  datapoint.rrdmin = value
    313
    314              if REQUEST.has_key('rrdmax'):
    315                  value = REQUEST['rrdmax']
    316                  if value != '':
    317                      try:
    318                          value = long(value)
    319                      except ValueError:
    320                          messaging.IMessageSender(self).sendToBrowser(
    321                              'Error',
    322                              "%s is an invalid RRD Max" % value,
    323                              priority=messaging.WARNING
    324                          )
    325                          return self.callZenScreen(REQUEST)
    326                  datapoint.rrdmax = value
    327
    328              if REQUEST.has_key('createCmd'):
    329                  datapoint.createCmd = REQUEST['createCmd']
    330
    331          return RRDDataSource.zmanage_editProperties(self, REQUEST)
    332
    333 -    def soleDataPoint(self):
    334          """
    335          Return the datasource's only datapoint
    336          """
    337          dps = self.datapoints()
    338          if dps:
    339              return dps[0]
    340
    341 -    def aliases(self):
    342          """
    343          Return the datapoint aliases that belong to the datasource's only
    344          datapoint
    345          """
    346          dp = self.soleDataPoint()
    347          if dp:
    348              return dp.aliases()
    349
    350      security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataPointsToGraphs')
    351 -    def manage_addDataPointsToGraphs(self, ids=(), graphIds=(), REQUEST=None):
    352          """
    353          Override method in super class.  ids will always be an empty tuple, so
    354          call the super class's method with the single datapoint as the ids.
    355          """
    356          return RRDDataSource.manage_addDataPointsToGraphs(self,
    357                  (self.soleDataPoint().id,), graphIds, REQUEST)
    358
    359      security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataPointAlias')
    360 -    def manage_addDataPointAlias(self, id, formula, REQUEST=None):
    361          """
    362          Add a datapoint alias to the datasource's only datapoint
    363          """
    364          alias = self.soleDataPoint().manage_addDataPointAlias( id, formula )
    365          if REQUEST:
    366              return self.callZenScreen( REQUEST )
    367          return alias
    368
    369      security.declareProtected(ZEN_MANAGE_DMD, 'manage_removeDataPointAliases')
    370 -    def manage_removeDataPointAliases(self, ids=(), REQUEST=None):
    371          """
    372          Remove the passed aliases from the datasource's only datapoint
    373          """
    374          self.soleDataPoint().manage_removeDataPointAliases( ids )
    375          if REQUEST:
    376              return self.callZenScreen(REQUEST)
    377
    378  from Products.ZenModel.interfaces import IZenDocProvider
    379  from Products.ZenModel.ZenModelBase import ZenModelZenDocProvider
    380
    381 -class SimpleRRDDataSourceZenDocProvider(ZenModelZenDocProvider):
    382      zope.component.adapts(SimpleRRDDataSource)
    383
    384 -    def datapoints(self):
    385          return self._underlyingObject.datapoints()
    386
    387 -    def soleDataPoint(self):
    388          return self._underlyingObject.soleDataPoint()
    389
    390 -    def getZendoc(self):
    391          if len( self.datapoints() ) == 1:
    392              dataPointAdapter = zope.component.queryAdapter( self.soleDataPoint(),
    393                                                              IZenDocProvider )
    394              return dataPointAdapter.getZendoc()
    395          else:
    396              return super( SimpleRRDDataSourceZenDocProvider, self ).getZendoc()
    397
    398 -    def setZendoc(self, zendocText):
    399          """Set zendoc text"""
    400          if len( self.datapoints() ) == 1:
    401              dataPointAdapter = zope.component.queryAdapter( self.soleDataPoint(),
    402                                                              IZenDocProvider )
    403              dataPointAdapter.setZendoc( zendocText )
    404          else:
    405              return super( SimpleRRDDataSourceZenDocProvider, self ).setZendoc( zendocText )
    406