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

Source Code for Module ZenModel.RRDView

  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 os 
 15  import types 
 16  import time 
 17  import glob 
 18   
 19  import logging 
 20  log = logging.getLogger("zen.RRDView") 
 21   
 22  from Acquisition import aq_base, aq_chain 
 23   
 24  from Products.ZenRRD.Exceptions import RRDObjectNotFound 
 25  from Products.ZenUtils import Map 
 26   
 27  from Products.ZenUtils.ZenTales import talesEval 
 28  from Products.ZenModel.ConfigurationError import ConfigurationError 
 29   
 30  CACHE_TIME = 60. 
 31   
 32  _cache = Map.Locked(Map.Timed({}, CACHE_TIME)) 
 33   
34 -def GetRRDPath(deviceOrComponent):
35 d = deviceOrComponent.device() 36 if not d: 37 return "Devices/" + deviceOrComponent.id 38 skip = len(d.getPrimaryPath()) - 1 39 return 'Devices/' + '/'.join(deviceOrComponent.getPrimaryPath()[skip:])
40 41
42 -class RRDViewError(Exception): pass
43 44
45 -class RRDView(object):
46 """ 47 Mixin to provide hooks to RRD management functions 48 """ 49
50 - def getGraphDefUrl(self, graph, drange=None, template=None):
51 """resolve template and graph names to objects 52 and pass to graph performance""" 53 if not drange: drange = self.defaultDateRange 54 templates = self.getRRDTemplates() 55 if template: 56 templates = [template] 57 if type(graph) in types.StringTypes: 58 for t in templates: 59 if hasattr(t.graphDefs, graph): 60 template = t 61 graph = getattr(t.graphDefs, graph) 62 break 63 targetpath = self.rrdPath() 64 objpaq = self.primaryAq() 65 perfServer = objpaq.device().getPerformanceServer() 66 if perfServer: 67 return perfServer.performanceGraphUrl(objpaq, targetpath, 68 template, graph, drange)
69
70 - def cacheRRDValue(self, dsname, default = "Unknown"):
71 "read an RRDValue with and cache it" 72 filename = self.getRRDFileName(dsname) 73 value = None 74 try: 75 value = _cache[filename] 76 if value is None: 77 return default 78 except KeyError: 79 pass 80 try: 81 value = self.getRRDValue(dsname) 82 except Exception: 83 log.error('Unable to cache value for %s', dsname) 84 _cache[filename] = value 85 if value is None: 86 return default 87 return value
88 89
90 - def getRRDValue(self, dsname, start=None, end=None, function="LAST"):
91 """Return a single rrd value from its file using function. 92 """ 93 dsnames = (dsname,) 94 results = self.getRRDValues(dsnames, start, end, function) 95 if results: 96 return results[dsname]
97 98
99 - def getRRDDataPoints(self):
100 result = [] 101 for t in self.getRRDTemplates(): 102 result += t.getRRDDataPoints() 103 return result
104 105
106 - def getRRDDataPoint(self, dpName):
107 result = None 108 for t in self.getRRDTemplates(): 109 for dp in t.getRRDDataPoints(): 110 if dp.name() == dpName: 111 result = dp 112 break 113 return result
114 115
116 - def getRRDValues(self, dsnames, start=None, end=None, function="LAST"):
117 """Return a dict of key value pairs where dsnames are the keys. 118 """ 119 try: 120 if not start: 121 start = time.time() - self.defaultDateRange 122 res = {}.fromkeys(dsnames, None) 123 gopts = [] 124 names = list(dsnames[:]) 125 for dsname in dsnames: 126 for dp in self.getRRDDataPoints(): 127 if dp.name().find(dsname) > -1: 128 break 129 else: 130 names.remove(dsname) 131 continue 132 filename = self.getRRDFileName(dp.name()) 133 rpn = str(dp.rpn) 134 if rpn: 135 rpn = "," + rpn 136 gopts.append("DEF:%s_r=%s:ds0:AVERAGE" % (dsname,filename)) 137 gopts.append("CDEF:%s_c=%s_r%s" % (dsname,dsname,rpn)) 138 gopts.append("VDEF:%s=%s_c,%s" % (dsname,dsname,function)) 139 gopts.append("PRINT:%s:%%.2lf" % (dsname)) 140 gopts.append("--start=%d" % start) 141 if end: 142 gopts.append("--end=%d" % end) 143 perfServer = self.device().getPerformanceServer() 144 vals = [] 145 if perfServer: 146 vals = perfServer.performanceCustomSummary(gopts) 147 if vals is None: 148 vals = [None] * len(gopts) 149 def cvt(val): 150 if val is None: return val 151 val = float(val) 152 if val != val: return None 153 return val
154 return dict(zip(names, map(cvt, vals))) 155 except Exception, ex: 156 log.exception(ex)
157 158 159
160 - def getRRDSum(self, points, start=None, end=None, function="LAST"):
161 "Return a some of listed datapoints." 162 163 try: 164 if not start: 165 start = time.time() - self.defaultDateRange 166 if not end: 167 end = time.time() 168 gopts = [] 169 names = list(points[:]) 170 for name in points: 171 for dp in self.getRRDDataPoints(): 172 if dp.name().find(name) > -1: 173 break 174 else: 175 raise RRDViewError("Unable to find data point %s" % name) 176 filename = self.getRRDFileName(dp.name()) 177 rpn = str(dp.rpn) 178 if rpn: 179 rpn = "," + rpn 180 gopts.append("DEF:%s_r=%s:ds0:AVERAGE" % (name, filename)) 181 gopts.append("CDEF:%s=%s_r%s" % (name, name, rpn)) 182 gopts.append("CDEF:sum=%s%s" % (','.join(points), 183 ',+'*(len(points)-1))) 184 gopts.append("VDEF:agg=sum,%s" % function) 185 gopts.append("PRINT:agg:%.2lf") 186 gopts.append("--start=%d" % start) 187 gopts.append("--end=%d" % end) 188 perfServer = self.device().getPerformanceServer() 189 if perfServer: 190 vals = perfServer.performanceCustomSummary(gopts) 191 if vals is None: 192 return None 193 return float(vals[0]) 194 except Exception, ex: 195 log.exception(ex)
196 197
198 - def getDefaultGraphDefs(self, drange=None):
199 """get the default graph list for this object""" 200 graphs = [] 201 for template in self.getRRDTemplates(): 202 for g in template.getGraphDefs(): 203 graph = {} 204 graph['title'] = g.getId() 205 try: 206 graph['url'] = self.getGraphDefUrl(g, drange, template) 207 graphs.append(graph) 208 except ConfigurationError: 209 pass 210 return graphs
211 212
213 - def getGraphDef(self, graphId):
214 ''' Fetch a graph by id. if not found return None 215 ''' 216 for t in self.getRRDTemplates(): 217 for g in t.getGraphDefs(): 218 if g.id == graphId: 219 return g 220 return None
221 222
223 - def getRRDTemplateName(self):
224 """Return the target type name of this component. By default meta_type. 225 Override to create custom type selection. 226 """ 227 return self.meta_type
228 229
230 - def getRRDFileName(self, dsname):
231 """Look up an rrd file based on its data point name""" 232 names = [p.name() for p in self.getRRDDataPoints() 233 if p.name().endswith(dsname)] 234 if names: 235 return '%s/%s.rrd' % (self.rrdPath(), names[0]) 236 else: 237 return '%s/%s.rrd' % (self.rrdPath(), dsname)
238 239
240 - def getRRDNames(self):
241 return []
242
243 - def getRRDPaths(self):
244 return map(self.getRRDFileName, self.getRRDNames())
245
246 - def snmpIgnore(self):
247 """Should this component be monitored for performance using snmp. 248 """ 249 return False
250
251 - def getRRDTemplates(self):
252 default = self.getRRDTemplateByName(self.getRRDTemplateName()) 253 if not default: 254 return [] 255 return [default]
256
257 - def getRRDTemplate(self):
258 try: 259 return self.getRRDTemplates()[0] 260 except IndexError: 261 return None
262
263 - def getRRDTemplateByName(self, name):
264 "Return the template of the given name." 265 try: 266 return self._getOb(name) 267 except AttributeError: 268 pass 269 for obj in aq_chain(self): 270 try: 271 return obj.rrdTemplates._getOb(name) 272 except AttributeError: 273 pass 274 return None
275 276
277 - def getThresholds(self, templ):
278 """Return a dictionary where keys are dsnames and values are thresholds. 279 """ 280 result = {} 281 for thresh in templ.thresholds(): 282 if not thresh.enabled: continue 283 for dsname in thresh.dsnames: 284 threshdef = result.setdefault(dsname, []) 285 threshdef.append(thresh.getConfig(self)) 286 return result
287 288
289 - def rrdPath(self):
290 return GetRRDPath(self)
291 292
293 - def fullRRDPath(self):
294 from PerformanceConf import performancePath 295 return performancePath(self.rrdPath())
296
297 - def getSnmpOidTargets(self):
298 """Return a list of (name, oid, path, type, createCmd, thresholds) 299 that define monitorable""" 300 oids = [] 301 if self.snmpIgnore(): return (oids, []) 302 basepath = self.rrdPath() 303 perfServer = self.device().getPerformanceServer() 304 for templ in self.getRRDTemplates(): 305 for ds in templ.getRRDDataSources("SNMP"): 306 if not ds.enabled: continue 307 oid = ds.oid 308 snmpindex = getattr(self, "ifindex", self.snmpindex) 309 if snmpindex: oid = "%s.%s" % (oid, snmpindex) 310 for dp in ds.getRRDDataPoints(): 311 cname = self.meta_type != "Device" \ 312 and self.viewName() or dp.id 313 oids.append((cname, 314 oid, 315 "/".join((basepath, dp.name())), 316 dp.rrdtype, 317 dp.getRRDCreateCommand(perfServer), 318 (dp.rrdmin, dp.rrdmax))) 319 return (oids, self.getThresholdInstances('SNMP'))
320 321
322 - def getDataSourceCommands(self, dsName=None):
323 """Return list of command definitions. 324 """ 325 result = [] 326 perfServer = self.device().getPerformanceServer() 327 for templ in self.getRRDTemplates(): 328 basepath = self.rrdPath() 329 if dsName: 330 dataSources = [x for x in templ.datasources() if x.id==dsName] 331 else: 332 dataSources = templ.getRRDDataSources('COMMAND') 333 for ds in dataSources: 334 if not ds.enabled: continue 335 points = [] 336 for dp in ds.getRRDDataPoints(): 337 points.append( 338 (dp.id, 339 "/".join((basepath, dp.name())), 340 dp.rrdtype, 341 dp.getRRDCreateCommand(perfServer), 342 (dp.rrdmin, dp.rrdmax))) 343 key = ds.eventKey or ds.id 344 result.append( (getattr(ds, 'usessh', False), 345 ds.cycletime, ds.component, 346 ds.eventClass, key, ds.severity, 347 ds.getCommand(self), points) ) 348 return (result, self.getThresholdInstances('COMMAND'))
349 350
351 - def getThresholdInstances(self, dsType):
352 result = [] 353 for template in self.getRRDTemplates(): 354 # if the template refers to a data source name of the right type 355 # include it 356 names = [] 357 for ds in template.getRRDDataSources(dsType): 358 for dp in ds.datapoints(): 359 names.append(dp.name()) 360 for threshold in template.thresholds(): 361 for ds in threshold.dsnames: 362 if ds in names: 363 result.append(threshold.createThresholdInstance(self)) 364 break 365 return result
366
367 - def makeLocalRRDTemplate(self, templateName=None, REQUEST=None):
368 """Make a local copy of our RRDTemplate if one doesn't exist. 369 """ 370 if templateName is None: templateName = self.getRRDTemplateName() 371 if not self.isLocalName(templateName): 372 ct = self.getRRDTemplateByName(templateName)._getCopy(self) 373 ct.id = templateName 374 self._setObject(ct.id, ct) 375 if REQUEST: 376 REQUEST['message'] = 'Local copy %s created' % templateName 377 return self.callZenScreen(REQUEST)
378 379
380 - def removeLocalRRDTemplate(self, templateName=None, REQUEST=None):
381 """Make a local delete of our RRDTemplate if one doesn't exist. 382 """ 383 if templateName is None: templateName = self.getRRDTemplateName() 384 if self.isLocalName(templateName): 385 self._delObject(templateName) 386 if REQUEST: 387 REQUEST['message'] = 'Local copy %s removed' % templateName 388 return self.callZenScreen(REQUEST)
389 390
391 -def updateCache(filenameValues):
392 _cache.update(dict(filenameValues))
393