1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__="""GraphDefinition
15
16 GraphDefinition defines the global options for a graph.
17 """
18
19 import sys
20 from sets import Set
21 import string
22
23 from Products.ZenRelations.RelSchema import *
24 from Products.ZenModel.ZenossSecurity import ZEN_MANAGE_DMD
25 from Globals import InitializeClass
26 from AccessControl import ClassSecurityInfo, Permissions
27 from ZenModelRM import ZenModelRM
28 from Products.ZenWidgets import messaging
29 from ZenPackable import ZenPackable
30 import logging
31 log = logging.getLogger("zen.Device")
32 from Acquisition import aq_base
33
34
46
48 isFake = True
49 - def __init__(self, name):
51 - def __getattr__(self, name):
53 - def __call__(self, *unused, **ignored):
55 - def __getitem__(self, key):
63 - def __nonzero__(self):
69
71 '''
72 '''
73
74 meta_type = 'GraphDefinition'
75
76 height = 100
77 width = 500
78 units = ""
79 log = False
80 base = False
81
82 miny = -1
83 maxy = -1
84 custom = ""
85 hasSummary = True
86 sequence = 0
87
88 _properties = (
89 {'id':'height', 'type':'int', 'mode':'w'},
90 {'id':'width', 'type':'int', 'mode':'w'},
91 {'id':'units', 'type':'string', 'mode':'w'},
92 {'id':'log', 'type':'boolean', 'mode':'w'},
93 {'id':'base', 'type':'boolean', 'mode':'w'},
94
95 {'id':'miny', 'type':'int', 'mode':'w'},
96 {'id':'maxy', 'type':'int', 'mode':'w'},
97 {'id':'custom', 'type':'text', 'mode':'w'},
98 {'id':'hasSummary', 'type':'boolean', 'mode':'w'},
99 {'id':'sequence', 'type':'long', 'mode':'w'},
100 )
101
102 _relations = (
103 ("rrdTemplate",
104 ToOne(ToManyCont,"Products.ZenModel.RRDTemplate", "graphDefs")),
105 ('report',
106 ToOne(ToManyCont, 'Products.ZenModel.MultiGraphReport', 'graphDefs')),
107 ('graphPoints',
108 ToManyCont(ToOne, 'Products.ZenModel.GraphPoint', 'graphDef')),
109
110 ('reportClass',
111 ToOne(ToManyCont, 'Products.ZenModel.MultiGraphReportClass', 'graphDefs')),
112 )
113
114
115
116 factory_type_information = (
117 {
118 'immediate_view' : 'editGraphDefinition',
119 'actions' :
120 (
121 { 'id' : 'edit'
122 , 'name' : 'Graph Definition'
123 , 'action' : 'editGraphDefinition'
124 , 'permissions' : ( Permissions.view, )
125 },
126 { 'id' : 'editCustom'
127 , 'name' : 'Graph Custom Definition'
128 , 'action' : 'editCustGraphDefinition'
129 , 'permissions' : ( Permissions.view, )
130 },
131 { 'id' : 'viewCommands'
132 , 'name' : 'Graph Commands'
133 , 'action' : 'viewGraphCommands'
134 , 'permissions' : ( Permissions.view, )
135 },
136 )
137 },
138 )
139
140 security = ClassSecurityInfo()
141
142
143
145 ''' Return ordered list of graph points
146 '''
147 def cmpGraphPoints(a, b):
148 try:
149 a = int(a.sequence)
150 except ValueError:
151 a = sys.maxint
152 try:
153 b = int(b.sequence)
154 except ValueError:
155 b = sys.maxint
156 return cmp(a, b)
157 gps = [gp for gp in self.graphPoints()
158 if includeThresholds or not gp.isThreshold]
159 gps.sort(cmpGraphPoints)
160 return gps
161
162
164 ''' Get ordered list of threshold graph points
165 '''
166 gps = [gp for gp in self.getGraphPoints() if gp.isThreshold]
167 return gps
168
169
171 ''' Return true if there is a thresholdgraphpoint with threshId=threshid
172 '''
173 for gp in self.getThresholdGraphPoints():
174 if gp.threshId == threshId:
175 return True
176 return False
177
178
189
190
191
192
193
203
204
206 """Checks a valid id
207 """
208
209
210
211
212 if len(id) > 200:
213 return 'GraphPoint names can not be longer than 200 characters.'
214 allowed = Set(list(string.ascii_letters)
215 + list(string.digits)
216 + ['_'])
217 attempted = Set(list(id))
218 if not attempted.issubset(allowed):
219 return 'Only letters, digits and underscores are allowed' + \
220 ' in GraphPoint names.'
221 return ZenModelRM.checkValidId(self, id, prep_id)
222
223
226
227
229 ''' Return list of graph point ids
230 '''
231 return [gp.id for gp in self.getGraphPoints()]
232
233
235 """
236 Return a string that lists the names of the graphpoints used in this
237 graph definition. If this graph definition has a perf template then
238 note in the string which graphpoints are broken (in that they refer
239 to nonexistent datapoints.)
240 """
241 names = []
242 for gp in self.getGraphPoints():
243 if hasattr(aq_base(gp), 'isBroken') and gp.isBroken():
244 names.append('%s(<span style="color: red">missing</span>)' %
245 gp.id)
246 else:
247 names.append(gp.id)
248 return ', '.join(names)
249
250
252 ''' Used by dialog_addGraphPoint to construct the list of
253 available graphpoint types.
254 '''
255 return (('DefGraphPoint', 'DEF'),
256 ('VdefGraphPoint', 'VDEF'),
257 ('CdefGraphPoint', 'CDEF'),
258 ('PrintGraphPoint', 'PRINT'),
259 ('GprintGraphPoint', 'GPRINT'),
260 ('CommentGraphPoint', 'COMMENT'),
261 ('VruleGraphPoint', 'VRULE'),
262 ('HruleGraphPoint', 'HRULE'),
263 ('LineGraphPoint', 'LINE'),
264 ('AreaGraphPoint', 'AREA'),
265 ('TickGraphPoint', 'TICK'),
266 ('ShiftGraphPoint', 'SHIFT'))
267
268
270 ''' Create the graphpoint with the given id or something similar
271 and add to self.graphPoints
272 '''
273 def getUniqueId(container, base):
274 ids = container.objectIds()
275 new = base
276 i = 2
277 while new in ids:
278 new = '%s%s' % (base, i)
279 i += 1
280 return new
281 newId = getUniqueId(self.graphPoints, newId)
282 gp = cls(newId)
283
284 if gp.isThreshold:
285 gp.sequence = -1
286 else:
287 gp.sequence = len(self.graphPoints())
288
289 if self.report() and hasattr(gp, 'legend'):
290
291
292
293 gp.legend = gp.DEFAULT_MULTIGRAPH_LEGEND
294 self.graphPoints._setObject(gp.id, gp)
295 gp = self.graphPoints._getOb(gp.id)
296 if gp.sequence == -1:
297 self.manage_resequenceGraphPoints()
298 return gp
299
300
301 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addCustomGraphPoint')
313
314
315 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataPointGraphPoints')
351
352
368
369
370 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addThresholdGraphPoints')
389
390
391 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteGraphPoints')
408
409
410 security.declareProtected(ZEN_MANAGE_DMD, 'manage_resequenceGraphPoints')
417
418
420 ''' Return a list of (value, name) tuples for the list of datapoints
421 which the user selects from to create new graphpoints.
422 '''
423 return [(dp.name(), dp.name())
424 for dp in self.rrdTemplate.getRRDDataPoints()]
425
426
428 ''' Return a list of (value, name) tuples for the list of thresholds
429 which the user selects from to create new graphpoints.
430 '''
431 return [(t.id, t.id) for t in self.rrdTemplate.thresholds()]
432
433
434
435
436
437 - def getGraphCmds(self, context, rrdDir, multiid=-1, upToPoint=None,
438 includeSetup=True, includeThresholds=True,
439 prefix='', cmds=None, idxOffset=0):
440 """build the graph opts for a single rrdfile"""
441 from Products.ZenUtils.ZenTales import talesEval
442 if not cmds:
443 cmds = []
444 if includeSetup:
445 cmds += self.graphsetup()
446
447
448
449 if includeThresholds:
450 threshGps = [gp for gp in self.getThresholdGraphPoints()
451 if upToPoint is None or gp.sequence < upToPoint]
452 if threshGps:
453 for index, gp in enumerate(threshGps):
454 try:
455 cmds = gp.getGraphCmds(cmds, context, rrdDir,
456 self.hasSummary, index+idxOffset,
457 multiid, prefix)
458 except (KeyError, NameError), e:
459 cmds.append('COMMENT: UNKNOWN VALUE IN '
460 'GRAPHPOINT %s\: %s' % (gp.id, str(e)))
461 gpList = [gp for gp in self.getGraphPoints(includeThresholds=False)
462 if upToPoint is None or gp.sequence < upToPoint]
463 for index, gp in enumerate(gpList):
464 try:
465 cmds = gp.getGraphCmds(cmds, context, rrdDir,
466 self.hasSummary, index+idxOffset,
467 multiid, prefix)
468 except (KeyError, NameError), e:
469 cmds.append('COMMENT: UNKNOWN VALUE IN GRAPHPOINT '
470 '%s\: %s' % (gp.id, str(e)))
471 if self.custom and includeSetup \
472 and not upToPoint:
473 try:
474 res = talesEval("string:"+str(self.custom), context)
475 except (KeyError, NameError), e:
476 res = 'COMMENT:UNKNOWN VALUE IN CUSTOM COMMANDS\: %s' % str(e)
477 res = [l for l in res.split('\n') if l.strip()]
478 cmds.extend(res)
479
480
481
482 return cmds
483
484
486 ''' Return list of rrd variable names that are defined by DEF, CDEF
487 or VDEF statements in the rrd commands. If upToPoint is not None then
488 only consider statements generated by graphoints where
489 sequence < upToPoint
490 '''
491 cmds = self.getFakeGraphCmds(upToPoint=upToPoint)
492 names = [line[line.find(':')+1:line.find('=')]
493 for line in cmds.split('\n')
494 if line[:line.find(':')] in ('DEF', 'CDEF', 'VDEF')]
495 return names
496
497
506
507
509 """Setup global graph parameters.
510 """
511 gopts = ['-F', '-E']
512 if self.height:
513 gopts.append('--height=%d' % int(self.height))
514 if self.width:
515 gopts.append('--width=%d' % int(self.width))
516 if self.log:
517 gopts.append('--logarithmic')
518 if self.maxy > -1:
519 gopts.append('--upper-limit=%d' % int(self.maxy))
520 gopts.append('--rigid')
521 if self.miny > -1:
522 gopts.append('--lower-limit=%d' % int(self.miny))
523 gopts.append('--rigid')
524
525
526 gopts.append('--vertical-label=%s' % (self.units or ' '))
527 if self.units == 'percentage':
528 if not self.maxy > -1:
529 gopts.append('--upper-limit=100')
530 if not self.miny > -1:
531 gopts.append('--lower-limit=0')
532 if self.base:
533 gopts.append('--base=1024')
534 gopts = [str(o) for o in gopts]
535 return gopts
536
537
545
546
548 '''
549 Get a list of all unique datapoint names
550 '''
551 from sets import Set
552 dpNames = Set()
553 for t in self.dmd.Devices.getAllRRDTemplates():
554 for ds in t.datasources():
555
556
557 if hasattr(ds, 'datapoints'):
558 for dp in ds.datapoints():
559 dpNames.add(dp.name())
560 if limit and len(dpNames) >= limit:
561 break
562 dpNames = list(dpNames)
563 dpNames.sort()
564 return dpNames
565
566
568 '''
569 Get a list of all unique threshold names
570 '''
571 from sets import Set
572 names = Set()
573 for t in self.dmd.Devices.getAllRRDTemplates():
574 for thresh in t.thresholds():
575 names.add(thresh.id)
576 if len(names) >= limit:
577 break
578 if len(names) >= limit:
579 break
580 names = list(names)
581 names.sort()
582 return names
583
584
585 InitializeClass(GraphDefinition)
586