Package ZenModel :: Module RRDTemplate
[hide private]
[frames] | no frames]

Source Code for Module ZenModel.RRDTemplate

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