Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / boinc / boinc_projs @ de047e8f

Historique | Voir | Annoter | Télécharger (12,7 ko)

1 562e63a7 Paul Saunders
#!/usr/bin/perl -w
2
#
3
# boinc_projs - Munin plugin to monitor actively running BOINC projects
4
#
5
# Run 'perldoc boinc_projs' for full man page
6
#
7
# Author:  Palo M. <palo.gm@gmail.com>
8
# Modified by: Paul Saunders <darac+munin@darac.org.uk>
9
# License: GPLv3 <http://www.gnu.org/licenses/gpl-3.0.txt>
10
#
11
#
12
# Parameters supported:
13
# 	config
14
#
15
#
16
# Configurable variables
17
#       boinccmd   - command-line control program (default: boinccmd)
18
# 	host       - Host to query (default: none = use local host)
19
#       port       - GUI RPC port (default: none = use BOINC-default)
20
#       boincdir   - Directory containing appropriate password file
21
#                    gui_rpc_auth.cfg (default: none)
22
#       password   - Password for BOINC (default: none) !!! UNSAFE !!!
23
#
24
#
25
# $Log$
26
#
27 1568bf67 darac
# Revision 1.2  2016/10/04  Paul Saunders
28
#   BoincCmd now translates states into words, so consider a "downloaded, scheduled, EXECUTING" task
29
#     to be equivalent to a "2, 2, 1" task
30
#   Really, this should be ported to use the proper RPC, rather than parsing boinccmd's output.
31 562e63a7 Paul Saunders
# Revision 1.1  2011/03/22  Paul Saunders
32
#   Update for BOINC 6.12
33
#   Add colours from http://boinc.netsoft-online.com/e107_plugins/forum/forum_viewtopic.php?3
34
# Revision 1.0  2009/09/13  Palo M.
35
#   Add documentation and license information
36
#   Ready to publish on Munin Exchange
37
# Revision 0.9  2009/09/13  Palo M.
38
#   Add possibility to read password from file
39
# Revision 0.8  2009/09/12  Palo M.
40
#   Update default binary name: boinc_cmd -> boinccmd
41
# Revision 0.7  2008/08/29  Palo M.
42
#   Creation - Attempt to port functionality from C++ code
43
#
44
# (Revisions 0.1 - 0.6) were done in C++
45
#
46
#
47
#
48
# Magic markers:
49
#%# family=contrib
50
51
use strict;
52
53
54
#########################################################################
55
# 1. Parse configuration variables
56
#
57
my $BOINCCMD = exists $ENV{'boinccmd'} ? $ENV{'boinccmd'} : "boinccmd";
58
my $HOST = exists $ENV{'host'} ? $ENV{'host'} : undef;
59
my $PORT = exists $ENV{'port'} ? $ENV{'port'} : undef;
60
my $PASSWORD = exists $ENV{'password'} ? $ENV{'password'} : undef;
61
my $BOINCDIR = exists $ENV{'boincdir'} ? $ENV{'boincdir'} : undef;
62
63
#########################################################################
64
# 2. Basic executable
65
#
66
if (defined $HOST) {
67
  $BOINCCMD .= " --host $HOST";
68
  if (defined $PORT) {
69
    $BOINCCMD .= ":$PORT";
70
  }
71
}
72
if (defined $PASSWORD) {
73
  $BOINCCMD .= " --passwd $PASSWORD";
74
}
75
if (defined $BOINCDIR) {
76
  chdir $BOINCDIR || die "Could not chdir to $BOINCDIR";
77
}
78
79
#########################################################################
80
# 3. Fetch all needed data from BOINC-client with single call
81
#
82
my $prj_status = "";
83
my $results = "";
84
85
my $simpleGuiInfo = `$BOINCCMD --get_simple_gui_info 2>/dev/null`;
86
if ($simpleGuiInfo ne "") {
87
  # Some data were retrieved, so let's split them
88
  my @sections;
89
  my @section1;
90
  @sections = split /=+ Projects =+\n/, $simpleGuiInfo;
91
  @section1 = split /=+ [A-z]+ =+\n/, $sections[1];
92
  $prj_status = $section1[0];
93
94
  @sections = split /=+ (?:Results|Tasks) =+\n/, $simpleGuiInfo;
95
  @section1 = split /=+ [A-z]+ =+\n/, $sections[1];
96
  $results = $section1[0];
97
}
98
99
if ($prj_status eq "") { exit -1; }
100
101
# 3.a) Split --get_project_status into projects
102
my @prjInfos = split /\d+\) -+\n/, $prj_status;
103
shift @prjInfos; # Throw out first empty line
104
105
# 3.b) Fetch project infos
106
my %projects;    # Store projects infos here
107
my @projects;    # Just to keep the order of projects
108
for my $prj_info (@prjInfos) {
109
  my @lines = split /\n/, $prj_info;
110
  my $line1 = shift @lines; # get project name
111
  if ($line1 !~ /^\s+name: /) { die "Unexpected output from boinccmd"; }
112
  $line1 =~ s/^\s+name: //; # Make just the project name itself
113
  my $line2 = shift @lines; # get project URL
114
  if ($line2 !~ /^\s+master URL: /) { die "Unexpected output from boinccmd"; }
115
  $line2 =~ s/^\s+master URL: //; # Make just the URL itself
116
  my $prj_url = $line2;
117
  my $prj_name = $line1;
118
  $line1 =~ s/\@/at/g;
119
  $line1 =~ s/[^0-9A-z]/_/g;
120
  my $prj_var = "prj_" . $line1;
121
  push @projects,$prj_url;
122
  $projects{$prj_url} = {
123
			 prj_name    => $prj_name,
124
			 prj_var     => $prj_var,
125
			 prj_running => 0
126
			};
127
}
128
129
130
#########################################################################
131
# 4. Parse results
132
#
133
# 4.a) Split --get_results
134
my @rsltInfos = split /\d+\) -+\n/, $results;
135
shift @rsltInfos; # Throw out first empty line
136
137
# 4.b) Parse results, find those which are running
138
for my $rslt_info (@rsltInfos) {
139
  my @lines = split /\n/, $rslt_info;
140
  my @url = grep /^\s+project URL: /,@lines;
141
  my $url = $url[0];
142
  $url =~ s/^\s+project URL: //; # Make just the URL itself
143
  my @schedstat = grep /^\s+scheduler state: /,@lines;
144
  my $schedstat = $schedstat[0];
145
  $schedstat =~ s/^\s+scheduler state: //;
146
  my @state = grep /^\s+state: /,@lines;
147
  my $state = $state[0];
148
  $state =~ s/^\s+state: //;
149
  my @acttask = grep /^\s+active_task_state: /,@lines;
150
  my $acttask = $acttask[0];
151
  $acttask =~ s/^\s+active_task_state: //;
152 1568bf67 darac
  if (( ($schedstat eq "2") && ($state eq "2") && ($acttask eq "1") ) ||
153 de047e8f Lars Kruse
      ( ($schedstat eq "scheduled") && ($state eq "downloaded") && ($acttask eq "EXECUTING") )) {
154 562e63a7 Paul Saunders
    # This is running task
155
    $projects{$url}->{prj_running} += 1;
156
  }
157
}
158
159
160
#########################################################################
161
# 5. Display output
162
#
163
164
# Project Colours from http://boinc.netsoft-online.com/e107_plugins/forum/forum_viewtopic.php?3
165
sub rgb($$$){
166
   return sprintf ('%02x%02x%02x', shift, shift, shift);
167
}
168
my %project_colour = (
169
    'climatepredition.net' => rgb(0,139,69),
170
    'Predictor@Home' => rgb(135,206,235),
171
    'SETI@home' => rgb(65,105,225),
172
    'Einstein@Home' => rgb(255,165,0),
173
    'Rosetta@home' => rgb(238,130,238),
174
    'PrimeGrid' => rgb(205,197,191),
175
    'LHC@home' => rgb(255,127,80),
176
    'World Community Grid' => rgb(250,128,114),
177
    'BURP' => rgb(0,255,127),
178
    'SZTAKI Desktop Grid' => rgb(205,79,57),
179
    'uFluids' => rgb(0,0,0),
180
    'SIMAP' => rgb(143,188,143),
181
    'Folding@Home' =>rgb(153,50,204),
182
    'MalariaControl' => rgb(30,144,255),
183
    'The Lattice Project' => rgb(0,100,0),
184
    'Pirates@Home' => rgb(127,255,0),
185
    'BBC Climate Change Experiment' => rgb(205,173,0),
186
    'Leiden Classical' => rgb(140,34,34),
187
    'SETI@home Beta' => rgb(152,245,255),
188
    'RALPH@Home' => rgb(250,240,230),
189
    'QMC@HOME' => rgb(144,238,144),
190
    'XtremLab' => rgb(130,130,130),
191
    'HashClash' => rgb(255,105,180),
192
    'cpdn seasonal' => rgb(255,255,255),
193
    'Chess960@Home Alpha' => rgb(165,42,42),
194
    'vtu@home' => rgb(255,0,0),
195
    'LHC@home alpha' => rgb(205,133,63),
196
    'TANPAKU' => rgb(189,183,107),
197
    'other' => rgb(255,193,37),
198
    'Rectilinear Crossing Number' => rgb(83,134,139),
199
    'Nano-Hive@Home' => rgb(193,205,193),
200
    'Spinhenge@home' => rgb(255,240,245),
201
    'RieselSieve' => rgb(205,183,158),
202
    'Project Neuron' => rgb(139,58,98),
203
    'RenderFarm@Home' => rgb(210,105,30),
204
    'Docking@Home' => rgb(178,223,238),
205
    'proteins@home' => rgb(0,0,255),
206
    'DepSpid' => rgb(139,90,43),
207
    'ABC@home' => rgb(222,184,135),
208
    'BOINC alpha test' => rgb(245,245,220),
209
    'WEP-M+2' => rgb(0,250,154),
210
    'Zivis Superordenador Ciudadano' => rgb(255,239,219),
211
    'SciLINC' => rgb(240,248,255),
212
    'APS@Home' => rgb(205,91,69),
213
    'PS3GRID' => rgb(0,139,139),
214
    'Superlink@Technion' => rgb(202,255,112),
215
    'BRaTS@Home' => rgb(255,106,106),
216
    'Cosmology@Home' => rgb(240,230,140),
217
    'SHA 1 Collision Search' => rgb(255,250,205),
218
);
219
220
221
if ( (defined $ARGV[0]) && ($ARGV[0] eq "config") ) {
222
#
223
# 5.a) Display config
224
#
225
226
  if (defined $HOST) {
227
    print "host_name $HOST\n";
228
  }
229
230
  print "graph_title Running BOINC processes\n";
231
  print "graph_category BOINC\n";
232
  print "graph_args --base 1000 -l 0\n";
233
  print "graph_vlabel BOINC applications\n";
234 5c9228a9 Paul Saunders
  print "graph_total Total\n";
235 562e63a7 Paul Saunders
236
  # First project is AREA, next are STACK
237
  # Not nice, but fast:
238
  my $prj1 = shift @projects;
239
  print "$projects{$prj1}->{prj_var}.label $projects{$prj1}->{prj_name}\n";
240
  if (exists $project_colour{$projects{$prj1}->{prj_name}}){
241
  	print "$projects{$prj1}->{prj_var}.colour $project_colour{$projects{$prj1}->{prj_name}}\n";
242
  }
243
  print "$projects{$prj1}->{prj_var}.draw AREA\n";
244
  print "$projects{$prj1}->{prj_var}.type GAUGE\n";
245
246
  for my $prjN (@projects) {
247
    print "$projects{$prjN}->{prj_var}.label $projects{$prjN}->{prj_name}\n";
248
    if (exists $project_colour{$projects{$prjN}->{prj_name}}){
249
  	print "$projects{$prjN}->{prj_var}.colour $project_colour{$projects{$prjN}->{prj_name}}\n";
250
    }
251
    print "$projects{$prjN}->{prj_var}.draw STACK\n";
252
    print "$projects{$prjN}->{prj_var}.type GAUGE\n";
253
  }
254
255
  exit 0;
256
}
257
258
#
259
# 5.b) Display running state of projects
260
#
261
262
for my $prjN (@projects) {
263
  print "$projects{$prjN}->{prj_var}.value $projects{$prjN}->{prj_running}\n";
264
}
265
266
exit 0;
267
268
269
#########################################################################
270
# perldoc section
271
272
=head1 NAME
273
274
boinc_projs - Munin plugin to monitor actively running BOINC projects.
275
276
=head1 APPLICABLE SYSTEMS
277
278
Linux machines running BOINC and munin-node
279
280
- or -
281
282
Linux servers (running munin-node) used to collect data from other systems 
283
which are running BOINC, but not running munin-node (e.g. non-Linux systems)
284
285
=head1 CONFIGURATION
286
287
Following configuration variables are supported:
288
289
=over 12
290
291
=item B<boinccmd>
292
293
command-line control program (default: boinccmd)
294
295
=item B<host>
296
297
Host to query (default: none)
298
299
=item B<port>
300
301
GUI RPC port (default: none = use BOINC-default)
302
303
=item B<boincdir>
304
305
Directory containing appropriate file gui_rpc_auth.cfg (default: none)
306
307
=item B<password>
308
309
Password for BOINC (default: none) 
310
311
=back
312
313
=head2 B<Security Consideration:>
314
315
Using of variable B<password> poses a security risk. Even if the Munin 
316
configuration file for this plugin containing BOINC-password is properly 
317
protected, the password is exposed as environment variable and finally passed 
318
to boinccmd as a parameter. It is therefore possible for local users of the 
319
machine running this plugin to eavesdrop the BOINC password. 
320
321
Using of variable password is therefore strongly discouraged and is left here 
322
as a legacy option and for testing purposes.
323
324
It should be always possible to use B<boincdir> variable instead - in such case 
325
the file gui_rpc_auth.cfg is read by boinccmd binary directly. 
326
If this plugin is used to fetch data from remote system, the gui_rpc_auth.cfg 
327
can be copied to special directory in a secure way (e.g. via scp) and properly 
328
protected by file permissions.
329
330
=head1 INTERPRETATION
331
332
This plugin shows the number of currently running BOINC tasks on the machine. 
333
If machine is attached to several BOINC projects, data for all these projects 
334
are displayed.
335
336
=head1 EXAMPLES
337
338
=head2 Local BOINC Example
339
340
BOINC is running on local machine. The BOINC binaries are installed in 
341
F</opt/boinc/custom-6.10.1/>, the BOINC is running in directory
342
F</usr/local/boinc/> under username boinc, group boinc and the password is used 
343
to protect access to BOINC:
344
345
  [boinc_*]
346
  group boinc
347
  env.boinccmd /opt/boinc/custom-6.10.1/boinccmd
348
  env.boincdir /usr/local/boinc
349
350
=head2 Remote BOINC Example
351
352
BOINC is running on 2 remote machines C<foo> and C<bar>. 
353
On the local machine the binary of command-line interface is installed in 
354
directory F</usr/local/bin/>.
355
The BOINC password used on the remote machine C<foo> is stored in file 
356
F</etc/munin/boinc/foo/gui_rpc_auth.cfg>.
357
The BOINC password used on the remote machine C<bar> is stored in file 
358
F</etc/munin/boinc/bar/gui_rpc_auth.cfg>.
359
These files are owned and readable by root, readable by group munin and not 
360
readable by others. 
361
There are 2 symbolic links to this plugin created in the munin plugins 
362 715d059c Diego Elio Pettenò
directory (usually F</etc/munin/plugins/>): F<boincprojs_foo> and 
363
F<boincprojs_bar>
364 562e63a7 Paul Saunders
365 715d059c Diego Elio Pettenò
  [boincprojs_foo]
366 562e63a7 Paul Saunders
  group munin
367
  env.boinccmd /usr/local/bin/boinccmd
368
  env.host foo
369
  env.boincdir /etc/munin/boinc/foo
370
371 715d059c Diego Elio Pettenò
  [boincprojs_bar]
372 562e63a7 Paul Saunders
  group munin
373
  env.boinccmd /usr/local/bin/boinccmd
374
  env.host bar
375
  env.boincdir /etc/munin/boinc/bar
376
377 715d059c Diego Elio Pettenò
This way the plugin can be used by Munin as a virtual node, akin to
378
SNMP and IPMI plugins.
379 562e63a7 Paul Saunders
380
=head1 BUGS
381
382
There is no C<autoconf> capability at the moment. This is due to the fact, that 
383
BOINC installations may vary over different systems, sometimes using default 
384
directory from distribution (e.g. F</var/lib/boinc/> in Debian or Ubuntu), but 
385
often running in user directories or in other separate directories.
386
Also the user-ID under which BOINC runs often differs. 
387
Under these circumstances the C<autoconf> would be either lame or too 
388
complicated.
389
390
=head1 AUTHOR
391
392
Palo M. <palo.gm@gmail.com>
393
394
=head1 LICENSE
395
396
GPLv3
397
398
=cut
399
400
# vim:syntax=perl