- Repository
- Munin (contrib)
- Last change
- 2018-08-02
- Graph Categories
- Family
- contrib
- Keywords
- Language
- Perl
- License
- GPL-3.0-only
- Authors
boinc_projs
Name
boinc_projs - Munin plugin to monitor actively running BOINC projects.
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)
Configuration
Following configuration variables are supported:
boinccmd
command-line control program (default: boinccmd)
host
Host to query (default: none)
port
GUI RPC port (default: none = use BOINC-default)
boincdir
Directory containing appropriate file gui_rpc_auth.cfg (default: none)
password
Password for BOINC (default: none)
Security Consideration:
Using of variable 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 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.
Interpretation
This plugin shows the number of currently running BOINC tasks on the machine. If machine is attached to several BOINC projects, data for all these projects are displayed.
Examples
Local Boinc Example
BOINC is running on local machine. The BOINC binaries are installed in
/opt/boinc/custom-6.10.1/
, the BOINC is running in directory
/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
Remote Boinc Example
BOINC is running on 2 remote machines foo
and bar
.
On the local machine the binary of command-line interface is installed in
directory /usr/local/bin/
.
The BOINC password used on the remote machine foo
is stored in file
/etc/munin/boinc/foo/gui_rpc_auth.cfg
.
The BOINC password used on the remote machine bar
is stored in file
/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 /etc/munin/plugins/
): boincprojs_foo
and
boincprojs_bar
[boincprojs_foo]
group munin
env.boinccmd /usr/local/bin/boinccmd
env.host foo
env.boincdir /etc/munin/boinc/foo
[boincprojs_bar]
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 as a virtual node, akin to SNMP and IPMI plugins.
Bugs
There is no 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. /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 autoconf
would be either lame or too
complicated.
Author
Palo M. palo.gm@gmail.com
License
GPLv3
#!/usr/bin/perl -w
#
# boinc_projs - Munin plugin to monitor actively running BOINC projects
#
# Run 'perldoc boinc_projs' for full man page
#
# Author: Palo M. <palo.gm@gmail.com>
# Modified by: Paul Saunders <darac+munin@darac.org.uk>
# License: GPLv3 <http://www.gnu.org/licenses/gpl-3.0.txt>
#
#
# Parameters supported:
# config
#
#
# Configurable variables
# boinccmd - command-line control program (default: boinccmd)
# host - Host to query (default: none = use local host)
# port - GUI RPC port (default: none = use BOINC-default)
# boincdir - Directory containing appropriate password file
# gui_rpc_auth.cfg (default: none)
# password - Password for BOINC (default: none) !!! UNSAFE !!!
#
#
# $Log$
#
# Revision 1.2 2016/10/04 Paul Saunders
# BoincCmd now translates states into words, so consider a "downloaded, scheduled, EXECUTING" task
# to be equivalent to a "2, 2, 1" task
# Really, this should be ported to use the proper RPC, rather than parsing boinccmd's output.
# 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;
#########################################################################
# 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 || die "Could not chdir to $BOINCDIR";
}
#########################################################################
# 3. 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];
}
if ($prj_status eq "") { exit -1; }
# 3.a) Split --get_project_status into projects
my @prjInfos = split /\d+\) -+\n/, $prj_status;
shift @prjInfos; # Throw out first empty line
# 3.b) Fetch project infos
my %projects; # Store projects infos here
my @projects; # Just to keep the order of projects
for my $prj_info (@prjInfos) {
my @lines = split /\n/, $prj_info;
my $line1 = shift @lines; # get project name
if ($line1 !~ /^\s+name: /) { die "Unexpected output from boinccmd"; }
$line1 =~ s/^\s+name: //; # Make just the project name itself
my $line2 = shift @lines; # get project URL
if ($line2 !~ /^\s+master URL: /) { die "Unexpected output from boinccmd"; }
$line2 =~ s/^\s+master URL: //; # Make just the URL itself
my $prj_url = $line2;
my $prj_name = $line1;
$line1 =~ s/\@/at/g;
$line1 =~ s/[^0-9A-z]/_/g;
my $prj_var = "prj_" . $line1;
push @projects,$prj_url;
$projects{$prj_url} = {
prj_name => $prj_name,
prj_var => $prj_var,
prj_running => 0
};
}
#########################################################################
# 4. Parse results
#
# 4.a) Split --get_results
my @rsltInfos = split /\d+\) -+\n/, $results;
shift @rsltInfos; # Throw out first empty line
# 4.b) Parse results, find those which are running
for my $rslt_info (@rsltInfos) {
my @lines = split /\n/, $rslt_info;
my @url = grep /^\s+project URL: /,@lines;
my $url = $url[0];
$url =~ s/^\s+project URL: //; # Make just the URL itself
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: //;
if (( ($schedstat eq "2") && ($state eq "2") && ($acttask eq "1") ) ||
( ($schedstat eq "scheduled") && ($state eq "downloaded") && ($acttask eq "EXECUTING") )) {
# This is running task
$projects{$url}->{prj_running} += 1;
}
}
#########################################################################
# 5. Display output
#
# Project Colours from http://boinc.netsoft-online.com/e107_plugins/forum/forum_viewtopic.php?3
sub rgb($$$){
return sprintf ('%02x%02x%02x', shift, shift, shift);
}
my %project_colour = (
'climatepredition.net' => rgb(0,139,69),
'Predictor@Home' => rgb(135,206,235),
'SETI@home' => rgb(65,105,225),
'Einstein@Home' => rgb(255,165,0),
'Rosetta@home' => rgb(238,130,238),
'PrimeGrid' => rgb(205,197,191),
'LHC@home' => rgb(255,127,80),
'World Community Grid' => rgb(250,128,114),
'BURP' => rgb(0,255,127),
'SZTAKI Desktop Grid' => rgb(205,79,57),
'uFluids' => rgb(0,0,0),
'SIMAP' => rgb(143,188,143),
'Folding@Home' =>rgb(153,50,204),
'MalariaControl' => rgb(30,144,255),
'The Lattice Project' => rgb(0,100,0),
'Pirates@Home' => rgb(127,255,0),
'BBC Climate Change Experiment' => rgb(205,173,0),
'Leiden Classical' => rgb(140,34,34),
'SETI@home Beta' => rgb(152,245,255),
'RALPH@Home' => rgb(250,240,230),
'QMC@HOME' => rgb(144,238,144),
'XtremLab' => rgb(130,130,130),
'HashClash' => rgb(255,105,180),
'cpdn seasonal' => rgb(255,255,255),
'Chess960@Home Alpha' => rgb(165,42,42),
'vtu@home' => rgb(255,0,0),
'LHC@home alpha' => rgb(205,133,63),
'TANPAKU' => rgb(189,183,107),
'other' => rgb(255,193,37),
'Rectilinear Crossing Number' => rgb(83,134,139),
'Nano-Hive@Home' => rgb(193,205,193),
'Spinhenge@home' => rgb(255,240,245),
'RieselSieve' => rgb(205,183,158),
'Project Neuron' => rgb(139,58,98),
'RenderFarm@Home' => rgb(210,105,30),
'Docking@Home' => rgb(178,223,238),
'proteins@home' => rgb(0,0,255),
'DepSpid' => rgb(139,90,43),
'ABC@home' => rgb(222,184,135),
'BOINC alpha test' => rgb(245,245,220),
'WEP-M+2' => rgb(0,250,154),
'Zivis Superordenador Ciudadano' => rgb(255,239,219),
'SciLINC' => rgb(240,248,255),
'APS@Home' => rgb(205,91,69),
'PS3GRID' => rgb(0,139,139),
'Superlink@Technion' => rgb(202,255,112),
'BRaTS@Home' => rgb(255,106,106),
'Cosmology@Home' => rgb(240,230,140),
'SHA 1 Collision Search' => rgb(255,250,205),
);
if ( (defined $ARGV[0]) && ($ARGV[0] eq "config") ) {
#
# 5.a) Display config
#
if (defined $HOST) {
print "host_name $HOST\n";
}
print "graph_title Running BOINC processes\n";
print "graph_category htc\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel BOINC applications\n";
print "graph_total Total\n";
# First project is AREA, next are STACK
# Not nice, but fast:
my $prj1 = shift @projects;
print "$projects{$prj1}->{prj_var}.label $projects{$prj1}->{prj_name}\n";
if (exists $project_colour{$projects{$prj1}->{prj_name}}){
print "$projects{$prj1}->{prj_var}.colour $project_colour{$projects{$prj1}->{prj_name}}\n";
}
print "$projects{$prj1}->{prj_var}.draw AREA\n";
print "$projects{$prj1}->{prj_var}.type GAUGE\n";
for my $prjN (@projects) {
print "$projects{$prjN}->{prj_var}.label $projects{$prjN}->{prj_name}\n";
if (exists $project_colour{$projects{$prjN}->{prj_name}}){
print "$projects{$prjN}->{prj_var}.colour $project_colour{$projects{$prjN}->{prj_name}}\n";
}
print "$projects{$prjN}->{prj_var}.draw STACK\n";
print "$projects{$prjN}->{prj_var}.type GAUGE\n";
}
exit 0;
}
#
# 5.b) Display running state of projects
#
for my $prjN (@projects) {
print "$projects{$prjN}->{prj_var}.value $projects{$prjN}->{prj_running}\n";
}
exit 0;
#########################################################################
# perldoc section
=head1 NAME
boinc_projs - Munin plugin to monitor actively running BOINC projects.
=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<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 the number of currently running BOINC tasks on the machine.
If machine is attached to several BOINC projects, data for all these projects
are displayed.
=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
=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<boincprojs_foo> and
F<boincprojs_bar>
[boincprojs_foo]
group munin
env.boinccmd /usr/local/bin/boinccmd
env.host foo
env.boincdir /etc/munin/boinc/foo
[boincprojs_bar]
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 as a virtual node, akin to
SNMP and IPMI plugins.
=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. <palo.gm@gmail.com>
=head1 LICENSE
GPLv3
=cut
# vim:syntax=perl