From 562e63a7bc32c4144d02ff312f05d8cda002119d Mon Sep 17 00:00:00 2001 From: Paul Saunders Date: Tue, 22 Mar 2011 12:15:32 +0100 Subject: [PATCH] Update for BOINC 6.12. --- plugins/other/boinc_projs | 721 +++++++++++++++++++++----------------- 1 file changed, 394 insertions(+), 327 deletions(-) diff --git a/plugins/other/boinc_projs b/plugins/other/boinc_projs index a9c27dcb..c8bf0172 100755 --- a/plugins/other/boinc_projs +++ b/plugins/other/boinc_projs @@ -1,327 +1,394 @@ -#!/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. -# License: GPLv3 -# -# -# 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.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; -} - -######################################################################### -# 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 =+\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") ) { - # This is running task - $projects{$url}->{prj_running} += 1; - } -} - - -######################################################################### -# 5. Display output -# - -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 BOINC\n"; - print "graph_args --base 1000 -l 0\n"; - print "graph_vlabel BOINC applications\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"; - 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"; - 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 - -command-line control program (default: boinccmd) - -=item B - -Host to query (default: none) - -=item B - -GUI RPC port (default: none = use BOINC-default) - -=item B - -Directory containing appropriate file gui_rpc_auth.cfg (default: none) - -=item B - -Password for BOINC (default: none) - -=back - -=head2 B - -Using of variable B 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 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, the BOINC is running in directory -F 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 and C. -On the local machine the binary of command-line interface is installed in -directory F. -The BOINC password used on the remote machine C is stored in file -F. -The BOINC password used on the remote machine C is stored in file -F. -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): F and -F - - [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 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 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 would be either lame or too -complicated. - -=head1 AUTHOR - -Palo M. - -=head1 LICENSE - -GPLv3 - -=cut - -# vim:syntax=perl +#!/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. +# Modified by: Paul Saunders +# License: GPLv3 +# +# +# 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.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") ) { + # 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 BOINC\n"; + print "graph_args --base 1000 -l 0\n"; + print "graph_vlabel BOINC applications\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 + +command-line control program (default: boinccmd) + +=item B + +Host to query (default: none) + +=item B + +GUI RPC port (default: none = use BOINC-default) + +=item B + +Directory containing appropriate file gui_rpc_auth.cfg (default: none) + +=item B + +Password for BOINC (default: none) + +=back + +=head2 B + +Using of variable B 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 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, the BOINC is running in directory +F 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 and C. +On the local machine the binary of command-line interface is installed in +directory F. +The BOINC password used on the remote machine C is stored in file +F. +The BOINC password used on the remote machine C is stored in file +F. +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): F and +F + + [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 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 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 would be either lame or too +complicated. + +=head1 AUTHOR + +Palo M. + +=head1 LICENSE + +GPLv3 + +=cut + +# vim:syntax=perl