zephir.monitor.agentmanager.rrd

Package zephir :: Package monitor :: Package agentmanager :: Module rrd |
[frames] | no frames]

# Source Code for Module zephir.monitor.agentmanager.rrd

      1  # -*- coding: UTF-8 -*-
      2  ###########################################################################
      3  # Eole NG - 2007
      4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
      5  # Licence CeCill  cf /root/LicenceEole.txt
      6  # eole@ac-dijon.fr
      7  ###########################################################################
      8
      9  """
     10  Interface orientée objet aux commandes RRDtool.
     11
     12  Il est conseillé de consulter la documentation des outils RRDtool:
     13  L{http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/manual/index.html}.
     14  """
     15
     16  try: _ # localized string fetch function
     17  except NameError: _ = str
     18
     19  from datetime import datetime, timedelta
     20
     21  import rrdtool, os
     22
     23  from zephir.monitor.agentmanager.util import TIME_ORIGIN, utcnow, log
     24
     25  DATASOURCE_TYPES = ['GAUGE', 'COUNTER', 'DERIVE', 'ABSOLUTE']
     26  CONSOLIDATION_FUNCTIONS = ['AVERAGE', 'MIN', 'MAX', 'LAST']
     27
     28
     29
     30
     31 -def rrd_date_from_datetime(date):
     32      if date is None:
     33          timestamp = 'N'
     34      else:
     35          delta = date - TIME_ORIGIN
     36          timestamp = '%d' % (delta.days*24*3600 + delta.seconds)
     37      return timestamp
     38
     39
     40
     41
     42 -class Database:
     43      """Round-Robin Database (fichier C{.rrd})
     44      """
     45
     46 -    def __init__(self, rrdfile, step=60):
     47          self.rrdfile = rrdfile # TODO path + basename without .rrd extension
     48          self.step = step
     49          self.datasources = []
     50          self.archives = []
     51          self.graphs = []
     52
     53
     54 -    def new_datasource(self, name, ds_type='GAUGE', heartbeat=None,
     55                         min_bound=None, max_bound=None):
     56          """Ajoute une nouvelle I{datasource} (DS) à la base de données
     57          """
     58          if heartbeat is None:
     59              heartbeat = 2 * self.step
     60          ds = Datasource(name, ds_type, heartbeat, min_bound, max_bound)
     61          self.datasources.append(ds)
     62
     63
     64 -    def new_archive(self, rows, consolidation='AVERAGE',
     65                      steps=1, xfiles_factor=0):
     66          """Ajoute une nouvelle archive I{round-robin} (RRA) à la base
     67          de données.
     68          """
     69          rra = Archive(rows, consolidation, steps, xfiles_factor)
     70          self.archives.append(rra)
     71
     72
     73 -    def new_graph(self, pngname, vnamedefs, options):
     74          """Ajoute un nouveau graphe à la base de données.
     75
     76          @param vnamedefs: {vname: (ds_name, CF)}
     77          """
     78          #TODO default options
     79          defs = [ "DEF:%s=%s:%s:%s" % (vname, self.rrdfile, ds, cf)
     80                   for vname, (ds, cf) in vnamedefs.items() ]
     81          graph = Graph(pngname, defs, *options)
     82          self.graphs.append(graph)
     83
     84
     85 -    def create(self):
     86          """Crée le fichier C{.rrd} une fois que les datasources,
     87          archives et graphes ont été configurés.
     88          """
     89          # check if already created
     90          if not os.path.exists(self.rrdfile):
     91              begin = rrd_date_from_datetime(utcnow()) # - timedelta(seconds=10))
     92              args = [self.rrdfile,
     93                      "-b%s" % begin,
     94                      "-s%d" % self.step]
     95              args += map(str, self.datasources)
     96              args += map(str, self.archives)
     97              #log.msg('RRDtool create: %s' % ' '.join(args))
     98              rrdtool.create(*args)
     99
    100
    101 -    def update(self, values, date=None): #values = list | dict
    102          """Insère une nouvelle valeur dans la base de données.
    103
    104          @param values: soit une liste de valeurs (données dans l'ordre
    105          de déclaration des champs), soit un dictionnaire C{{champ:
    106          valeur}}.
    107          """
    108          if date is None:
    109              date = utcnow()
    110          args = [self.rrdfile]
    111          if type(values) is dict:
    112              items = values.items()
    113              args.append('-t' + ':'.join([ str(i[0]) for i in items]))
    114              values = [ str(i[1]) for i in items]
    115          args.append(rrd_date_from_datetime(date)+ ':' + ':'.join(values))
    116          #log.msg(' '.join(args))
    117          try:
    118              rrdtool.update(*args)
    119          except rrdtool.error, e:
    120              log.msg(_('RRDtool warning: ') + str(e))
    121
    122
    123 -    def graph_all(self, additional_args = None):
    124          """Génère ou met à jour tous les graphes de cette base de
    125          données.
    126          """
    127          for g in self.graphs:
    128              g.graph(additional_args)
    129
    130 -    def info(self):
    131          """retourne des informations sur le fichier rrd associé
    132          """
    133          if os.path.exists(self.rrdfile):
    134              return rrdtool.info(self.rrdfile)
    135          else:
    136              return None
    137
    138 -class Datasource:
    139
    140 -    def __init__(self, name, ds_type, heartbeat,
    141                   min_bound=None, max_bound=None):
    142          assert not name is ""
    143          assert ds_type in DATASOURCE_TYPES
    144          assert not heartbeat is None
    145          self.name = name
    146          self.type = ds_type
    147          self.heartbeat = heartbeat
    148          self.min_bound = min_bound
    149          self.max_bound = max_bound
    150
    151 -    def __str__(self):
    152          minb, maxb = "U", "U"
    153          if self.min_bound is not None: minb = str(self.min_bound)
    154          if self.max_bound is not None: maxb = str(self.max_bound)
    155          return "DS:%(ds-name)s:%(DST)s:%(heartbeat)d:%(min)s:%(max)s" % {
    156              'ds-name': self.name, 'DST': self.type,
    157              'heartbeat': self.heartbeat,
    158              'min': minb, 'max': maxb
    159              }
    160
    161
    162
    163
    164 -class Archive:
    165
    166 -    def __init__(self, rows, consolidation='AVERAGE',
    167                   steps=1, xfiles_factor=0):
    168          assert consolidation in CONSOLIDATION_FUNCTIONS
    169          assert xfiles_factor >= 0.0 and xfiles_factor < 1
    170          self.rows = rows
    171          self.consolidation = consolidation
    172          self.steps = steps
    173          self.xfiles_factor = xfiles_factor
    174
    175 -    def __str__(self):
    176          return "RRA:%(CF)s:%(xff)f:%(steps)d:%(rows)d" % {
    177              'CF': self.consolidation, 'xff': self.xfiles_factor,
    178              'steps': self.steps,
    179              'rows': self.rows
    180              }
    181
    182
    183
    184
    185 -class Graph:
    186
    187 -    def __init__(self, imgname, defs, *options):
    188          self.imgname = imgname
    189          self.defs = defs
    190          self.options = list(options)
    191          # self.options.append('-z')
    192
    193 -    def graph(self, additional_args = None):
    194          #log.msg("*** rrd.graph %s" % self.imgname)
    195          args = [self.imgname]
    196          args += map(str, self.defs)
    197          args += self.options
    198          if additional_args is not None:
    199              args += additional_args
    200          return rrdtool.graph(*args)
    201
    202
    203
    204
    205  # def test_main():
    206  #     test_support.run_unittest(UserStringTest)
    207
    208  # if __name__ == "__main__":
    209  #     test_main()
    210