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

# Source Code for Module Products.ZenModel.GraphPoint

      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__="""GraphPoint
     15
     16  Defines attributes for how a data source will be graphed
     17  and builds the nessesary rrd commands.
     18  """
     19
     20  from Globals import InitializeClass
     21  from AccessControl import ClassSecurityInfo, Permissions
     22  from Products.ZenModel.ZenossSecurity import *
     23  from Products.ZenRelations.RelSchema import *
     24  from ZenModelRM import ZenModelRM
     25  from ZenPackable import ZenPackable
     26  from Products.ZenWidgets import messaging
     27
     28 -def manage_addGraphPoint(context, id, REQUEST = None):
     29      ''' This is here so than zope will let us copy/paste/rename
     30      graphpoints.
     31      '''
     32      gp = GraphPoint(id)
     33      context._setObject(gp.id, gp)
     34      if REQUEST:
     35          return context.callZenScreen(REQUEST)
     36
     37
     38 -class GraphPoint(ZenModelRM, ZenPackable):
     39      '''
     40      '''
     41
     42      isThreshold = False
     43
     44      DEFAULT_FORMAT = '%5.2lf%s'
     45      DEFAULT_LEGEND = '${graphPoint/id}'
     46      DEFAULT_MULTIGRAPH_LEGEND = '${here/name | here/id} ${graphPoint/id}'
     47
     48      sequence = 0
     49      _properties = (
     50          {'id':'sequence', 'type':'long', 'mode':'w'},
     51          )
     52
     53      _relations = ZenPackable._relations + (
     54          ("graphDef", ToOne(ToManyCont,"Products.ZenModel.GraphDefinition","graphPoints")),
     55          )
     56
     57      factory_type_information = (
     58          {
     59              'immediate_view' : 'editGraphPoint',
     60              'actions'        :
     61              (
     62                  { 'id'            : 'edit'
     63                  , 'name'          : 'Graph Point'
     64                  , 'action'        : 'editGraphPoint'
     65                  , 'permissions'   : ( Permissions.view, )
     66                  },
     67              )
     68          },
     69      )
     70
     71      colors = (
     72          '#00cc00', '#0000ff', '#00ffff', '#ff0000',
     73          '#ff9900', '#cc0000', '#0000cc', '#0080c0',
     74          '#8080c0', '#ff0080', '#800080', '#0000a0',
     75          '#408080', '#808000', '#000000', '#00ff00',
     76          '#fb31fb', '#0080ff', '#ff8000', '#800000',
     77          )
     78
     79      security = ClassSecurityInfo()
     80
     81      ## Interface
     82
     83
     84 -    def breadCrumbs(self, terminator='dmd'):
     85          """Return the breadcrumb links for this object add ActionRules list.
     86          [('url','id'), ...]
     87          """
     88          if self.graphDef.rrdTemplate():
     89              from RRDTemplate import crumbspath
     90              crumbs = super(GraphPoint, self).breadCrumbs(terminator)
     91              return crumbspath(self.graphDef(), crumbs, -3)
     92          return ZenModelRM.breadCrumbs(self, terminator)
     93
     94
     95      security.declareProtected(ZEN_MANAGE_DMD, 'manage_editProperties')
     96 -    def manage_editProperties(self, REQUEST):
     97          '''
     98          Process a save request from a GraphPoint edit screen.  Perform
     99          validation on fields and either return error message or save
    100          results.
    101          '''
    102          def IsHex(s):
    103              try:
    104                  _ = long(color, 16)
    105              except ValueError:
    106                  return False
    107              return True
    108
    109          color = REQUEST.get('color', '').strip().lstrip('#').upper()
    110          if color:
    111              if len(color) in (6, 8) and IsHex(color):
    112                  REQUEST.form['color'] = color
    113              else:
    114                  messaging.IMessageSender(self).sendToBrowser(
    115                      'Invalid Color',
    116                      'Color must be a 6 or 8-digit hexadecimal value.',
    117                      priority=messaging.WARNING
    118                  )
    119                  return self.callZenScreen(REQUEST)
    120          return self.zmanage_editProperties(REQUEST)
    121
    122
    123 -    def getDescription(self):
    124          ''' Return a description
    125          '''
    126          return self.id
    127
    128
    129 -    def getTalesContext(self, thing=None, **kw):
    130          '''
    131          Standard stuff to add to context for tales expressions
    132          '''
    133          context = {
    134              'graphDef': self.graphDef(),
    135              'graphPoint': self,
    136              }
    137          if thing:
    138              thing.getRRDContextData(context)
    139          for key, value in kw.items():
    140              context[key] = value
    141          return context
    142
    143
    144 -    def talesEval(self, str, context, **kw):
    145          '''
    146          return a tales evaluation of str
    147          '''
    148          from Products.ZenUtils.ZenTales import talesEvalStr
    149          extraContext = self.getTalesContext(thing=context, **kw)
    150          try:
    151              result = talesEvalStr(str, context, extraContext)
    152          except Exception:
    153              result = '(Tales expression error)'
    154          return result
    155
    156
    157      ## Graphing Support
    158
    159 -    def getColor(self, index):
    160          """
    161          Return a string apprpriate for use as the color part of an
    162          rrd graph command.  The color either comes from the attribute on
    163          this object or from an offset into the self.colors list.
    164          """
    165          color = None
    166          if self.color:
    167              color = self.color
    168              try:
    169                  _ = long(color, 16)
    170              except ValueError:
    171                  color = None
    172          if not color:
    173              index %= len(self.colors)
    174              color = self.colors[index]
    175          color = '#%s' % color.lstrip('#')
    176          if hasattr(self, 'stacked'):
    177              # This is setting the alpha channel?
    178              # Why is this needed?
    179              if not self.stacked and index>0: color += "99"
    180              else: color += "ff"
    181          return color
    182
    183
    184 -    def getThresholdColor(self, index):
    185          index %= len(self.colors)
    186          color = self.color or self.colors[-1 * (index+1)]
    187          color = '#%s' % color.lstrip('#')
    188          return color
    189
    190
    191 -    def getGraphCmds(self, cmds, context, rrdDir, addSummary, idx,
    192                      multiid=-1, prefix=''):
    193          ''' Build the graphing commands for this graphpoint
    194          '''
    195          from Products.ZenUtils.Utils import unused
    196          unused(multiid, prefix, rrdDir)
    197          return cmds
    198
    199
    200 -    def getDsName(self, base, multiid=-1, prefix=''):
    201          name = self.addPrefix(prefix, base)
    202          if multiid > -1:
    203              name = '%s_%s' % (name, multiid)
    204          return name
    205
    206
    207 -    def addPrefix(self, prefix, base):
    208          ''' If not base then return ''
    209          elif prefix then return prefix_base
    210          else return base
    211          The result is rrd scrubbed
    212          '''
    213          s = base or ''
    214          if s and prefix:
    215              s = '_'.join((prefix, base))
    216          s = self.scrubForRRD(s)
    217          return s
    218
    219
    220 -    def scrubForRRD(self, value, namespace=None):
    221          ''' scrub value so it is a valid rrd variable name.  If namespace
    222          is provided then massage value as needed to avoid name conflicts
    223          with items in namespace.
    224          '''
    225          import string
    226          import itertools
    227          def Scrub(c):
    228              if c not in string.ascii_letters + string.digits + '_-':
    229                  c = '_'
    230              return c
    231          value = ''.join([Scrub(c) for c in value])
    232          if namespace:
    233              postfixIter = itertools.count(2)
    234              candidate = value
    235              while candidate in namespace:
    236                  candidate = value + str(postfixIter.next())
    237              value = candidate
    238          return value
    239
    240
    241 -    def escapeForRRD(self, value):
    242          '''
    243          Escapes characters like colon ':' for use by RRDTool which would
    244          '''
    245          value = value.replace(":", "\:")
    246          return value
    247
    248
    249  InitializeClass(GraphPoint)
    250