forked from munin-monitoring/contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboinc_wus
executable file
·448 lines (378 loc) · 12.8 KB
/
boinc_wus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
#!/usr/bin/perl -w
#
# boinc_wus - Munin plugin to monitor states of all BOINC WUs
#
# Run 'perldoc boinc_wus' for full man page
#
# Author: Palo M. <[email protected]>
# Modified by: Paul Saunders <[email protected]>
# License: GPLv3 <http://www.gnu.org/licenses/gpl-3.0.txt>
#
#
# Parameters supported:
# config
#
#
# Configurable variables
# boinccmd - command-line control program (default: boinc_cmd)
# host - Host to query (default: none)
# port - GUI RPC port (default: none = use BOINC-default)
# boincdir - Directory containing appropriate password file
# gui_rpc_auth.cfg (default: none)
# verbose - Whether display more detailed states (default: 0)
# password - Password for BOINC (default: none) !!! UNSAFE !!!
#
#
# $Log$
#
# Revision 1.1 2011/03/22 Paul Saunders
# Update for BOINC 6.12
# Add colours from http://boinc.netsoft-online.com/e107_plugins/forum/forum_viewtopic.php?3
# Revision 1.0 2009/09/13 Palo M.
# Add documentation and license information
# Ready to publish on Munin Exchange
# Revision 0.9 2009/09/13 Palo M.
# Add possibility to read password from file
# Revision 0.8 2009/09/12 Palo M.
# Update default binary name: boinc_cmd -> boinccmd
# Revision 0.7 2008/08/29 Palo M.
# Creation - Attempt to port functionality from C++ code
#
# (Revisions 0.1 - 0.6) were done in C++
#
#
#
# Magic markers:
#%# family=contrib
use strict;
#########################################################################
# 1. Parse configuration variables
#
my $BOINCCMD = exists $ENV{'boinccmd'} ? $ENV{'boinccmd'} : "boinccmd";
my $HOST = exists $ENV{'host'} ? $ENV{'host'} : undef;
my $PORT = exists $ENV{'port'} ? $ENV{'port'} : undef;
my $PASSWORD = exists $ENV{'password'} ? $ENV{'password'} : undef;
my $BOINCDIR = exists $ENV{'boincdir'} ? $ENV{'boincdir'} : undef;
my $VERBOSE = exists $ENV{'verbose'} ? $ENV{'verbose'} : "0";
#########################################################################
# 2. Basic executable
#
if (defined $HOST) {
$BOINCCMD .= " --host $HOST";
if (defined $PORT) {
$BOINCCMD .= ":$PORT";
}
}
if (defined $PASSWORD) {
$BOINCCMD .= " --passwd $PASSWORD";
}
if (defined $BOINCDIR) {
chdir $BOINCDIR;
}
#########################################################################
# 3. Initialize output structure
#
my $wu_states = {
wu_run => 0,
wu_pre => 0,
wu_sus => 0,
wu_dld => 0,
wu_rtr => 0,
wu_dlg => 0,
wu_upl => 0,
wu_err => 0,
wu_abt => 0,
wu_other => 0
};
#########################################################################
# 4. Fetch all needed data from BOINC-client with single call
#
my $prj_status = "";
my $results = "";
my $simpleGuiInfo = `$BOINCCMD --get_simple_gui_info 2>/dev/null`;
if ($simpleGuiInfo ne "") {
# Some data were retrieved, so let's split them
my @sections;
my @section1;
@sections = split /=+ Projects =+\n/, $simpleGuiInfo;
@section1 = split /=+ [A-z]+ =+\n/, $sections[1];
$prj_status = $section1[0];
@sections = split /=+ (?:Results|Tasks) =+\n/, $simpleGuiInfo;
@section1 = split /=+ [A-z]+ =+\n/, $sections[1];
$results = $section1[0];
}
#########################################################################
# 5. Parse BOINC data
#
# 5.a) Create project info structure
my @prjInfos = split /\d+\) -+\n/, $prj_status;
shift @prjInfos; # Throw out first empty line
my @susp_projects; # array of suspended projects
for my $prj_info (@prjInfos) {
my @lines = split /\n/, $prj_info;
my @prjURL = grep /^\s+master URL: /,@lines;
if ($#prjURL != 0) {die "Unexpected output from boinccmd"; }
my $prjURL =$prjURL[0];
$prjURL =~ s/^\s+master URL: //;
my @suspGUI = grep /^\s+suspended via GUI: /,@lines;
if ($#suspGUI != 0) {die "Unexpected output from boinccmd"; }
my $suspGUI =$suspGUI[0];
$suspGUI =~ s/^\s+suspended via GUI: //;
if ($suspGUI eq "yes") {
push @susp_projects, $prjURL
}
}
# 5.b) Parse results, check their states
my @rsltInfos = split /\d+\) -+\n/, $results;
shift @rsltInfos; # Throw out first empty line
for my $rslt_info (@rsltInfos) {
my @lines = split /\n/, $rslt_info;
my @schedstat = grep /^\s+scheduler state: /,@lines;
my $schedstat = $schedstat[0];
$schedstat =~ s/^\s+scheduler state: //;
my @state = grep /^\s+state: /,@lines;
my $state = $state[0];
$state =~ s/^\s+state: //;
my @acttask = grep /^\s+active_task_state: /,@lines;
my $acttask = $acttask[0];
$acttask =~ s/^\s+active_task_state: //;
my @suspGUI = grep /^\s+suspended via GUI: /,@lines;
my $suspGUI =$suspGUI[0];
$suspGUI =~ s/^\s+suspended via GUI: //;
my @prjURL = grep /^\s+project URL: /,@lines;
my $prjURL =$prjURL[0];
$prjURL =~ s/^\s+project URL: //;
if ($suspGUI eq "yes") {
$wu_states->{wu_sus} += 1;
next;
}
my @suspPRJ = grep /^$prjURL$/,@susp_projects;
if ($#suspPRJ == 0) {
$wu_states->{wu_sus} += 1;
next;
}
if ($state eq "1") {
# RESULT_FILES_DOWNLOADING
$wu_states->{wu_dlg} += 1;
next;
}
if ($state eq "2") {
# RESULT_FILES_DOWNLOADED
if ($schedstat eq "0") {
# CPU_SCHED_UNINITIALIZED 0
$wu_states->{wu_dld} += 1;
next;
}
if ($schedstat eq "1") {
# CPU_SCHED_PREEMPTED 1
$wu_states->{wu_pre} += 1;
next;
}
if ($schedstat eq "2") {
# CPU_SCHED_SCHEDULED 2
if ($acttask eq "1") {
# PROCESS_EXECUTING 1
$wu_states->{wu_run} += 1;
next;
}
if ( ($acttask eq "0") || ($acttask eq "9") ) {
# PROCESS_UNINITIALIZED 0
# PROCESS_SUSPENDED 9
# suspended by "user active"?
$wu_states->{wu_sus} += 1;
next;
}
$wu_states->{wu_other} += 1;
next;
}
$wu_states->{wu_other} += 1;
next;
}
if ($state eq "3") {
# RESULT_COMPUTE_ERROR
$wu_states->{wu_err} += 1;
next;
}
if ($state eq "4") {
# RESULT_FILES_UPLOADING
$wu_states->{wu_upl} += 1;
next;
}
if ($state eq "5") {
# RESULT_FILES_UPLOADED
$wu_states->{wu_rtr} += 1;
next;
}
if ($state eq "6") {
# RESULT_ABORTED
$wu_states->{wu_abt} += 1;
next;
}
$wu_states->{wu_other} += 1;
}
#########################################################################
# 6. Display output
#
if ( (defined $ARGV[0]) && ($ARGV[0] eq "config") ) {
#
# 6.a) Display config
#
if (defined $HOST) {
print "host_name $HOST\n";
}
print "graph_title BOINC work status\n";
print "graph_category htc\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel Workunits\n";
print "graph_total total\n";
# First state is AREA, next are STACK
print "wu_run.label Running\n";
print "wu_run.draw AREA\n";
print "wu_run.type GAUGE\n";
print "wu_pre.label Preempted\n";
print "wu_pre.draw STACK\n";
print "wu_pre.type GAUGE\n";
print "wu_sus.label Suspended\n";
print "wu_sus.draw STACK\n";
print "wu_sus.type GAUGE\n";
print "wu_dld.label Ready to run\n";
print "wu_dld.draw STACK\n";
print "wu_dld.type GAUGE\n";
print "wu_rtr.label Ready to report\n";
print "wu_rtr.draw STACK\n";
print "wu_rtr.type GAUGE\n";
print "wu_dlg.label Downloading\n";
print "wu_dlg.draw STACK\n";
print "wu_dlg.type GAUGE\n";
print "wu_upl.label Uploading\n";
print "wu_upl.draw STACK\n";
print "wu_upl.type GAUGE\n";
if ($VERBOSE ne "0") {
print "wu_err.label Computation Error\n";
print "wu_err.draw STACK\n";
print "wu_err.type GAUGE\n";
print "wu_abt.label Aborted\n";
print "wu_abt.draw STACK\n";
print "wu_abt.type GAUGE\n";
}
print "wu_other.label other states\n";
print "wu_other.draw STACK\n";
print "wu_other.type GAUGE\n";
exit 0;
}
#
# 6.b) Display state of WUs
#
print "wu_run.value $wu_states->{wu_run}\n";
print "wu_pre.value $wu_states->{wu_pre}\n";
print "wu_sus.value $wu_states->{wu_sus}\n";
print "wu_dld.value $wu_states->{wu_dld}\n";
print "wu_rtr.value $wu_states->{wu_rtr}\n";
print "wu_dlg.value $wu_states->{wu_dlg}\n";
print "wu_upl.value $wu_states->{wu_upl}\n";
if ($VERBOSE ne "0") {
print "wu_err.value $wu_states->{wu_err}\n";
print "wu_abt.value $wu_states->{wu_abt}\n";
print "wu_other.value $wu_states->{wu_other}\n";
}
else {
my $other = $wu_states->{wu_err} + $wu_states->{wu_abt} + $wu_states->{wu_other};
print "wu_other.value $other\n";
}
exit 0;
#########################################################################
# perldoc section
=head1 NAME
boinc_wus - Munin plugin to monitor states of all BOINC WUs
=head1 APPLICABLE SYSTEMS
Linux machines running BOINC and munin-node
- or -
Linux servers (running munin-node) used to collect data from other systems
which are running BOINC, but not running munin-node (e.g. non-Linux systems)
=head1 CONFIGURATION
Following configuration variables are supported:
=over 12
=item B<boinccmd>
command-line control program (default: boinccmd)
=item B<host>
Host to query (default: none)
=item B<port>
GUI RPC port (default: none = use BOINC-default)
=item B<boincdir>
Directory containing appropriate file gui_rpc_auth.cfg (default: none)
=item B<verbose>
Display unusual states details (default: 0 = Summarize unusual states as C<other>)
=item B<password>
Password for BOINC (default: none)
=back
=head2 B<Security Consideration:>
Using of variable B<password> poses a security risk. Even if the Munin
configuration file for this plugin containing BOINC-password is properly
protected, the password is exposed as environment variable and finally passed
to boinccmd as a parameter. It is therefore possible for local users of the
machine running this plugin to eavesdrop the BOINC password.
Using of variable password is therefore strongly discouraged and is left here
as a legacy option and for testing purposes.
It should be always possible to use B<boincdir> variable instead - in such case
the file gui_rpc_auth.cfg is read by boinccmd binary directly.
If this plugin is used to fetch data from remote system, the gui_rpc_auth.cfg
can be copied to special directory in a secure way (e.g. via scp) and properly
protected by file permissions.
=head1 INTERPRETATION
This plugin shows how many BOINC workunits are in all the various states.
The most important states C<Running>, C<Preempted>, C<Suspended>,
C<Ready to run>, C<Ready to report>, C<Downloading> and C<Uploading> are always
displayed. All other states are shown as C<other>.
If the variable B<verbose> is used, additionally also states
C<Computation Error> and C<Aborted> are shown separately (they are included in
C<other> otherwise).
=head1 EXAMPLES
=head2 Local BOINC Example
BOINC is running on local machine. The BOINC binaries are installed in
F</opt/boinc/custom-6.10.1/>, the BOINC is running in directory
F</usr/local/boinc/> under username boinc, group boinc and the password is used
to protect access to BOINC:
[boinc_*]
group boinc
env.boinccmd /opt/boinc/custom-6.10.1/boinccmd
env.boincdir /usr/local/boinc
env.verbose 1
=head2 Remote BOINC Example
BOINC is running on 2 remote machines C<foo> and C<bar>.
On the local machine the binary of command-line interface is installed in
directory F</usr/local/bin/>.
The BOINC password used on the remote machine C<foo> is stored in file
F</etc/munin/boinc/foo/gui_rpc_auth.cfg>.
The BOINC password used on the remote machine C<bar> is stored in file
F</etc/munin/boinc/bar/gui_rpc_auth.cfg>.
These files are owned and readable by root, readable by group munin and not
readable by others.
There are 2 symbolic links to this plugin created in the munin plugins
directory (usually F</etc/munin/plugins/>): F<snmp_foo_boincwus> and
F<snmp_bar_boincwus>
[snmp_foo_boinc*]
group munin
env.boinccmd /usr/local/bin/boinccmd
env.host foo
env.boincdir /etc/munin/boinc/foo
[snmp_bar_boinc*]
group munin
env.boinccmd /usr/local/bin/boinccmd
env.host bar
env.boincdir /etc/munin/boinc/bar
This way the plugin can be used by Munin the same way as the Munin plugins
utilizng SNMP (although this plugin itself does not use SNMP).
=head1 BUGS
There is no C<autoconf> capability at the moment. This is due to the fact, that
BOINC installations may vary over different systems, sometimes using default
directory from distribution (e.g. F</var/lib/boinc/> in Debian or Ubuntu), but
often running in user directories or in other separate directories.
Also the user-ID under which BOINC runs often differs.
Under these circumstances the C<autoconf> would be either lame or too
complicated.
=head1 AUTHOR
Palo M. <[email protected]>
=head1 LICENSE
GPLv3 L<http://www.gnu.org/licenses/gpl-3.0.txt>
=cut
# vim:syntax=perl