1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """RRD resource poller daemon for Flumotion.
19
20 Makes periodic observations on components' UI states, recording them to
21 RRD files. One can then extract graphs using rrdtool graph. For example,
22 to show a stream bandwidth graph for the last 30 minutes with the
23 example configuration file, in the source tree as
24 conf/rrdmon/default.xml, the following command makes a graph:
25
26 rrdtool graph --end now --start end-30min --width 400 out.png \
27 DEF:ds0=/tmp/stream-bitrate.rrd:http-streamer:AVERAGE \
28 AREA:ds0#0000FF:"Stream bandwidth (bytes/sec)"
29
30 It would be possible to expose these graphs via HTTP, but I don't know
31 how useful this might be.
32
33 See L{flumotion.admin.rrdmon.config} for information on how to configure
34 the RRD resource poller.
35 """
36
37 import os
38 import random
39 import rrdtool
40 import datetime
41 import time
42
43 from flumotion.admin import multi
44 from flumotion.common import log, common
45 from flumotion.common import eventcalendar
46 from flumotion.component.base import scheduler
47
48
49 from flumotion.common import componentui
50
51 componentui
52
53 __version__ = "$Rev$"
54
55
58
59
62
63
65 return source['sample-frequency']
66
67
69
70 def makeDS():
71 if source['is-gauge']:
72 return 'DS:%s:GAUGE:%d:U:U' % (source['name'],
73 2*source['sample-frequency'])
74 else:
75 return 'DS:%s:DERIVE:%d:0:U' % (source['name'],
76 2*source['sample-frequency'])
77 return source['rrd-ds-spec'] or makeDS()
78
79
81
82 def archiveGetRRA(archive):
83 return 'RRA:' + archive['rra-spec']
84 return [archiveGetRRA(archive) for archive in source['archives']]
85
86
89
90
92 return source['component-id']
93
94
96 return source['ui-state-key']
97
98
100 logName = 'rrdmon'
101
109
125
130
137
138 def eventStopped(eventInstance):
139 pass
140
141 self.scheduler.subscribe(eventInstanceStarted, eventInstanceStopped)
142
143 for source in sources:
144 freq = sourceGetSampleFrequency(source)
145
146
147 offset = datetime.timedelta(seconds=r.randint(0, freq))
148
149 data = (str(sourceGetConnectionInfo(source)),
150 sourceGetComponentId(source),
151 sourceGetUIStateKey(source),
152 sourceGetName(source),
153 sourceGetFileName(source))
154
155
156
157 calendar = eventcalendar.Calendar()
158 calendar.addEvent(now.isoformat(),
159 now + offset, now + offset + datetime.timedelta(seconds=1),
160 data, rrule=datetime.timedelta(seconds=freq))
161 self.scheduler.setCalendar(calendar)
162
163 - def pollData(self, managerId, componentId, uiStateKey, dsName,
164 rrdFile):
165
166 def stateListToDict(l):
167 return dict([(x.get('name'), x) for x in l])
168
169 if managerId in self.multi.admins:
170 admin = self.multi.admins[managerId]
171
172 flowName, componentName = common.parseComponentId(componentId)
173
174 flows = stateListToDict(admin.planet.get('flows'))
175 if flowName not in flows:
176 self.warning('not polling %s%s:%s: no such flow %s',
177 managerId, componentId, uiStateKey,
178 flowName)
179 return
180
181 components = stateListToDict(flows[flowName].get('components'))
182 if componentName not in components:
183 self.warning('not polling %s%s:%s: no such component %s',
184 managerId, componentId, uiStateKey,
185 componentId)
186 return
187
188 state = components[componentName]
189
190 def gotUIState(uiState):
191 if not uiState.hasKey(uiStateKey):
192 self.warning('while polling %s%s:%s: uiState has no '
193 'key %s', managerId, componentId,
194 uiStateKey, uiStateKey)
195 else:
196 try:
197 value = '%d:%s' % (int(time.time()),
198 uiState.get(uiStateKey))
199 self.log("polled %s%s:%s, updating ds %s = %s",
200 managerId, componentId, uiStateKey,
201 dsName, value)
202 rrdtool.update(rrdFile, "-t", dsName, value)
203 except rrdtool.error, e:
204 self.warning('error updating rrd file %s for '
205 '%s%s:%s', rrdFile, managerId,
206 componentId, uiStateKey)
207 self.debug('error reason: %s',
208 log.getExceptionMessage(e))
209
210 def errback(failure):
211 self.warning('not polling %s%s:%s: failed to get ui '
212 'state')
213 self.debug('reason: %s', log.getFailureMessage(failure))
214
215 d = admin.componentCallRemote(state, 'getUIState')
216 d.addCallbacks(gotUIState, errback)
217