| Trees | Indices | Help |
|
|---|
|
|
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
14 import sys
15 from Globals import DTMLFile
16 from Globals import InitializeClass
17 from AccessControl import ClassSecurityInfo, Permissions
18 from Products.ZenModel.ZenossSecurity import *
19 from zope.interface import implements
20 from Acquisition import aq_parent
21 from ZenModelRM import ZenModelRM
22 from Products.ZenModel.interfaces import IIndexed
23
24 from Products.ZenRelations.RelSchema import *
25 from Products.ZenModel.RRDDataSource import SimpleRRDDataSource
26 from Products.ZenModel.BasicDataSource import BasicDataSource
27 from Products.ZenModel.BuiltInDS import BuiltInDS
28 from Products.ZenModel.PingDataSource import PingDataSource
29 from Products.ZenModel.ConfigurationError import ConfigurationError
30 from Products.ZenUtils.Utils import importClass
31 from Products.ZenWidgets import messaging
32 from RRDDataPoint import SEPARATOR
33 from ZenPackable import ZenPackable
34
35 import logging
36 log = logging.getLogger('zen.RRDTemplate')
37
38 RRDTEMPLATE_CATALOG = 'searchRRDTemplates'
39
40
42 """
43 Create the searchRRDTemplates catalog if it does not already exist.
44 Return the catalog.
45 """
46 from Products.ZCatalog.ZCatalog import manage_addZCatalog
47 from Products.ZenUtils.Search import makeCaseSensitiveFieldIndex, \
48 makePathIndex
49 zcat = getattr(dmd, RRDTEMPLATE_CATALOG, None)
50 if zcat and rebuild:
51 dmd._delObject(RRDTEMPLATE_CATALOG)
52 zcat = None
53 if zcat is None:
54 manage_addZCatalog(dmd, RRDTEMPLATE_CATALOG, RRDTEMPLATE_CATALOG)
55 zcat = dmd._getOb(RRDTEMPLATE_CATALOG)
56 cat = zcat._catalog
57 cat.addIndex('id', makeCaseSensitiveFieldIndex('id'))
58 cat.addIndex('getPhysicalPath', makePathIndex('getPhysicalPath'))
59 return zcat
60
61
63 """
64 Yield all templates in the searchRRDTemplates catalog which fall under
65 the given root and match the given criteria. To get all RRDTemplates
66 pass dmd in as root. If criteria contains a
67 value for getPhysicalRoot then the root parameter will be ignored.
68
69 If the searchRRDTemplates catalog is not present then fall back to using
70 DeviceClass.getAllRRDTemplatesPainfully(). In this case root must
71 be a DeviceClass and criteria is ignored. (This is compatible with
72 previous DeviceClass.getAllRRDTemplates usage.)
73
74 The searchRRDTemplates catalog was added in 2.2
75 """
76 zcat = getattr(root, RRDTEMPLATE_CATALOG, None)
77 if zcat is not None:
78 criteria = criteria or {}
79 criteria.setdefault('getPhysicalPath', root.getPrimaryId())
80 brains = zcat(criteria)
81 for result in brains:
82 yield result.getObject()
83 else:
84 for t in root.getAllRRDTemplatesPainfully():
85 yield t
86
87
89 """make a RRDTemplate"""
90 tt = RRDTemplate(id)
91 context._setObject(tt.id, tt)
92 if REQUEST is not None:
93 REQUEST['RESPONSE'].redirect(context.absolute_url()+'/manage_main')
94
95
96 addRRDTemplate = DTMLFile('dtml/addRRDTemplate',globals())
97
98
103
104
106
107 implements(IIndexed)
108 meta_type = 'RRDTemplate'
109
110 default_catalog = RRDTEMPLATE_CATALOG
111
112 security = ClassSecurityInfo()
113
114 description = ""
115 targetPythonClass = "Products.ZenModel.Device"
116
117 _properties = (
118 {'id':'description', 'type':'text', 'mode':'w'},
119 {'id':'targetPythonClass', 'type':'string', 'mode':'w'},
120 )
121
122 # The graphs relationship can be removed post 2.1. It is needed
123 # by the graphDefinitionAndFriends migrate script for 2.1
124
125 _relations = ZenPackable._relations + (
126 ("deviceClass", ToOne(
127 ToManyCont,"Products.ZenModel.TemplateContainer", "rrdTemplates")),
128 ("datasources", ToManyCont(
129 ToOne,"Products.ZenModel.RRDDataSource", "rrdTemplate")),
130 ("graphs", ToManyCont(
131 ToOne,"Products.ZenModel.RRDGraph", "rrdTemplate")),
132 ("thresholds", ToManyCont(
133 ToOne,"Products.ZenModel.ThresholdClass", "rrdTemplate")),
134 ("graphDefs", ToManyCont(
135 ToOne,"Products.ZenModel.GraphDefinition", "rrdTemplate")),
136 )
137
138
139 # Screen action bindings (and tab definitions)
140 factory_type_information = (
141 {
142 'immediate_view' : 'viewRRDTemplate',
143 'actions' :
144 (
145 { 'id' : 'overview'
146 , 'name' : 'Performance Template'
147 , 'action' : 'viewRRDTemplate'
148 , 'permissions' : ( Permissions.view, )
149 },
150 )
151 },
152 )
153
155 """Return the breadcrumb links for this object add ActionRules list.
156 [('url','id'), ...]
157 """
158 crumbs = super(RRDTemplate, self).breadCrumbs(terminator)
159 return crumbspath(self, crumbs)
160
161
163 """Is this template editable in context.
164 """
165 return ((context == self or context.isLocalName(self.id))
166 and self.checkRemotePerm(ZEN_CHANGE_DEVICE, self))
167
168
170 ''' Return an ordered list of the graph definitions
171 '''
172 def cmpGraphDefs(a, b):
173 try: a = int(a.sequence)
174 except ValueError: a = sys.maxint
175 try: b = int(b.sequence)
176 except ValueError: b = sys.maxint
177 return cmp(a, b)
178 graphDefs = [g for g in self.graphDefs()]
179 graphDefs.sort(cmpGraphDefs)
180 return graphDefs
181
182
184 """Return the path on which this template is defined.
185 """
186 return self.getPrimaryParent().getPrimaryDmdId(subrel="rrdTemplates")
187
188
190 ''' Return a list of names of graphable thresholds
191 '''
192 return [t for t in self.thresholds()]
193
194
196 """Return the list of all datapoint names.
197 """
198 # We check for the presence of datapoints on the datasources
199 # to better handle situation where the datasource is broken
200 # (usually because of a missing zenpack.)
201 datasources = [ds for ds in self.datasources()
202 if hasattr(ds, 'datapoints')]
203 return [dp.name() for ds in datasources for dp in ds.datapoints()]
204
205
207 """Return a list of all datapoints on this template.
208 """
209 if dsType is None: return self.datasources()
210 return [ds for ds in self.datasources()
211 if ds.sourcetype == dsType
212 or (dsType=='COMMAND' and ds.useZenCommand())]
213
214
216 """Return a list of all datapoints on this template.
217 """
218 result = []
219 for s in self.datasources():
220 result.extend(s.datapoints())
221 return result
222
223
225 """Return a datapoint based on its name.
226 """
227 source = name
228 point = name
229 if name.find(SEPARATOR) >= 0:
230 source, point = name.split(SEPARATOR, 1)
231 ds = self.datasources._getOb(source, None)
232 if ds is None:
233 results = []
234 for ds in self.datasources():
235 for dp in ds.datapoints():
236 if dp.name() == name:
237 results.append(dp)
238 if len(results) == 1:
239 return results[0]
240 else:
241 return ds.datapoints._getOb(point)
242 raise ConfigurationError('Unknown data point "%s"' % name)
243
244
245 security.declareProtected('Add DMD Objects', 'manage_addRRDDataSource')
247 """Add an RRDDataSource to this DeviceClass.
248 """
249 ds = None
250 if id and dsOption:
251 ds = self.getDataSourceInstance(id, dsOption)
252 self.datasources._setObject(ds.id, ds)
253 ds = self.datasources._getOb(ds.id)
254 if ds:
255 ds.addDataPoints()
256 if REQUEST:
257 if ds:
258 messaging.IMessageSender(self).sendToBrowser(
259 'Datasource Added',
260 "Data source %s added" % ds.id
261 )
262 url = '%s/datasources/%s' % (self.getPrimaryUrlPath(), ds.id)
263 return REQUEST['RESPONSE'].redirect(url)
264 else:
265 return self.callZenScreen(REQUEST)
266 return ds
267
268
270 """
271 Returns the python class object that this template can be bound to.
272 """
273 from Products.ZenModel.Device import Device
274 cname = getattr(self, "targetPythonClass", None)
275 if cname:
276 try:
277 return importClass(cname)
278 except ImportError:
279 log.exception("Unable to import class " + cname)
280 return Device
281
282
283 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteRRDDataSources')
285 """Delete RRDDataSources from this DeviceClass
286 """
287 def clean(rel, id):
288 for obj in rel():
289 if id in obj.dsnames:
290 obj.dsnames.remove(id)
291 if not obj.dsnames:
292 rel._delObject(obj.id)
293
294 if not ids: return self.callZenScreen(REQUEST)
295 for id in ids:
296 self._p_changed = True
297 if getattr(self.datasources,id,False):
298 if getattr(self, 'device', False):
299 perfConf = self.device().getPerformanceServer()
300 if perfConf:
301 perfConf.deleteRRDFiles(device=self.device().id,
302 datasource=id)
303 else:
304 for d in self.deviceClass.obj.getSubDevicesGen():
305 perfConf = d.getPerformanceServer()
306 if perfConf:
307 perfConf.deleteRRDFiles(device=d, datasource=id)
308
309 self.datasources._delObject(id)
310 clean(self.graphs, id)
311 clean(self.thresholds, id)
312
313 if REQUEST:
314 messaging.IMessageSender(self).sendToBrowser(
315 'Datasources Deleted',
316 'Datasource%s %s deleted.' % ('' if len(ids)==1 else 's',
317 ', '.join(ids))
318 )
319 return self.callZenScreen(REQUEST)
320
321
322 security.declareProtected('Add DMD Objects', 'manage_addRRDThreshold')
324 """Add an RRDThreshold to this DeviceClass.
325 """
326 if not id: return self.callZenScreen(REQUEST)
327 org = self.getThresholdClass(id, thresholdClassName)
328 self.thresholds._setObject(org.id, org)
329 org = self.thresholds._getOb(org.id)
330 if REQUEST:
331 if org:
332 messaging.IMessageSender(self).sendToBrowser(
333 'Threshold Added',
334 'Threshold "%s" added' % org.id
335 )
336 url = '%s/thresholds/%s' % (self.getPrimaryUrlPath(), org.id)
337 return REQUEST['RESPONSE'].redirect(url)
338 else:
339 return self.callZenScreen(REQUEST)
340 return org
341
342
343 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteRRDThresholds')
345 """Delete RRDThresholds from this DeviceClass
346 """
347 if not ids: return self.callZenScreen(REQUEST)
348 for id in ids:
349 if getattr(self.thresholds,id,False):
350 self.thresholds._delObject(id)
351 if REQUEST:
352 messaging.IMessageSender(self).sendToBrowser(
353 'Thresholds Deleted',
354 'Threshold%s %s deleted.' % ('' if len(ids)==1 else 's',
355 ', '.join(ids))
356 )
357 return self.callZenScreen(REQUEST)
358
359
360 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addGraphDefinition')
362 """Add a GraphDefinition to our RRDTemplate.
363 """
364 from GraphDefinition import GraphDefinition
365 self.getGraphDefs()
366 graph = None
367 graph = GraphDefinition(new_id)
368 graph.sequence = len(self.graphDefs())
369 self.graphDefs._setObject(graph.id, graph)
370 graph = self.graphDefs._getOb(graph.id)
371 if REQUEST:
372 messaging.IMessageSender(self).sendToBrowser(
373 'Graph Added',
374 'Graph "%s" added' % graph.id
375 )
376 url = '%s/graphDefs/%s' % (self.getPrimaryUrlPath(), graph.id)
377 return REQUEST['RESPONSE'].redirect(url)
378 return graph
379
380
381 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteGraphDefinitions')
383 """Remove GraphDefinitions from this RRDTemplate.
384 """
385 for id in ids:
386 self.graphDefs._delObject(id)
387 self.manage_resequenceGraphDefs()
388 if REQUEST:
389 messaging.IMessageSender(self).sendToBrowser(
390 'Graphs Deleted',
391 'Graph%s %s deleted.' % ('' if len(ids)==1 else 's',
392 ', '.join(ids))
393 )
394 return self.callZenScreen(REQUEST)
395
396
397 security.declareProtected(ZEN_MANAGE_DMD, 'manage_resequenceGraphDefs')
399 """Reorder the sequence of the GraphDefinitions.
400 """
401 from Products.ZenUtils.Utils import resequence
402 return resequence(self, self.getGraphDefs(),
403 seqmap, origseq, REQUEST)
404
405
406 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataSourcesToGraphs')
408 """
409 Create GraphPoints for all datapoints in the given datasources (ids)
410 in each of the graphDefs (graphIds.)
411 If a graphpoint already exists for a datapoint in a graphDef then
412 don't create a 2nd one.
413 """
414 newGraphPoints = []
415 for dsId in ids:
416 ds = self.datasources._getOb(dsId, None)
417 if ds:
418 newGraphPoints += ds.manage_addDataPointsToGraphs(
419 [dp.id for dp in ds.datapoints()],
420 graphIds)
421 numAdded = len(newGraphPoints)
422 if REQUEST:
423 messaging.IMessageSender(self).sendToBrowser(
424 'Graph Points Added',
425 'Added %s GraphPoint%s' % (numAdded, numAdded != 1 and 's' or '')
426 )
427 return self.callZenScreen(REQUEST)
428 return newGraphPoints
429
430
431 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataSourcesToGraphs')
433 """
434 Create GraphPoints for all given thresholds that are not already
435 graphed. in the given datasources (ids)
436 """
437 newGps = []
438 for graphId in graphIds:
439 graphDef = self.graphDefs._getOb(graphId, None)
440 if graphDef:
441 for threshId in ids:
442 thresh = self.thresholds._getOb(threshId, None)
443 if thresh and not graphDef.isThresholdGraphed(thresh.id):
444 newGps += graphDef.manage_addThresholdGraphPoints(
445 [thresh.id])
446 if REQUEST:
447 numAdded = len(newGps)
448 messaging.IMessageSender(self).sendToBrowser(
449 'Graph Points Added',
450 'Added %s GraphPoint%s' % (numAdded, numAdded != 1 and 's' or '')
451 )
452 return self.callZenScreen(REQUEST)
453 return newGps
454
455
457 dsClasses = [BasicDataSource, BuiltInDS, PingDataSource]
458 for zp in self.dmd.ZenPackManager.packs():
459 dsClasses += zp.getDataSourceClasses()
460 return dsClasses
461
462
464 ''' Returns a list of the available datasource options as a list
465 of (display name, dsOption)
466 '''
467 dsTypes = []
468 for dsClass in self.getDataSourceClasses():
469 dsTypes += [(t, '%s.%s' % (dsClass.__name__, t))
470 for t in dsClass.sourcetypes]
471 return dsTypes
472
473
475 ''' Given one of the dsOptions returned by getDataSourceOptions)
476 return an instance of the that RRDDataSource subclass.
477 '''
478 dsClassName, dsType = dsOption.split('.')
479 for c in self.getDataSourceClasses():
480 if dsClassName == c.__name__:
481 ds = c(id)
482 ds.sourcetype = dsType
483 break
484 else:
485 raise ConfigurationError('Cannot find datasource class'
486 ' for %s' % dsOption)
487 return ds
488
489
491 from Products.ZenModel.MinMaxThreshold import MinMaxThreshold
492 thresholdClasses = [MinMaxThreshold]
493 for zp in self.dmd.ZenPackManager.packs():
494 thresholdClasses += zp.getThresholdClasses()
495 return map(lambda x: (x, x.__name__), thresholdClasses)
496
497
499 ''' Given one of the dsOptions returned by getDataSourceOptions)
500 return an instance of the that RRDDataSource subclass.
501 '''
502 for c, name in self.getThresholdClasses():
503 if thresholdClassName == c.__name__:
504 return c(id)
505 raise ConfigurationError('Cannot find threshold class %s' %
506 thresholdClassName)
507
508
510 """
511 Get a list of all event class names within the permission scope.
512 """
513 return self.primaryAq().Events.getOrganizerNames()
514
515
517 """
518 Given a separator and a template this method returns the UI path that we display
519 to the user.
520 @param RRDTemplate template
521 @param String separator e.g. '/'
522 @returns String e.g. '/Devices' or '/Server'
523 """
524 obj = self.deviceClass()
525 if obj is None:
526 # this template is in a Device
527 obj = aq_parent(self)
528 path = list(obj.getPrimaryPath())
529 # remove the "devices" relationship
530 path.pop(-2)
531 else:
532 # this template is in a DeviceClass.rrdTemplates relationship
533 path = list(obj.getPrimaryPath())
534 parts = path[4:-1]
535 parts.append(obj.titleOrId())
536 return separator + separator.join(parts)
537
538
539 InitializeClass(RRDTemplate)
540
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1.1812 on Tue Oct 11 12:51:52 2011 | http://epydoc.sourceforge.net |