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

Source Code for Module Products.ZenModel.RRDTemplate

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  import sys 
 12  from Globals import DTMLFile 
 13  from Globals import InitializeClass 
 14  from AccessControl import ClassSecurityInfo, Permissions 
 15  from Products.ZenModel.ZenossSecurity import * 
 16  from zope.interface import implements 
 17  from Acquisition import aq_parent 
 18  from ZenModelRM import ZenModelRM 
 19  from Products.ZenModel.interfaces import IIndexed 
 20   
 21  from Products.ZenRelations.RelSchema import * 
 22  from Products.ZenModel.RRDDataSource import SimpleRRDDataSource 
 23  from Products.ZenModel.BasicDataSource import BasicDataSource 
 24  from Products.ZenModel.BuiltInDS import BuiltInDS 
 25  from Products.ZenModel.PingDataSource import PingDataSource 
 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 return crumbs
100 101
102 -class RRDTemplate(ZenModelRM, ZenPackable):
103 104 implements(IIndexed) 105 meta_type = 'RRDTemplate' 106 107 default_catalog = RRDTEMPLATE_CATALOG 108 109 security = ClassSecurityInfo() 110 111 description = "" 112 targetPythonClass = "Products.ZenModel.Device" 113 114 _properties = ( 115 {'id':'description', 'type':'text', 'mode':'w'}, 116 {'id':'targetPythonClass', 'type':'string', 'mode':'w'}, 117 ) 118 119 # The graphs relationship can be removed post 2.1. It is needed 120 # by the graphDefinitionAndFriends migrate script for 2.1 121 122 _relations = ZenPackable._relations + ( 123 ("deviceClass", ToOne( 124 ToManyCont,"Products.ZenModel.TemplateContainer", "rrdTemplates")), 125 ("datasources", ToManyCont( 126 ToOne,"Products.ZenModel.RRDDataSource", "rrdTemplate")), 127 ("graphs", ToManyCont( 128 ToOne,"Products.ZenModel.RRDGraph", "rrdTemplate")), 129 ("thresholds", ToManyCont( 130 ToOne,"Products.ZenModel.ThresholdClass", "rrdTemplate")), 131 ("graphDefs", ToManyCont( 132 ToOne,"Products.ZenModel.GraphDefinition", "rrdTemplate")), 133 ) 134 135 136 # Screen action bindings (and tab definitions) 137 factory_type_information = ( 138 { 139 'immediate_view' : 'viewRRDTemplate', 140 'actions' : 141 ( 142 { 'id' : 'overview' 143 , 'name' : 'Performance Template' 144 , 'action' : 'viewRRDTemplate' 145 , 'permissions' : ( Permissions.view, ) 146 }, 147 ) 148 }, 149 ) 150
151 - def breadCrumbs(self, terminator='dmd'):
152 """Return the breadcrumb links for this object add ActionRules list. 153 [('url','id'), ...] 154 """ 155 crumbs = super(RRDTemplate, self).breadCrumbs(terminator) 156 return crumbspath(self, crumbs)
157 158
159 - def isEditable(self, context):
160 """Is this template editable in context. 161 """ 162 return ((context == self or context.isLocalName(self.id)) 163 and self.checkRemotePerm(ZEN_CHANGE_DEVICE, self))
164 165
166 - def getGraphDefs(self):
167 ''' Return an ordered list of the graph definitions 168 ''' 169 def graphDefSortKey(a): 170 try: 171 return int(a.sequence) 172 except ValueError: 173 return sys.maxint
174 return sorted(self.graphDefs(), key=graphDefSortKey)
175 176
177 - def getRRDPath(self):
178 """Return the path on which this template is defined. 179 """ 180 return self.getPrimaryParent().getPrimaryDmdId(subrel="rrdTemplates")
181 182
183 - def getGraphableThresholds(self):
184 ''' Return a list of names of graphable thresholds 185 ''' 186 return [t for t in self.thresholds()]
187 188
189 - def getRRDDataPointNames(self):
190 """Return the list of all datapoint names. 191 """ 192 # We check for the presence of datapoints on the datasources 193 # to better handle situation where the datasource is broken 194 # (usually because of a missing zenpack.) 195 datasources = [ds for ds in self.datasources() 196 if hasattr(ds, 'datapoints')] 197 return [dp.name() for ds in datasources for dp in ds.datapoints()]
198 199
200 - def getRRDDataSources(self, dsType=None):
201 """Return a list of all datapoints on this template. 202 """ 203 if dsType is None: return self.datasources() 204 return [ds for ds in self.datasources() 205 if ds.sourcetype == dsType 206 or (dsType=='COMMAND' and ds.useZenCommand())]
207 208
209 - def getRRDDataPoints(self):
210 """Return a list of all datapoints on this template. 211 """ 212 result = [] 213 for s in self.datasources(): 214 result.extend(s.datapoints()) 215 return result
216 217
218 - def getRRDDataPoint(self, name):
219 """Return a datapoint based on its name. 220 """ 221 source = name 222 point = name 223 if name.find(SEPARATOR) >= 0: 224 source, point = name.split(SEPARATOR, 1) 225 ds = self.datasources._getOb(source, None) 226 if ds is None: 227 results = [] 228 for ds in self.datasources(): 229 for dp in ds.datapoints(): 230 if dp.name() == name: 231 results.append(dp) 232 if len(results) == 1: 233 return results[0] 234 else: 235 return ds.datapoints._getOb(point) 236 raise ConfigurationError('Unknown data point "%s"' % name)
237 238 239 security.declareProtected('Add DMD Objects', 'manage_addRRDDataSource')
240 - def manage_addRRDDataSource(self, id, dsOption, REQUEST=None):
241 """Add an RRDDataSource to this DeviceClass. 242 """ 243 ds = None 244 if id and dsOption: 245 ds = self.getDataSourceInstance(id, dsOption) 246 self.datasources._setObject(ds.id, ds) 247 ds = self.datasources._getOb(ds.id) 248 if ds: 249 ds.addDataPoints() 250 if REQUEST: 251 if ds: 252 messaging.IMessageSender(self).sendToBrowser( 253 'Datasource Added', 254 "Data source %s added" % ds.id 255 ) 256 url = '%s/datasources/%s' % (self.getPrimaryUrlPath(), ds.id) 257 return REQUEST['RESPONSE'].redirect(url) 258 else: 259 return self.callZenScreen(REQUEST) 260 return ds
261 262
263 - def getTargetPythonClass(self):
264 """ 265 Returns the python class object that this template can be bound to. 266 """ 267 from Products.ZenModel.Device import Device 268 cname = getattr(self, "targetPythonClass", None) 269 if cname: 270 try: 271 return importClass(cname) 272 except ImportError: 273 log.exception("Unable to import class " + cname) 274 return Device
275 276 277 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteRRDDataSources')
278 - def manage_deleteRRDDataSources(self, ids=(), REQUEST=None):
279 """Delete RRDDataSources from this DeviceClass 280 """ 281 def clean(rel, id): 282 for obj in rel(): 283 if id in obj.dsnames: 284 obj.dsnames.remove(id) 285 if not obj.dsnames: 286 rel._delObject(obj.id)
287 288 if not ids: return self.callZenScreen(REQUEST) 289 for id in ids: 290 self._p_changed = True 291 if getattr(self.datasources,id,False): 292 if getattr(self, 'device', False): 293 perfConf = self.device().getPerformanceServer() 294 if perfConf: 295 perfConf.deleteRRDFiles(device=self.device().id, 296 datasource=id) 297 else: 298 for d in self.deviceClass.obj.getSubDevicesGen(): 299 perfConf = d.getPerformanceServer() 300 if perfConf: 301 perfConf.deleteRRDFiles(device=d, datasource=id) 302 303 self.datasources._delObject(id) 304 clean(self.graphs, id) 305 clean(self.thresholds, id) 306 307 if REQUEST: 308 messaging.IMessageSender(self).sendToBrowser( 309 'Datasources Deleted', 310 'Datasource%s %s deleted.' % ('' if len(ids)==1 else 's', 311 ', '.join(ids)) 312 ) 313 return self.callZenScreen(REQUEST) 314 315 316 security.declareProtected('Add DMD Objects', 'manage_addRRDThreshold')
317 - def manage_addRRDThreshold(self, id, thresholdClassName, REQUEST=None):
318 """Add an RRDThreshold to this DeviceClass. 319 """ 320 if not id: return self.callZenScreen(REQUEST) 321 org = self.getThresholdClass(id, thresholdClassName) 322 self.thresholds._setObject(org.id, org) 323 org = self.thresholds._getOb(org.id) 324 if REQUEST: 325 if org: 326 messaging.IMessageSender(self).sendToBrowser( 327 'Threshold Added', 328 'Threshold "%s" added' % org.id 329 ) 330 url = '%s/thresholds/%s' % (self.getPrimaryUrlPath(), org.id) 331 return REQUEST['RESPONSE'].redirect(url) 332 else: 333 return self.callZenScreen(REQUEST) 334 return org
335 336 337 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteRRDThresholds')
338 - def manage_deleteRRDThresholds(self, ids=(), REQUEST=None):
339 """Delete RRDThresholds from this DeviceClass 340 """ 341 if not ids: return self.callZenScreen(REQUEST) 342 for id in ids: 343 if getattr(self.thresholds,id,False): 344 self.thresholds._delObject(id) 345 if REQUEST: 346 messaging.IMessageSender(self).sendToBrowser( 347 'Thresholds Deleted', 348 'Threshold%s %s deleted.' % ('' if len(ids)==1 else 's', 349 ', '.join(ids)) 350 ) 351 return self.callZenScreen(REQUEST)
352 353 354 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addGraphDefinition')
355 - def manage_addGraphDefinition(self, new_id, REQUEST=None):
356 """Add a GraphDefinition to our RRDTemplate. 357 """ 358 from GraphDefinition import GraphDefinition 359 self.getGraphDefs() 360 graph = None 361 graph = GraphDefinition(new_id) 362 graph.sequence = len(self.graphDefs()) 363 self.graphDefs._setObject(graph.id, graph) 364 graph = self.graphDefs._getOb(graph.id) 365 if REQUEST: 366 messaging.IMessageSender(self).sendToBrowser( 367 'Graph Added', 368 'Graph "%s" added' % graph.id 369 ) 370 url = '%s/graphDefs/%s' % (self.getPrimaryUrlPath(), graph.id) 371 return REQUEST['RESPONSE'].redirect(url) 372 return graph
373 374 375 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteGraphDefinitions')
376 - def manage_deleteGraphDefinitions(self, ids=(), REQUEST=None):
377 """Remove GraphDefinitions from this RRDTemplate. 378 """ 379 for id in ids: 380 self.graphDefs._delObject(id) 381 self.manage_resequenceGraphDefs() 382 if REQUEST: 383 messaging.IMessageSender(self).sendToBrowser( 384 'Graphs Deleted', 385 'Graph%s %s deleted.' % ('' if len(ids)==1 else 's', 386 ', '.join(ids)) 387 ) 388 return self.callZenScreen(REQUEST)
389 390 391 security.declareProtected(ZEN_MANAGE_DMD, 'manage_resequenceGraphDefs')
392 - def manage_resequenceGraphDefs(self, seqmap=(), origseq=(), REQUEST=None):
393 """Reorder the sequence of the GraphDefinitions. 394 """ 395 from Products.ZenUtils.Utils import resequence 396 return resequence(self, self.getGraphDefs(), 397 seqmap, origseq, REQUEST)
398 399 400 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataSourcesToGraphs')
401 - def manage_addDataSourcesToGraphs(self, ids=(), graphIds=(), REQUEST=None):
402 """ 403 Create GraphPoints for all datapoints in the given datasources (ids) 404 in each of the graphDefs (graphIds.) 405 If a graphpoint already exists for a datapoint in a graphDef then 406 don't create a 2nd one. 407 """ 408 newGraphPoints = [] 409 for dsId in ids: 410 ds = self.datasources._getOb(dsId, None) 411 if ds: 412 newGraphPoints += ds.manage_addDataPointsToGraphs( 413 [dp.id for dp in ds.datapoints()], 414 graphIds) 415 numAdded = len(newGraphPoints) 416 if REQUEST: 417 messaging.IMessageSender(self).sendToBrowser( 418 'Graph Points Added', 419 'Added %s GraphPoint%s' % (numAdded, numAdded != 1 and 's' or '') 420 ) 421 return self.callZenScreen(REQUEST) 422 return newGraphPoints
423 424 425 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addDataSourcesToGraphs')
426 - def manage_addThresholdsToGraphs(self, ids=(), graphIds=(), REQUEST=None):
427 """ 428 Create GraphPoints for all given thresholds that are not already 429 graphed. in the given datasources (ids) 430 """ 431 newGps = [] 432 for graphId in graphIds: 433 graphDef = self.graphDefs._getOb(graphId, None) 434 if graphDef: 435 for threshId in ids: 436 thresh = self.thresholds._getOb(threshId, None) 437 if thresh and not graphDef.isThresholdGraphed(thresh.id): 438 newGps += graphDef.manage_addThresholdGraphPoints( 439 [thresh.id]) 440 if REQUEST: 441 numAdded = len(newGps) 442 messaging.IMessageSender(self).sendToBrowser( 443 'Graph Points Added', 444 'Added %s GraphPoint%s' % (numAdded, numAdded != 1 and 's' or '') 445 ) 446 return self.callZenScreen(REQUEST) 447 return newGps
448 449
450 - def getDataSourceClasses(self):
451 dsClasses = [BasicDataSource, BuiltInDS, PingDataSource] 452 for zp in self.dmd.ZenPackManager.packs(): 453 dsClasses += zp.getDataSourceClasses() 454 return dsClasses
455 456
457 - def getDataSourceOptions(self):
458 ''' Returns a list of the available datasource options as a list 459 of (display name, dsOption) 460 ''' 461 dsTypes = [] 462 for dsClass in self.getDataSourceClasses(): 463 dsTypes += [(t, '%s.%s' % (dsClass.__name__, t)) 464 for t in dsClass.sourcetypes] 465 return dsTypes
466 467
468 - def getDataSourceInstance(self, id, dsOption):
469 ''' Given one of the dsOptions returned by getDataSourceOptions) 470 return an instance of the that RRDDataSource subclass. 471 ''' 472 dsClassName, dsType = dsOption.split('.') 473 for c in self.getDataSourceClasses(): 474 if dsClassName == c.__name__: 475 ds = c(id) 476 ds.sourcetype = dsType 477 break 478 else: 479 raise ConfigurationError('Cannot find datasource class' 480 ' for %s' % dsOption) 481 return ds
482 483
484 - def getThresholdClasses(self):
485 from Products.ZenModel.MinMaxThreshold import MinMaxThreshold 486 from Products.ZenModel.ValueChangeThreshold import ValueChangeThreshold 487 thresholdClasses = [MinMaxThreshold, ValueChangeThreshold] 488 for zp in self.dmd.ZenPackManager.packs(): 489 thresholdClasses += zp.getThresholdClasses() 490 return map(lambda x: (x, x.__name__), thresholdClasses)
491 492
493 - def getThresholdClass(self, id, thresholdClassName):
494 ''' Given one of the dsOptions returned by getDataSourceOptions) 495 return an instance of the that RRDDataSource subclass. 496 ''' 497 for c, name in self.getThresholdClasses(): 498 if thresholdClassName == c.__name__: 499 return c(id) 500 raise ConfigurationError('Cannot find threshold class %s' % 501 thresholdClassName)
502 503
504 - def getEventClassNames(self):
505 """ 506 Get a list of all event class names within the permission scope. 507 """ 508 return self.primaryAq().Events.getOrganizerNames()
509 510
511 - def getUIPath(self, separator='/'):
512 """ 513 Given a separator and a template this method returns the UI path that we display 514 to the user. 515 @param RRDTemplate template 516 @param String separator e.g. '/' 517 @returns String e.g. '/Devices' or '/Server' 518 """ 519 obj = self.deviceClass() 520 if obj is None: 521 # this template is in a Device 522 obj = aq_parent(self) 523 path = list(obj.getPrimaryPath()) 524 # remove the "devices" relationship 525 path.pop(-2) 526 else: 527 # this template is in a DeviceClass.rrdTemplates relationship 528 path = list(obj.getPrimaryPath()) 529 parts = path[4:-1] 530 parts.append(obj.titleOrId()) 531 return separator + separator.join(parts)
532 533 534 InitializeClass(RRDTemplate) 535