1
2
3
4
5
6
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: _
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
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
43 """Round-Robin Database (fichier C{.rrd})
44 """
45
47 self.rrdfile = rrdfile
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
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
86 """Crée le fichier C{.rrd} une fois que les datasources,
87 archives et graphes ont été configurés.
88 """
89
90 if not os.path.exists(self.rrdfile):
91 begin = rrd_date_from_datetime(utcnow())
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
98 rrdtool.create(*args)
99
100
101 - def update(self, values, date=None):
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
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
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
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
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
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
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
186
187 - def __init__(self, imgname, defs, *options):
188 self.imgname = imgname
189 self.defs = defs
190 self.options = list(options)
191
192
193 - def graph(self, additional_args = None):
194
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
206
207
208
209
210