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