Package flumotion :: Package component :: Package plugs :: Module rrd
[hide private]

Source Code for Module flumotion.component.plugs.rrd

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2008 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  import os 
 23   
 24  # FIXME: use a variable like HAS_RRDTOOL like we do in similar code 
 25  try: 
 26      import rrdtool 
 27  except ImportError: 
 28      rrdtool = None 
 29   
 30  from flumotion.component.plugs import base 
 31  from flumotion.common import common, messages, i18n, log 
 32  from flumotion.common.poller import Poller 
 33   
 34  from flumotion.common.i18n import N_ 
 35  T_ = i18n.gettexter() 
 36   
 37  _DEFAULT_POLL_INTERVAL = 60 # in seconds 
 38  _DEFAULT_STEP_SIZE = 300 # in seconds 
 39   
 40  __version__ = "$Rev: 7162 $" 
 41   
 42   
43 -class ComponentRRDPlug(base.ComponentPlug):
44 """Class to create or update a RRD file with statistics""" 45 46 ### ComponentPlug methods 47
48 - def start(self, component):
49 self._rrdpoller = None 50 51 self._component = component 52 53 if not self._hasImport(): 54 return 55 56 properties = self.args['properties'] 57 self._clientsPath = properties['clients-connected-file'] 58 self._bytesPath = properties['bytes-transferred-file'] 59 self._stepSize = properties.get('step-size', _DEFAULT_STEP_SIZE) 60 self._RRDPaths = self._getRRDPaths() 61 # call to update_rrd with a poll interval 62 timeout = properties.get('poll-interval', _DEFAULT_POLL_INTERVAL) 63 self._rrdpoller = Poller(self._updateRRD, timeout)
64
65 - def stop(self, component):
66 if self._rrdpoller: 67 self._rrdpoller.stop()
68
69 - def _hasImport(self):
70 """Check rrdtool availability""" 71 if not rrdtool: 72 m = messages.Warning(T_(N_( 73 "Cannot import module '%s'.\n"), 'rrdtool'), 74 mid='rrdtool-import-error') 75 m.add(T_(N_( 76 "The RRD plug for this component is disabled."))) 77 self._component.addMessage(m) 78 return False 79 80 return True
81
82 - def _updateRRD(self):
83 """Update data in RRD file""" 84 for path in self._RRDPaths: 85 value = None 86 if path == self._clientsPath: 87 value = self._component.getClients() 88 elif path == self._bytesPath: 89 value = self._component.getBytesSent() 90 91 try: 92 rrdtool.update(path, 'N:%i' % value) 93 self.debug('RRD file [%s] updated with value: %r', 94 path, value) 95 except rrdtool.error, e: 96 # We could get an error from rrdtool on converting the 97 # value to a double or from not finding the file 98 self.warning('RRD error: %r', 99 log.getExceptionMessage(e))
100
101 - def _getRRDPaths(self):
102 """Create the RRD file using the CACTI standard configuration 103 if it doesn't exist""" 104 paths = [] 105 rrds = ( 106 (self._clientsPath, 'clients', 'GAUGE'), 107 (self._bytesPath, 'bytes', 'DERIVE'), 108 ) 109 110 for path, name, counterType in rrds: 111 if not os.path.exists(path): 112 try: 113 DAY = 60 * 60 * 24 114 count = [ 115 8 * DAY // self._stepSize, 116 56 * DAY // (self._stepSize * 6), 117 250 * DAY // (self._stepSize * 24), 118 3000 * DAY // (self._stepSize * 288), 119 ] 120 121 rrdtool.create(path, 122 '-s %d' % self._stepSize, 123 'DS:%s:%s:600:0:U' % (name, counterType), 124 'RRA:AVERAGE:0.5:1:%d' % count[0], 125 'RRA:AVERAGE:0.5:6:%d' % count[1], 126 'RRA:AVERAGE:0.5:24:%d' % count[2], 127 'RRA:AVERAGE:0.5:288:%d' % count[3], 128 'RRA:MAX:0.5:1:%d' % count[0], 129 'RRA:MAX:0.5:6:%d' % count[1], 130 'RRA:MAX:0.5:24:%d' % count[2], 131 'RRA:MAX:0.5:288:%d' % count[3]) 132 paths.append(path) 133 self.info("Created RRD file: '%s'", path) 134 except Exception, e: 135 self.warning("Error creating RRD file '%s': %s", 136 path, log.getExceptionMessage(e)) 137 m = messages.Warning(T_(N_( 138 "Could not create RRD file '%s'.\n"), path), 139 debug=log.getExceptionMessage(e), 140 mid='rrd-create-error-%s' % path) 141 self._component.addMessage(m) 142 else: 143 paths.append(path) 144 self.info("Using existing RRD file: '%s'", path) 145 146 return paths
147