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

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