Projet

Général

Profil

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

root / plugins / other / boinc_projs @ 5c9228a9

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

1
#!/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
# Revision 1.1  2011/03/22  Paul Saunders
28
#   Update for BOINC 6.12
29
#   Add colours from http://boinc.netsoft-online.com/e107_plugins/forum/forum_viewtopic.php?3
30
# Revision 1.0  2009/09/13  Palo M.
31
#   Add documentation and license information
32
#   Ready to publish on Munin Exchange
33
# Revision 0.9  2009/09/13  Palo M.
34
#   Add possibility to read password from file
35
# Revision 0.8  2009/09/12  Palo M.
36
#   Update default binary name: boinc_cmd -> boinccmd
37
# Revision 0.7  2008/08/29  Palo M.
38
#   Creation - Attempt to port functionality from C++ code
39
#
40
# (Revisions 0.1 - 0.6) were done in C++
41
#
42
#
43
#
44
# Magic markers:
45
#%# family=contrib
46

    
47
use strict;
48

    
49

    
50
#########################################################################
51
# 1. Parse configuration variables
52
#
53
my $BOINCCMD = exists $ENV{'boinccmd'} ? $ENV{'boinccmd'} : "boinccmd";
54
my $HOST = exists $ENV{'host'} ? $ENV{'host'} : undef;
55
my $PORT = exists $ENV{'port'} ? $ENV{'port'} : undef;
56
my $PASSWORD = exists $ENV{'password'} ? $ENV{'password'} : undef;
57
my $BOINCDIR = exists $ENV{'boincdir'} ? $ENV{'boincdir'} : undef;
58

    
59
#########################################################################
60
# 2. Basic executable
61
#
62
if (defined $HOST) {
63
  $BOINCCMD .= " --host $HOST";
64
  if (defined $PORT) {
65
    $BOINCCMD .= ":$PORT";
66
  }
67
}
68
if (defined $PASSWORD) {
69
  $BOINCCMD .= " --passwd $PASSWORD";
70
}
71
if (defined $BOINCDIR) {
72
  chdir $BOINCDIR || die "Could not chdir to $BOINCDIR";
73
}
74

    
75
#########################################################################
76
# 3. Fetch all needed data from BOINC-client with single call
77
#
78
my $prj_status = "";
79
my $results = "";
80

    
81
my $simpleGuiInfo = `$BOINCCMD --get_simple_gui_info 2>/dev/null`;
82
if ($simpleGuiInfo ne "") {
83
  # Some data were retrieved, so let's split them
84
  my @sections;
85
  my @section1;
86
  @sections = split /=+ Projects =+\n/, $simpleGuiInfo;
87
  @section1 = split /=+ [A-z]+ =+\n/, $sections[1];
88
  $prj_status = $section1[0];
89

    
90
  @sections = split /=+ (?:Results|Tasks) =+\n/, $simpleGuiInfo;
91
  @section1 = split /=+ [A-z]+ =+\n/, $sections[1];
92
  $results = $section1[0];
93
}
94

    
95
if ($prj_status eq "") { exit -1; }
96

    
97
# 3.a) Split --get_project_status into projects
98
my @prjInfos = split /\d+\) -+\n/, $prj_status;
99
shift @prjInfos; # Throw out first empty line
100

    
101
# 3.b) Fetch project infos
102
my %projects;    # Store projects infos here
103
my @projects;    # Just to keep the order of projects
104
for my $prj_info (@prjInfos) {
105
  my @lines = split /\n/, $prj_info;
106
  my $line1 = shift @lines; # get project name
107
  if ($line1 !~ /^\s+name: /) { die "Unexpected output from boinccmd"; }
108
  $line1 =~ s/^\s+name: //; # Make just the project name itself
109
  my $line2 = shift @lines; # get project URL
110
  if ($line2 !~ /^\s+master URL: /) { die "Unexpected output from boinccmd"; }
111
  $line2 =~ s/^\s+master URL: //; # Make just the URL itself
112
  my $prj_url = $line2;
113
  my $prj_name = $line1;
114
  $line1 =~ s/\@/at/g;
115
  $line1 =~ s/[^0-9A-z]/_/g;
116
  my $prj_var = "prj_" . $line1;
117
  push @projects,$prj_url;
118
  $projects{$prj_url} = {
119
			 prj_name    => $prj_name,
120
			 prj_var     => $prj_var,
121
			 prj_running => 0
122
			};
123
}
124

    
125

    
126
#########################################################################
127
# 4. Parse results
128
#
129
# 4.a) Split --get_results
130
my @rsltInfos = split /\d+\) -+\n/, $results;
131
shift @rsltInfos; # Throw out first empty line
132

    
133
# 4.b) Parse results, find those which are running
134
for my $rslt_info (@rsltInfos) {
135
  my @lines = split /\n/, $rslt_info;
136
  my @url = grep /^\s+project URL: /,@lines;
137
  my $url = $url[0];
138
  $url =~ s/^\s+project URL: //; # Make just the URL itself
139
  my @schedstat = grep /^\s+scheduler state: /,@lines;
140
  my $schedstat = $schedstat[0];
141
  $schedstat =~ s/^\s+scheduler state: //;
142
  my @state = grep /^\s+state: /,@lines;
143
  my $state = $state[0];
144
  $state =~ s/^\s+state: //;
145
  my @acttask = grep /^\s+active_task_state: /,@lines;
146
  my $acttask = $acttask[0];
147
  $acttask =~ s/^\s+active_task_state: //;
148
  if ( ($schedstat eq "2") && ($state eq "2") && ($acttask eq "1") ) {
149
    # This is running task
150
    $projects{$url}->{prj_running} += 1;
151
  }
152
}
153

    
154

    
155
#########################################################################
156
# 5. Display output
157
#
158

    
159
# Project Colours from http://boinc.netsoft-online.com/e107_plugins/forum/forum_viewtopic.php?3
160
sub rgb($$$){
161
   return sprintf ('%02x%02x%02x', shift, shift, shift);
162
}
163
my %project_colour = (
164
    'climatepredition.net' => rgb(0,139,69),
165
    'Predictor@Home' => rgb(135,206,235),
166
    'SETI@home' => rgb(65,105,225),
167
    'Einstein@Home' => rgb(255,165,0),
168
    'Rosetta@home' => rgb(238,130,238),
169
    'PrimeGrid' => rgb(205,197,191),
170
    'LHC@home' => rgb(255,127,80),
171
    'World Community Grid' => rgb(250,128,114),
172
    'BURP' => rgb(0,255,127),
173
    'SZTAKI Desktop Grid' => rgb(205,79,57),
174
    'uFluids' => rgb(0,0,0),
175
    'SIMAP' => rgb(143,188,143),
176
    'Folding@Home' =>rgb(153,50,204),
177
    'MalariaControl' => rgb(30,144,255),
178
    'The Lattice Project' => rgb(0,100,0),
179
    'Pirates@Home' => rgb(127,255,0),
180
    'BBC Climate Change Experiment' => rgb(205,173,0),
181
    'Leiden Classical' => rgb(140,34,34),
182
    'SETI@home Beta' => rgb(152,245,255),
183
    'RALPH@Home' => rgb(250,240,230),
184
    'QMC@HOME' => rgb(144,238,144),
185
    'XtremLab' => rgb(130,130,130),
186
    'HashClash' => rgb(255,105,180),
187
    'cpdn seasonal' => rgb(255,255,255),
188
    'Chess960@Home Alpha' => rgb(165,42,42),
189
    'vtu@home' => rgb(255,0,0),
190
    'LHC@home alpha' => rgb(205,133,63),
191
    'TANPAKU' => rgb(189,183,107),
192
    'other' => rgb(255,193,37),
193
    'Rectilinear Crossing Number' => rgb(83,134,139),
194
    'Nano-Hive@Home' => rgb(193,205,193),
195
    'Spinhenge@home' => rgb(255,240,245),
196
    'RieselSieve' => rgb(205,183,158),
197
    'Project Neuron' => rgb(139,58,98),
198
    'RenderFarm@Home' => rgb(210,105,30),
199
    'Docking@Home' => rgb(178,223,238),
200
    'proteins@home' => rgb(0,0,255),
201
    'DepSpid' => rgb(139,90,43),
202
    'ABC@home' => rgb(222,184,135),
203
    'BOINC alpha test' => rgb(245,245,220),
204
    'WEP-M+2' => rgb(0,250,154),
205
    'Zivis Superordenador Ciudadano' => rgb(255,239,219),
206
    'SciLINC' => rgb(240,248,255),
207
    'APS@Home' => rgb(205,91,69),
208
    'PS3GRID' => rgb(0,139,139),
209
    'Superlink@Technion' => rgb(202,255,112),
210
    'BRaTS@Home' => rgb(255,106,106),
211
    'Cosmology@Home' => rgb(240,230,140),
212
    'SHA 1 Collision Search' => rgb(255,250,205),
213
);
214

    
215

    
216
if ( (defined $ARGV[0]) && ($ARGV[0] eq "config") ) {
217
#
218
# 5.a) Display config
219
#
220

    
221
  if (defined $HOST) {
222
    print "host_name $HOST\n";
223
  }
224

    
225
  print "graph_title Running BOINC processes\n";
226
  print "graph_category BOINC\n";
227
  print "graph_args --base 1000 -l 0\n";
228
  print "graph_vlabel BOINC applications\n";
229
  print "graph_total Total\n";
230

    
231
  # First project is AREA, next are STACK
232
  # Not nice, but fast:
233
  my $prj1 = shift @projects;
234
  print "$projects{$prj1}->{prj_var}.label $projects{$prj1}->{prj_name}\n";
235
  if (exists $project_colour{$projects{$prj1}->{prj_name}}){
236
  	print "$projects{$prj1}->{prj_var}.colour $project_colour{$projects{$prj1}->{prj_name}}\n";
237
  }
238
  print "$projects{$prj1}->{prj_var}.draw AREA\n";
239
  print "$projects{$prj1}->{prj_var}.type GAUGE\n";
240

    
241
  for my $prjN (@projects) {
242
    print "$projects{$prjN}->{prj_var}.label $projects{$prjN}->{prj_name}\n";
243
    if (exists $project_colour{$projects{$prjN}->{prj_name}}){
244
  	print "$projects{$prjN}->{prj_var}.colour $project_colour{$projects{$prjN}->{prj_name}}\n";
245
    }
246
    print "$projects{$prjN}->{prj_var}.draw STACK\n";
247
    print "$projects{$prjN}->{prj_var}.type GAUGE\n";
248
  }
249

    
250
  exit 0;
251
}
252

    
253
#
254
# 5.b) Display running state of projects
255
#
256

    
257
for my $prjN (@projects) {
258
  print "$projects{$prjN}->{prj_var}.value $projects{$prjN}->{prj_running}\n";
259
}
260

    
261
exit 0;
262

    
263

    
264
#########################################################################
265
# perldoc section
266

    
267
=head1 NAME
268

    
269
boinc_projs - Munin plugin to monitor actively running BOINC projects.
270

    
271
=head1 APPLICABLE SYSTEMS
272

    
273
Linux machines running BOINC and munin-node
274

    
275
- or -
276

    
277
Linux servers (running munin-node) used to collect data from other systems 
278
which are running BOINC, but not running munin-node (e.g. non-Linux systems)
279

    
280
=head1 CONFIGURATION
281

    
282
Following configuration variables are supported:
283

    
284
=over 12
285

    
286
=item B<boinccmd>
287

    
288
command-line control program (default: boinccmd)
289

    
290
=item B<host>
291

    
292
Host to query (default: none)
293

    
294
=item B<port>
295

    
296
GUI RPC port (default: none = use BOINC-default)
297

    
298
=item B<boincdir>
299

    
300
Directory containing appropriate file gui_rpc_auth.cfg (default: none)
301

    
302
=item B<password>
303

    
304
Password for BOINC (default: none) 
305

    
306
=back
307

    
308
=head2 B<Security Consideration:>
309

    
310
Using of variable B<password> poses a security risk. Even if the Munin 
311
configuration file for this plugin containing BOINC-password is properly 
312
protected, the password is exposed as environment variable and finally passed 
313
to boinccmd as a parameter. It is therefore possible for local users of the 
314
machine running this plugin to eavesdrop the BOINC password. 
315

    
316
Using of variable password is therefore strongly discouraged and is left here 
317
as a legacy option and for testing purposes.
318

    
319
It should be always possible to use B<boincdir> variable instead - in such case 
320
the file gui_rpc_auth.cfg is read by boinccmd binary directly. 
321
If this plugin is used to fetch data from remote system, the gui_rpc_auth.cfg 
322
can be copied to special directory in a secure way (e.g. via scp) and properly 
323
protected by file permissions.
324

    
325
=head1 INTERPRETATION
326

    
327
This plugin shows the number of currently running BOINC tasks on the machine. 
328
If machine is attached to several BOINC projects, data for all these projects 
329
are displayed.
330

    
331
=head1 EXAMPLES
332

    
333
=head2 Local BOINC Example
334

    
335
BOINC is running on local machine. The BOINC binaries are installed in 
336
F</opt/boinc/custom-6.10.1/>, the BOINC is running in directory
337
F</usr/local/boinc/> under username boinc, group boinc and the password is used 
338
to protect access to BOINC:
339

    
340
  [boinc_*]
341
  group boinc
342
  env.boinccmd /opt/boinc/custom-6.10.1/boinccmd
343
  env.boincdir /usr/local/boinc
344

    
345
=head2 Remote BOINC Example
346

    
347
BOINC is running on 2 remote machines C<foo> and C<bar>. 
348
On the local machine the binary of command-line interface is installed in 
349
directory F</usr/local/bin/>.
350
The BOINC password used on the remote machine C<foo> is stored in file 
351
F</etc/munin/boinc/foo/gui_rpc_auth.cfg>.
352
The BOINC password used on the remote machine C<bar> is stored in file 
353
F</etc/munin/boinc/bar/gui_rpc_auth.cfg>.
354
These files are owned and readable by root, readable by group munin and not 
355
readable by others. 
356
There are 2 symbolic links to this plugin created in the munin plugins 
357
directory (usually F</etc/munin/plugins/>): F<snmp_foo_boincprojs> and 
358
F<snmp_bar_boincprojs>
359

    
360
  [snmp_foo_boinc*]
361
  group munin
362
  env.boinccmd /usr/local/bin/boinccmd
363
  env.host foo
364
  env.boincdir /etc/munin/boinc/foo
365

    
366
  [snmp_bar_boinc*]
367
  group munin
368
  env.boinccmd /usr/local/bin/boinccmd
369
  env.host bar
370
  env.boincdir /etc/munin/boinc/bar
371

    
372
This way the plugin can be used by Munin the same way as the Munin plugins 
373
utilizng SNMP (although this plugin itself does not use SNMP).
374

    
375
=head1 BUGS
376

    
377
There is no C<autoconf> capability at the moment. This is due to the fact, that 
378
BOINC installations may vary over different systems, sometimes using default 
379
directory from distribution (e.g. F</var/lib/boinc/> in Debian or Ubuntu), but 
380
often running in user directories or in other separate directories.
381
Also the user-ID under which BOINC runs often differs. 
382
Under these circumstances the C<autoconf> would be either lame or too 
383
complicated.
384

    
385
=head1 AUTHOR
386

    
387
Palo M. <palo.gm@gmail.com>
388

    
389
=head1 LICENSE
390

    
391
GPLv3
392

    
393
=cut
394

    
395
# vim:syntax=perl