This commit is contained in:
root
2025-11-07 11:31:06 +00:00
commit 2859f93882
407 changed files with 99769 additions and 0 deletions

143
debian/smokeping/usr/sbin/smokeinfo vendored Executable file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/perl
use strict;
use warnings;
use lib (split /:/, q{}); # PERL5LIB
use lib qw(/usr/share/perl5); # LIBDIR
use Smokeping::Info;
use Getopt::Long 2.25 qw(:config no_ignore_case);
use Pod::Usage 1.14;
'$Revision: 3879 $ ' =~ /Revision: (\S*)/;
my $Revision = $1;
sub main()
{
# parse options
my %opt = (mode=>'plain',separator=>';',format=>'%le',start=>'end-24h',end=>'now');
GetOptions(\%opt, 'help|h', 'man', 'version', 'noaction|no-action|n','no-head',
'start=s','end=s','filter=s','mode=s','separator=s','format=s') or exit(1);
if($opt{help}) { pod2usage(1) }
if($opt{man}) { pod2usage(-exitstatus => 0, -verbose => 2) }
if($opt{version}) { print "smokeinfo $Revision\n"; exit(0) }
if($opt{noaction}) { die "ERROR: don't know how to \"no-action\".\n" }
my $config = shift @ARGV;
my $si = Smokeping::Info->new($config);
my $nodes = $si->fetch_nodes(pattern=>$opt{filter},mode=>$opt{mode});
my @rows = qw(med_avg med_min med_max med_now loss_avg loss_max loss_now);
print '# ',join $opt{separator}, 'node_path',@rows if not $opt{'no-head'};
print "\n";
for my $node (@$nodes) {
my $data = $si->stat_node($node,$opt{start},$opt{end});
print join $opt{separator},$node->{path},map {defined $data->{$_} ? sprintf($opt{format},$data->{$_}) : '?'} @rows;
print "\n";
}
}
main;
__END__
=head1 NAME
smokeinfo - poll smokeping site for numeric information
=head1 SYNOPSIS
B<smokeinfo> path/to/config.cfg [I<options>]
--start x rrd graph start time. (default now-24h)
--end y rrd graph end time. (default now)
--filter pattern search pattern for node selection
--mode plain (default) how to use the pattern
- plain
- recursive
- regexp
--separator ; (default)
--format %le (default)
--no-head do not print a header
--man show man-page and exit
-h, --help display this help and exit
--version output version information and exit
=head1 DESCRIPTION
SmokeInfo is a simple frontend to the L<Smokeping::Info> module. It provides
access to numeric data stored in the rrd files.
Note that --start and --end are passed directly to rrd graph. This means
they work on the same syntax.
=head2 Examples
Get all data all nodes
smokeinfo etc/config
Only show nodes directly under /Customers
smokeinfo --filter=/Customers/ etc/config
Show all nodes under /Customers
smokeinfo --mode=recursive --filter=/Customers/ etc/config
Show all nodes with '_wlan_' in the name
smokeinfo --mode=regexp --filter=_wlan_ etc/config
=head1 SEE ALSO
L<smokeping(1)>
=head1 COPYRIGHT
Copyright (c) 2009 by OETIKER+PARTNER AG. All rights reserved.
=head1 LICENSE
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
=head1 AUTHOR
S<Tobi Oetiker E<lt>tobi@oetiker.chE<gt>>
=head1 HISTORY
2009-01-05 to Initial Version
=cut
# Emacs Configuration
#
# Local Variables:
# mode: cperl
# eval: (cperl-set-style "PerlStyle")
# mode: flyspell
# mode: flyspell-prog
# End:
#
# vi: sw=4 et

184
debian/smokeping/usr/sbin/smokeping vendored Executable file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/perl
# -*-perl-*-
use strict;
use warnings;
use FindBin;
use lib (split /:/, q{}); # PERL5LIB
use lib qw(/usr/share/perl5); # LIBDIR
use Smokeping;
Smokeping::main("$FindBin::RealBin/../etc/config");
=head1 NAME
smokeping - Commandline tool for SmokePing
=head1 SYNOPSIS
B<smokeping> [ B<--email> | B<--makepod> | B<--version> | B<--restart> ]
Options:
--man[=x] Show the manpage for the program (or for probe x, if specified)
--help Help :-)
--email Send SmokePing Agents to all Targets marked DYNAMIC
--config=x Use a config file different from the default
--check Just check the config file syntax, don't start the daemon
--makepod[=x] Create POD documentation on Config file (or for probe x, if specified)
--version Show SmokePing Version
--debug Run Only once and do not Fork
--debug-daemon Start the daemon with debugging enabled
--restart Restart SmokePing
--reload Reload configuration in the running process without interrupting
any probes
--nodaemon Do no daemonize the process (no fork)
--filter=x Only measure entries which pass the filter x
--logfile=x Append warnings to logfile x.
--static[=x] Generates a static website in directory x. If x is left out,
pagedir from the config is used.
--nosleep For debugging you may want to run SmokePing without sleep interval
--gen-examples Generate the smokeping_examples document and example config files
(to be used while building inside the smokeping distribution)
With --check : check the syntax of the generated examples.
--master-url=s Run smokeping in slave mode. Attach to master for config.
--slave-name=s By default the slave will use whatever it thinks its name
is, when talking to its master. In some cases you may
probably want to override this.
--shared-secret=s File containing the shared secret for talking to the server.
--cache-dir=s Directory for temporary data storage when running in slave mode.
--pid-dir=s Directory for the PID file when running in slave mode.
(optional, defaults to --cache-dir)
=head1 DESCRIPTION
The B<smokeping> tool is the commandline part of the SmokePing system. Its
main function is to run as a daemon and send Pings to all the Targets you
have specified in the Config file. When you call B<smokeping> without
arguments it will start as a daemon and do its work.
If called with an argument, then further functions can be activated, as seen
in the Synopsis above. The B<--email> function is explained in the
documentation on the config file.
The B<--filter> option allows you to run the daemon on a big config file,
but have the config file filtered and only measure the entries that pass the
filter. This is useful for remote measurement. Run Smokeping with two
exclusive filters in two locations and rsync the rrds back to the webserver
host where you run the cgi. Filters act on the section names in the config
file. Multiple section names are concatenated with B</> like path names:
*** targets ***
+ A
....
+ B
...
++ C
This gives
/A
and
/B, /B/C
If I want to monitor /A my filter would look like this:
--filter=/A
Filters follow regular expression syntax. The are always anchored at the tip of the string.
by adding a B<!> to the front of the filter string you negate it. Matching entries will be excluded from monitoring.
Multiple B<--filter> arguments can be used to assemble complex filters:
--filter=/A --filter=/B
would include all the targets
--filter=/A --filter=/B --filter=!/B/C
would include all but /B/C.
The B<--makepod> does get used internally to produce the
L<documentation on the SmokePing configuration file|smokeping_config>.
Please refer to L<the installation document|smokeping_install> for detailed setup instructions.
=head1 SETUP
When installing SmokePing, this file has to be adjusted to fit your
local system. Three paths have to be entered.
One pointing to your B<rrdtool> installation
use lib qw(/usr/pack/rrdtool-1.0.33-to/lib/perl);
One pointing to the place where you have installed the SmokePing libraries
use lib qw(/home/oetiker/public_html/smokeping/lib);
The third path is the argument to the Smokeping::main command. It points to
the SmokePing configuration file.
use Smokeping;
Smokeping::main("/home/oetiker/.smokeping/config");
=head1 SEE ALSO
L<smokeping_config(5)>, L<smokeping_examples(5)>, L<smokeping_cgi(1)>,
L<tSmoke(1)>, L<smokeping_master_slave(7)>, L<smokeping_extend(7)>,
L<smokeping_install(7)>, L<smokeping_upgrade(7)>,
How to read the graphs https://oss.oetiker.ch/smokeping/doc/reading.en.html
=head1 COPYRIGHT
Copyright (c) 2002 by Tobias Oetiker. All right reserved.
=head1 LICENSE
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
02139, USA.
=head1 AUTHOR
Tobias Oetiker E<lt>tobi@oetiker.chE<gt>
=cut

570
debian/smokeping/usr/sbin/tSmoke vendored Executable file
View File

@@ -0,0 +1,570 @@
#!/usr/bin/perl
#
#-----------------------------------------------
# tSmoke.pl
# Dan McGinn-Combs, Sep 2003
# tSmoke.v 0.4 2004/03 McGinn-Combs
#-----------------------------------------------
#
# Modified for Smokeping official distribution since 20050526
# Original README follows
#
# tSmoke.v04.README
# - added downtime report (--downtime)
# - a few tweaks to the calculations to ensure it's consistent
#
# tSmoke.v03.README
# - Initial Release
# - The script, started through cron, will cull through a config file and
# determine which hosts are down at a point in time (Morning report) and
# send out an smtp message to a mobile phone (for example).
#
# - It will also cull through the same config file and, using an included html
# file (small change to General section of the config file), send an html
# message which shows the availability over the past day, week, month
# and quarter.
#
# - It can also show detail data depending on the setting of
# command line option "detail".
#
# tSmoke.v02.README
# - Local testing version
#-----------------------------------------------
#
# 1) This program is run via CRON or the command line
# 2) It extracts RRD information from a smokeping config file
# 3) It pulls data from RRD files to determine if anything is offline, that is returning 0 PINGs
# 4) tSmoke reports status via an SMTP alert
# 5) tSmoke also generates an SMTP mail showing historical view of availability
#
# Many thanks to the following people for their help and guidance:
# Jim Horwath of Agere Systems Inc. for his examples and pointers to Spreadsheet::WriteExcel
# Frank Harper the author of SLAMon, a tool for tracking Service Level Agreements
# Tobias Oetiker, or course, the author of Smokeping, RRDTool and MRTG
#
use strict;
use warnings;
# We need to use
# -- Smokeping libraries
# -- RRDTool
# -- Getopt::Long
#
# Point the lib variables to your implementation
use lib (split /:/, q{}); # PERL5LIB
use FindBin;
use lib qw(/usr/share/perl5); # LIBDIR
use Smokeping;
use Net::SMTP;
use Getopt::Long;
use Pod::Usage;
use RRDs;
# Point to your Smokeping config file
my $cfgfile = (shift @ARGV) || "$FindBin::Bin/../etc/config";
# global variables
my $cfg;
#this is designed to work on IPv4 only
my $havegetaddrinfo = 0;
# we want opts everywhere
my %opt;
#Hashes for the data
my (%Daily,%Weekly,%Monthly,%Quarterly); # the entries
my (%DailyC,%WeeklyC,%MonthlyC,%QuarterlyC); # a count of the entries
######################
### Moving Average ###
######################
# Just a reminder of how to do a moving average if you ever want to
# PREV,UN,<DS>,UN,1,<DS>,IF,PREV,IF,<DS>,UN,1,<DS>,IF,-,<WEIGHT>,*,A,UN,1,A,IF,+
# Change Log:
# DMC - Added Quarterly Status
# DMC - Added HTML mail reporting and consolidated functions
# DMC = Added an external HTML mail template, tMail
my $RCS_VERSION = '$id: tSmoke.v 0.4 2004/03 McGinn-Combs';
sub test_mail($) {
my $cfg = shift;
my $mail = <<"EOF";
Subject: tSmoke test
To: $cfg->{Alerts}{to}
This is a test mail with 'tSmoke --testmail'.
EOF
print "Sending a test mail to $cfg->{Alerts}{to} from $cfg->{Alerts}{from}...";
Smokeping::sendmail($cfg->{Alerts}{from}, $cfg->{Alerts}{to}, $mail);
print "done.\n";
};
sub morning_update($) {
# Send out a morning summary of devices that are down
my $cfg = shift;
my $Body = "";
my $TmpBody = "";
my $To = "";
if ( $opt{to} ) { $To = $opt{to}; } else { $To = $cfg->{Alerts}{to}; }
# Get a list of the existing RRD Files
my @rrds = split ( /\n/,list_rrds($cfg->{Targets},"","") );
my $Count = $#rrds + 1;
my $Down = 0;
foreach my $target (@rrds) {
my $Loss = 0;
my ($start,$step,$names,$data) = RRDs::fetch "$target","AVERAGE","--start","-300";
my $ERR=RRDs::error;
die "ERROR while reading $_: $ERR\n" if $ERR;
foreach my $line (@$data) {
$Loss += ( defined($$line[3]) ? $$line[3] : 0 );
}
$Down += 1 if $Loss == 0;
$target =~ s/^([a-zA-Z0-9]*\/)*//;
$target =~ s/.rrd//;
$target =~ s/\~(.*)/ from $1/ if $target =~ m/\~/;
$TmpBody .= "$target\n" if $Loss == 0;
}
$Body = <<MAIL_END;
Subject: Of $Count Hosts, $Down Down
To: $To
Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-encoding: 8bit
MIME-Version: 1.0
Of $Count Hosts, $Down Down:
$TmpBody
MAIL_END
Smokeping::sendmail($cfg->{Alerts}{from},$To,$Body);
}
sub weekly_update($) {
# Send out a formatted HTML Table of the
# Previous Day, Week, Month and Quarter Availability
# Get a list of the existing RRD Files
my @rrds = split ( /\n/,list_rrds($cfg->{Targets},"","") );
my $To = "";
if ( $opt{to} ) { $To = $opt{to}; } else { $To = $cfg->{Alerts}{to}; }
my $Body ='';
# Calculations Based on the following:
# RRDs::graph "fake.png",
# '--start','-86400',
# '-end','-300',
# "DEF:loss=${rrd}:loss:AVERAGE",
# "CDEF:avail=loss,0,100,IF", or more precisely "CDEF:avail=loss,2,GE,0,100,IF"
# and adding in the check for unknown for systems just coming on line
# "CDEF:avail=loss,UN,0,loss,IF,$pings,GE,0,100,IF"
# Arbitrarily a loss of 10% of Pings means the system was down
my $pings = $cfg->{Database}{pings} * .1;
foreach my $target (@rrds) {
# Get an average Availability for each RRD file
my $ERR;
my ($DAverage,$Dxsize,$Dysize) = RRDs::graph "fake.png",
"--start","-86400",
"--end","-600",
"--step","1008",
"DEF:loss=$target:loss:AVERAGE",
"CDEF:avail=loss,UN,0,loss,IF,$pings,GE,0,100,IF",
"PRINT:avail:AVERAGE:%.2lf";
$ERR=RRDs::error;
die "ERROR while reading $_: $ERR\n" if $ERR;
my ($WAverage,$Wxsize,$Wysize) = RRDs::graph "fake.png",
"--start","-604800",
"--end","-600",
"--step","4320",
"DEF:loss=$target:loss:AVERAGE",
"CDEF:avail=loss,UN,0,loss,IF,$pings,GE,0,100,IF",
"PRINT:avail:AVERAGE:%.2lf";
$ERR=RRDs::error;
die "ERROR while reading $_: $ERR\n" if $ERR;
my ($MAverage,$Mxsize,$Mysize) = RRDs::graph "fake.png",
"--start","-2592000",
"--end","-600",
"--step","4320",
"DEF:loss=$target:loss:AVERAGE",
"CDEF:avail=loss,UN,0,loss,IF,$pings,GE,0,100,IF",
"PRINT:avail:AVERAGE:%.2lf";
$ERR=RRDs::error;
die "ERROR while reading $_: $ERR\n" if $ERR;
my ($QAverage,$Qxsize,$Qysize) = RRDs::graph "fake.png",
"--start","-7776000",
"--end","-600",
"--step","4320",
"DEF:loss=$target:loss:AVERAGE",
"CDEF:avail=loss,UN,0,loss,IF,$pings,GE,0,100,IF",
"PRINT:avail:AVERAGE:%.2lf";
$ERR=RRDs::error;
die "ERROR while reading $_: $ERR\n" if $ERR;
$target =~ s/$cfg->{General}{datadir}\///;
$target =~ s/.rrd//;
my @Path;
push @Path,split/\//,$target;
update_stats ( \@Path, @$DAverage[0], @$WAverage[0], @$MAverage[0], @$QAverage[0]);
}
# Prepare the e-mail message
$Body = <<MAIL_END;
Subject: IT System Availability
To: $To
Content-Type: text/html; charset=iso-8859-15
Content-Transfer-encoding: 8bit
MIME-Version: 1.0
MAIL_END
open tSMOKE, $cfg->{General}{tmail} or die "ERROR: can't read $cfg->{General}{tmail}\n";
while (<tSMOKE>){
my $Summary = Summary_Sheet();
s/<##SUMMARY##>/$Summary/ig;
my $Daily = DetailSheet(86400);
s/<##DAYDETAIL##>/$Daily/ig;
my $Weekly = DetailSheet(604800);
s/<##WEEKDETAIL##>/$Weekly/ig;
my $Monthly = DetailSheet(2592000);
s/<##MONTHDETAIL##>/$Monthly/ig;
my $Quarterly = DetailSheet(7776000);
s/<##QUARTERDETAIL##>/$Quarterly/ig;
$Body .= $_;
}
close tSMOKE;
Smokeping::sendmail($cfg->{Alerts}{from}, $To, $Body);
}
sub update_stats($$$$$);
sub update_stats($$$$$) {
# Update the uptime percentages in the Hash Arrays
my $Path = shift;
my $DAverage = shift;
my $WAverage = shift;
my $MAverage = shift;
my $QAverage = shift;
#Enter everything once as it exists
#Trim off the rightmost component (hostname) and reenter the code
#If there is only one component, this is the final level
#This is an average of averages
my $Ticket = join ( ".",@$Path);
$Daily { $Ticket } += $DAverage;
$Weekly { $Ticket } += $WAverage;
$Monthly { $Ticket } += $MAverage;
$Quarterly {$Ticket } += $QAverage;
$DailyC { $Ticket }++;
$WeeklyC { $Ticket }++;
$MonthlyC { $Ticket }++;
$QuarterlyC { $Ticket }++;
my $Length = @$Path;
@$Path = @$Path [ 0 .. $Length - 2 ];
update_stats(\@$Path,$DAverage,$WAverage,$MAverage,$QAverage) if $Length > 1;
}
sub Summary_Sheet() {
my $Body = '';
$Body .= "<table border='1' bordercolor=#111111>\n";
$Body .= "<tr>\n";
$Body .= "<td class ='appHeader' colspan='5'>IT Network Systems Availability Summary</td></tr>\n";
$Body .= "<tr>\n";
$Body .= "<td class ='appHeader' colspan='5'>Compiled: ". scalar(localtime) . "</td></tr>\n";
$Body .= "<tr>\n";
$Body .= "<td class = 'subhead' width='20%'>Service</td>
<td class = 'subhead' width='20%'>Past Quarter</td>
<td class = 'subhead' width='20%'>Past Month</td>
<td class = 'subhead' width='20%'>Past Week</td>
<td class = 'subhead' width='20%'>Past Day</td></tr>\n";
foreach (sort { $a cmp $b } keys %Monthly) {
next if ( $_ =~ /\./ );
# this is a major section heading
$Body .= "<tr>\n";
$Body .= "<td class = 'SubHead'>$_</td>";
$Body .= "<td class = 'Up99'>" . sprintf('%.2f',$Quarterly{$_}/$QuarterlyC{$_}) . "%</td>"
if $Quarterly{$_}/$QuarterlyC{$_} >= 99 ;
$Body .= "<td class = 'Up95'>" . sprintf('%.2f',$Quarterly{$_}/$QuarterlyC{$_}) . "%</td>"
if $Quarterly{$_}/$QuarterlyC{$_} > 95 and $Quarterly{$_}/$QuarterlyC{$_} < 99 ;
$Body .= "<td class = 'Up90'>" . sprintf('%.2f',$Quarterly{$_}/$QuarterlyC{$_}) . "%</td>"
if $Quarterly{$_}/$QuarterlyC{$_} > 90 and $Quarterly{$_}/$QuarterlyC{$_} < 95 ;
$Body .= "<td class = 'UpNo'>" . sprintf('%.2f',$Quarterly{$_}/$QuarterlyC{$_}) . "%</td>"
if $Quarterly{$_}/$QuarterlyC{$_} < 90 ;
$Body .= "<td class = 'Up99'>" . sprintf('%.2f',$Monthly{$_}/$MonthlyC{$_}) . "%</td>"
if $Monthly{$_}/$MonthlyC{$_} >= 99 ;
$Body .= "<td class = 'Up95'>" . sprintf('%.2f',$Monthly{$_}/$MonthlyC{$_}) . "%</td>"
if $Monthly{$_}/$MonthlyC{$_} > 95 and $Monthly{$_}/$MonthlyC{$_} < 99 ;
$Body .= "<td class = 'Up90'>" . sprintf('%.2f',$Monthly{$_}/$MonthlyC{$_}) . "%</td>"
if $Monthly{$_}/$MonthlyC{$_} > 90 and $Monthly{$_}/$MonthlyC{$_} < 95 ;
$Body .= "<td class = 'UpNo'>" . sprintf('%.2f',$Monthly{$_}/$MonthlyC{$_}) . "%</td>"
if $Monthly{$_}/$MonthlyC{$_} < 90 ;
$Body .= "<td class = 'Up99'>" . sprintf('%.2f',$Weekly{$_}/$WeeklyC{$_}) . "%</td>"
if $Weekly{$_}/$WeeklyC{$_} >= 99;
$Body .= "<td class = 'Up95'>" . sprintf('%.2f',$Weekly{$_}/$WeeklyC{$_}) . "%</td>"
if $Weekly{$_}/$WeeklyC{$_} > 95 and $Weekly{$_}/$WeeklyC{$_} < 99 ;
$Body .= "<td class = 'Up90'>" . sprintf('%.2f',$Weekly{$_}/$WeeklyC{$_}) . "%</td>"
if $Weekly{$_}/$WeeklyC{$_} > 90 and $Weekly{$_}/$WeeklyC{$_} < 95 ;
$Body .= "<td class = 'UpNo'>" . sprintf('%.2f',$Weekly{$_}/$WeeklyC{$_}) . "%</td>"
if $Weekly{$_}/$WeeklyC{$_} < 90 ;
$Body .= "<td class = 'Up99'>" . sprintf('%.2f',$Daily{$_}/$DailyC{$_}) . "%</td>"
if $Daily{$_}/$DailyC{$_} >= 99;
$Body .= "<td class = 'Up95'>" . sprintf('%.2f',$Daily{$_}/$DailyC{$_}) . "%</td>"
if $Daily{$_}/$DailyC{$_} > 95 and $Daily{$_}/$DailyC{$_} < 99 ;
$Body .= "<td class = 'Up90'>" . sprintf('%.2f',$Daily{$_}/$DailyC{$_}) . "%</td>"
if $Daily{$_}/$DailyC{$_} > 90 and $Daily{$_}/$DailyC{$_} < 95 ;
$Body .= "<td class = 'UpNo'>" . sprintf('%.2f',$Daily{$_}/$DailyC{$_}) . "%</td>"
if $Daily{$_}/$DailyC{$_} < 90 ;
$Body .= "</tr>\n";
}
$Body .= "</table>";
$Body .= "<P><P><P>\n";
$Body .= "<table border='1' bordercolor=#111111><tr><td class ='appHeader'>Legend:</td>\n";
$Body .= "<tr><td class = 'Up99'>if uptime > 99% then GREEN</td></tr>\n";
$Body .= "<tr><td class = 'Up95'>if uptime > 95% but < 99% then BLUE</td></tr>\n";
$Body .= "<tr><td class = 'Up90'>if uptime > 90% but < 95% then YELLOW</td></tr>\n";
$Body .= "<tr><td class = 'UpNo'>if uptime < 90% then RED</td></tr>\n";
$Body .= "</table>\n";
return $Body;
}
sub NumDots($) {
# Count the number of dots in a string
# There's probably a better way to do this
my $DNA = shift;
my $a = 0;
while($DNA =~ /\./ig){$a++}
return $a
}
sub DetailSheet($) {
# Populate the table with details depending on the value of %opts{detail}
my $Seconds = shift;
my $Body = '';
return '' unless $opt{detail};
# Monthly/Weekly/Daily
$Body .= "<table border='1' bordercolor=#111111>\n";
$Body .= "<tr>\n";
$Body .= "<td class ='appHeader' colspan='3'>IT Network Systems Availability Previous " . $Seconds/86400 . " Day(s)</td></tr>\n";
$Body .= "<tr>\n";
$Body .= "<td class ='appHeader' colspan='3'>Compiled: ". scalar(localtime) . "</td></tr>\n";
$Body .= "<tr>\n";
$Body .= "<td class = 'SubHead' width='40%'>Service</td>
<td class = 'SubHead' width='30%'>Seconds</td>
<td class = 'SubHead' width='30%'>Percent</td></tr>\n";
my %CornBeef;
my %CornBeefC;
CASE: {
%CornBeef = %Daily, %CornBeefC = %DailyC, print "Doing Daily\n", last CASE if $Seconds == 86400;
%CornBeef = %Weekly, %CornBeefC = %WeeklyC, print "Doing Weekly\n", last CASE if $Seconds == 604800;
%CornBeef = %Monthly, %CornBeefC = %MonthlyC, print "Doing Monthly\n", last CASE if $Seconds == 2592000;
%CornBeef = %Quarterly, %CornBeefC = %QuarterlyC, print "Doing Quarterly\n", last CASE if $Seconds == 7776000;
} # end of CASE block
foreach (sort { $a cmp $b } keys %CornBeef ) {
next if NumDots ($_) > $opt{detail};
if ( $_ =~ /\./ ) {
#this is a sub section
$Body .= "<tr>\n";
$Body .= "<td class = 'SubSubHead'>$_</td>\n";
$Body .= "<td class = 'SubDetail'>" . sprintf('%.0f',(100 - $CornBeef{$_} / $CornBeefC{$_}) * ($Seconds/100)) . "</td>\n";
$Body .= "<td class = 'SubDetail'>" . sprintf('%.2f',$CornBeef{$_} / $CornBeefC{$_}) . "%</td>\n";
$Body .= "</tr>\n";
} else {
# this is a non-sub section
$Body .= "<tr>\n";
$Body .= "<td class = 'SubHead'>" . $_ . "</td>\n";
$Body .= "<td class = 'SubDetail'>" . sprintf('%.0f',(100 - $CornBeef{$_} / $CornBeefC{$_}) * ($Seconds/100)) . "</td>\n";
$Body .= "<td class = 'SubDetail'>" . sprintf('%.2f',$CornBeef{$_} / $CornBeefC{$_}) . "%</td>\n";
$Body .= "</tr>";
}
}
$Body .= "</table>\n";
return $Body;
}
sub list_rrds($$$$$);
sub list_rrds($$$$$) {
# List the RRD's used by this configuration
my $tree = shift;
my $path = shift;
my $print = shift;
my $slaves = shift;
my $nomasterpoll = shift;
my $prline = '';
if ( $opt{slaves} ) {
$slaves = $tree->{slaves} if exists( $tree->{slaves} );
} else {
$slaves = '';
}
$nomasterpoll = $tree->{nomasterpoll} if exists ( $tree->{nomasterpoll} );
foreach my $rrds (keys %{$tree}) {
if (ref $tree->{$rrds} eq 'HASH'){
$prline .= list_rrds( $tree->{$rrds}, $path."/$rrds", $print, $slaves, $nomasterpoll );
}
if ($rrds eq 'host' and $tree->{$rrds} !~ m|/| ) {
if ( exists( $opt{slaves} ) && $slaves ) {
foreach( split( /\s+/, $slaves ) ) {
my $tslave = $_;
$prline .= "$cfg->{General}{datadir}$path~$tslave".".rrd\n"
if $opt{slaves} eq '' || grep( $tslave, split( ',', $opt{slaves} ) );
}
$prline .= "$cfg->{General}{datadir}$path".".rrd\n" unless $nomasterpoll;
} else {
$prline .= "$cfg->{General}{datadir}$path".".rrd\n";
}
}
}
return $prline;
}
sub load_cfg ($) {
my $cfgfile = shift;
# my $parser = get_parser;
my $parser = Smokeping::get_parser;
$cfg = Smokeping::get_config $parser, $cfgfile;
}
###########################################################################
# The Main Program
###########################################################################
sub main($);
main($cfgfile);
sub main ($) {
umask 022;
my $cfgfile = shift;
my $sendto;
GetOptions(\%opt, 'quiet','version','testmail','listrrds','to=s','detail=n','morning','weekly','help','man','slaves:s') or pod2usage(2);
if($opt{version}) { print "$RCS_VERSION\n"; exit(0) };
if($opt{help}) { pod2usage(-verbose => 1); exit 0 };
if($opt{man}) { pod2usage(-verbose => 2); exit 0 };
load_cfg $cfgfile;
print "tSmoke for network managed by $cfg->{General}{owner}\nat $cfg->{General}{contact}\n(c) 2003 Dan McGinn-Combs\n" unless $opt{quiet};
if($opt{testmail}) { test_mail($cfg) };
if($opt{listrrds}) { print "List of Round Robin Databases used by this implementation\n";
my @rrds = split ( /\n/,list_rrds($cfg->{Targets},"","","","") );
foreach (@rrds) {
print "RRD: $_\n"; };
}
if($opt{morning}) { morning_update($cfg) };
if($opt{weekly}) { weekly_update($cfg) };
exit 0;
}
=head1 NAME
tSmoke - Commandline tool for sending SmokePing information
=head1 SYNOPSIS
B<tSmoke> [ B<--testmail> | B<--morning> | B<--weekly> | B<--version> | B<--help> | B<--man> | B<--slaves> ]
Options:
--man Show the manpage
--help Help :-)
--version Show SmokePing Version
--testmail Send a test message
--listrrds List the RRDs used by this Smokeping
--morning Send a morning synopsis
--weekly Send a weekly status report
--to E-mail address to send message (i.e. '--to=xyz@company.com.invalid'
--detail How much detail to send in weekly report (i.e. '--detail=1')
--quiet Do not print welcome
--slaves Enable slave support assumes all slaves unless csv list of slaves
is added (i.e. '--slaves' or '--slaves=slave1[,slave2...]')
=head1 DESCRIPTION
The B<tSmoke> tool is a commandline tool which interfaces with the SmokePing system.
Its main function is to send a message indicating the current status of the systems
being monitored by Smokeping or an HTML mail file containing the status over the past day,
past week and past month including an overview.
Typical crontab used to invoke this are
# Quick morning alert to see what's down
0 6 * * * /usr/local/smokeping/bin/tSmoke.pl --q --to=mobilephone@att.net.invalid --morning
# Weekly report on the percent availability of network systems with no detail
0 8 * * * /usr/local/smokeping/bin/tSmoke.pl --q --to=mailbox@company.com.invalid --weekly --detail=0
=head1 SETUP
When installing tSmoke, some variables must be adjusted to fit your local system.
We need to use the following B<libraries>:
=over
=item Smokeping
=item RRDTool Perl bindings
=item Getopt::Long
=back
Set up your libraries:
use lib "/usr/local/smokeping/lib";
use lib "/usr/local/rrdtool-1.0.39/lib/perl";
Point to your Smokeping B<config> file
my $cfgfile = "/usr/local/smokeping/etc/config";
Modify the Smokeping config file to include a path for tmail in the
General section:
tmail = /usr/local/smokeping/etc/tmail
=head1 SEE ALSO
L<smokeping(1)>, L<smokeping_config(5)>
=head1 COPYRIGHT
Copyright (c) 2003 by Dan McGinn-Combs. All right reserved.
=head1 LICENSE
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
02139, USA.
=head1 AUTHOR
Dan McGinn-Combs E<lt>d.mcginn-combs@mindspring.comE<gt>
Modified for Smokeping official distribution by Niko Tyni E<lt>ntyni@iki.fiE<gt>
=cut