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 from twisted.python import log
23
24 from zephir.monitor.agentmanager import util
25
26 DATASOURCE_TYPES = ['GAUGE', 'COUNTER', 'DERIVE', 'ABSOLUTE']
27 CONSOLIDATION_FUNCTIONS = ['AVERAGE', 'MIN', 'MAX', 'LAST']
28
29
30
31
33 if date is None:
34 timestamp = 'N'
35 else:
36 delta = date - util.TIME_ORIGIN
37 timestamp = '%d' % (delta.days*24*3600 + delta.seconds)
38 return timestamp
39
40
41
42
44 """Round-Robin Database (fichier C{.rrd})
45 """
46
48 self.rrdfile = rrdfile
49 self.step = step
50 self.datasources = []
51 self.archives = []
52 self.graphs = []
53
54
55 - def new_datasource(self, name, ds_type='GAUGE', heartbeat=None,
56 min_bound=None, max_bound=None):
57 """Ajoute une nouvelle I{datasource} (DS) à la base de données
58 """
59 if heartbeat is None:
60 heartbeat = 2 * self.step
61 ds = Datasource(name, ds_type, heartbeat, min_bound, max_bound)
62 self.datasources.append(ds)
63
64
65 - def new_archive(self, rows, consolidation='AVERAGE',
66 steps=1, xfiles_factor=0):
67 """Ajoute une nouvelle archive I{round-robin} (RRA) à la base
68 de données.
69 """
70 rra = Archive(rows, consolidation, steps, xfiles_factor)
71 self.archives.append(rra)
72
73
74 - def new_graph(self, pngname, vnamedefs, options):
75 """Ajoute un nouveau graphe à la base de données.
76
77 @param vnamedefs: {vname: (ds_name, CF)}
78 """
79
80 defs = [ "DEF:%s=%s:%s:%s" % (vname, self.rrdfile, ds, cf)
81 for vname, (ds, cf) in vnamedefs.items() ]
82 graph = Graph(pngname, defs, *options)
83 self.graphs.append(graph)
84
85
87 """Crée le fichier C{.rrd} une fois que les datasources,
88 archives et graphes ont été configurés.
89 """
90
91 if not os.path.exists(self.rrdfile):
92 begin = rrd_date_from_datetime(util.utcnow())
93 args = [self.rrdfile,
94 "-b%s" % begin,
95 "-s%d" % self.step]
96 args += map(str, self.datasources)
97 args += map(str, self.archives)
98
99 rrdtool.create(*args)
100
101
102 - def update(self, values, date=None):
103 """Insère une nouvelle valeur dans la base de données.
104
105 @param values: soit une liste de valeurs (données dans l'ordre
106 de déclaration des champs), soit un dictionnaire C{{champ:
107 valeur}}.
108 """
109 if date is None:
110 date = util.utcnow()
111 args = [self.rrdfile]
112 if type(values) is dict:
113 items = values.items()
114 args.append('-t' + ':'.join([ str(i[0]) for i in items]))
115 values = [ str(i[1]) for i in items]
116 args.append(rrd_date_from_datetime(date)+ ':' + ':'.join(values))
117
118 try:
119 rrdtool.update(*args)
120 except rrdtool.error, e:
121 log.msg(_('RRDtool warning: ') + str(e))
122
123
124 - def graph_all(self, additional_args = None):
125 """Génère ou met à jour tous les graphes de cette base de
126 données.
127 """
128 for g in self.graphs:
129 g.graph(additional_args)
130
131
132
133
135
136 - def __init__(self, name, ds_type, heartbeat,
137 min_bound=None, max_bound=None):
138 assert not name is ""
139 assert ds_type in DATASOURCE_TYPES
140 assert not heartbeat is None
141 self.name = name
142 self.type = ds_type
143 self.heartbeat = heartbeat
144 self.min_bound = min_bound
145 self.max_bound = max_bound
146
148 minb, maxb = "U", "U"
149 if self.min_bound is not None: minb = str(self.min_bound)
150 if self.max_bound is not None: maxb = str(self.max_bound)
151 return "DS:%(ds-name)s:%(DST)s:%(heartbeat)d:%(min)s:%(max)s" % {
152 'ds-name': self.name, 'DST': self.type,
153 'heartbeat': self.heartbeat,
154 'min': minb, 'max': maxb
155 }
156
157
158
159
161
162 - def __init__(self, rows, consolidation='AVERAGE',
163 steps=1, xfiles_factor=0):
164 assert consolidation in CONSOLIDATION_FUNCTIONS
165 assert xfiles_factor >= 0.0 and xfiles_factor < 1
166 self.rows = rows
167 self.consolidation = consolidation
168 self.steps = steps
169 self.xfiles_factor = xfiles_factor
170
172 return "RRA:%(CF)s:%(xff)f:%(steps)d:%(rows)d" % {
173 'CF': self.consolidation, 'xff': self.xfiles_factor,
174 'steps': self.steps,
175 'rows': self.rows
176 }
177
178
179
180
182
183 - def __init__(self, imgname, defs, *options):
184 self.imgname = imgname
185 self.defs = defs
186 self.options = list(options)
187
188
189 - def graph(self, additional_args = None):
190
191 args = [self.imgname]
192 args += map(str, self.defs)
193 args += self.options
194 if additional_args is not None:
195 args += additional_args
196 return rrdtool.graph(*args)
197
198
199
200
201
202
203
204
205
206