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 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   
41 -def CreateRRDTemplatesCatalog(dmd, rebuild=False):
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
62 -def YieldAllRRDTemplates(root, criteria=None):
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
88 -def manage_addRRDTemplate(context, id, REQUEST = None):
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
99 -def crumbspath(templ, crumbs, idx=-1):
100 """Create the crumbs path for sub objects of an RRDTemplate. 101 """ 102 return crumbs
103 104
105 -class RRDTemplate(ZenModelRM, ZenPackable):
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
154 - def breadCrumbs(self, terminator='dmd'):
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
162 - def isEditable(self, context):
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
169 - def getGraphDefs(self):
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
183 - def getRRDPath(self):
184 """Return the path on which this template is defined. 185 """ 186 return self.getPrimaryParent().getPrimaryDmdId(subrel="rrdTemplates")
187 188
189 - def getGraphableThresholds(self):
190 ''' Return a list of names of graphable thresholds 191 ''' 192 return [t for t in self.thresholds()]
193 194
195 - def getRRDDataPointNames(self):
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
206 - def getRRDDataSources(self, dsType=None):
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
215 - def getRRDDataPoints(self):
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
224 - def getRRDDataPoint(self, name):
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')
246 - def manage_addRRDDataSource(self, id, dsOption, REQUEST=None):
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
269 - def getTargetPythonClass(self):
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')
284 - def manage_deleteRRDDataSources(self, ids=(), REQUEST=None):
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')
323 - def manage_addRRDThreshold(self, id, thresholdClassName, REQUEST=None):
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')
344 - def manage_deleteRRDThresholds(self, ids=(), REQUEST=None):
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')
361 - def manage_addGraphDefinition(self, new_id, REQUEST=None):
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')
382 - def manage_deleteGraphDefinitions(self, ids=(), REQUEST=None):
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')
398 - def manage_resequenceGraphDefs(self, seqmap=(), origseq=(), REQUEST=None):
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')
407 - def manage_addDataSourcesToGraphs(self, ids=(), graphIds=(), REQUEST=None):
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')
432 - def manage_addThresholdsToGraphs(self, ids=(), graphIds=(), REQUEST=None):
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
456 - def getDataSourceClasses(self):
457 dsClasses = [BasicDataSource, BuiltInDS, PingDataSource] 458 for zp in self.dmd.ZenPackManager.packs(): 459 dsClasses += zp.getDataSourceClasses() 460 return dsClasses
461 462
463 - def getDataSourceOptions(self):
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
474 - def getDataSourceInstance(self, id, dsOption):
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
490 - def getThresholdClasses(self):
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
498 - def getThresholdClass(self, id, thresholdClassName):
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
509 - def getEventClassNames(self):
510 """ 511 Get a list of all event class names within the permission scope. 512 """ 513 return self.primaryAq().Events.getOrganizerNames()
514 515
516 - def getUIPath(self, separator='/'):
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