#!/usr/bin/perl -w

=head1 NAME

check_smsgw

=head1 VERSION

$Id: check_smsgw,v 1.3 2004/05/25 12:26:56 fany Exp $

=head1 BESCHREIBUNG

Netsaint-kompatibles Script zum Monitoring der Mail-Zustellung

=head1 AUFRUFSYNTAX

    check_smsgw -w 500 -c 200

Das Script fragt ab, wie viele SMs wir bei Brodos noch frei haben.
(Darueber laufen smsgw.noris.net, sms-c.noris.net und auch die SMS-Alarmings
des Monitorings.)

=head1 OPTIONEN

Alle Optionen werden mittels
L<GetOptions() aus Getopt::Long|Getopt::Long/GetOptions> analysiert und koennen
daher (eindeutig) abgekuerzt werden, vgl. auch L<obiges Beispiel|/AUFRUFSYNTAX>.

=over 4

=item --url URL

URL, die abgefragt werden soll

=item --critical-threshold N

um einen kritischen Alarm zu erzeugen, wenn weniger als I<N> SMs uebrig sind

=item --warning-threshold N

um eine Warnung zu erzeugen, wenn weniger als I<N> SMs uebrig sind

=item --rrd RRD

Dateiname einer Round Robin Database (RRD), in die die Groesse des noch
bestehenden SMS-Kontingents gespeichert werden soll.

=item --ds DS

Name der RRD-Data-Source, unter der (fuer die Option L<--rrd|/-rrd RRD>) die
Zustellzeiten gespeichert werden sollen.
Default ist "sms".

=item --debug +

Schaltet lustige Debugging-Meldungen auf STDERR ein.

=item --help | -?

gibt nur diese Dokumentation aus.

=back

=head1 AUTOR

 Martin H. Sluka <fany@noris.net>
 fuer die noris network AG

=cut

use strict;
use utf8;
use warnings;

use FindBin ();
use lib $FindBin::Bin;

use Getopt::Long 'GetOptions';
use LWP::UserAgent ();
use noris::NetSaint;

sub sms($) {
    my $count = shift;
	"$count SM" . ( abs $count != 1 && 's' );
}

GetOptions(
    'url=s' => \( our $URL = 'connectivity.end2endmobile.com/balance.php' ),
    'critical-threshold=i' => \our $Critical_Threshold,
    'warning-threshold=i'  => \our $Warning_Threshold,
    'debug+'               => \my $Debug,
    'rrd=s'                => \our $RRD,
    'ds=s'                 => \( our $DS = 'sms' ),

    # Die "rrdtool" Option dient nur der Rueckwaerts-Kombatibilitaet.
    'rrdtool=s' => sub {},
    'help|?' =>
      sub { exec perldoc => -F => $0 or die "Konnte perldoc nicht ausfuehren: $!\n" }
) or exit 1;

our $NetSaint = noris::NetSaint->new;

unless ( my $ua = LWP::UserAgent->new ) {
    $NetSaint->update( Unknown => 'Ich konnte kein LWP::UserAgent-Objekt erzeugen.' );
}
elsif ( not my $response = $ua->get($URL) ) {
    $NetSaint->update( Unknown => 'Unbekannter Fehler bei der Seitenabfrage.' );
}
elsif ( not $response->is_success ) {
    $NetSaint->update(
        Unknown => "Error fetching page: " . $response->status_line );
}
elsif ( not my ($sms) =
    ( my $content = $response->content ) =~ /^\+OK, (-?\d+) SMS$/ )
{
    $NetSaint->update( Unknown => "Unbekanntes Antwortformat: $content" );
}
else {
    if ( defined $Critical_Threshold && $sms < $Critical_Threshold ) {
        $NetSaint->update( Critical => $sms < 0
            ? 'Bereits ' . sms($sms) . ' im Minus.'
            : 'Nur noch ' . sms($sms) . '.' );
    }
    elsif ( defined $Warning_Threshold && $sms < $Warning_Threshold ) {
        $NetSaint->update( Warning => $sms < 0
            ? 'Bereits ' . sms($sms) . ' im Minus.'
            : 'Nur noch ' . sms($sms) . '.' );
    }
    else {
        $NetSaint->update( OK => $sms < 0
            ? sms($sms) . ' im Minus.'
            : 'Noch ' . sms($sms) . '.' );
    }

    if ($RRD)
    {
	require RRDs;

	my $ds = defined $DS ? $DS : 'value';

	if (!-e $RRD)
	{
	    RRDs::create ($RRD, '--step', '3600',
		    "DS:${ds}:GAUGE:86400:0:10000",
		    "RRA:MIN:0.1:1:1200",
		    "RRA:AVERAGE:0.1:1:1200",
		    "RRA:MIN:0.7:24:800",
		    "RRA:AVERAGE:0.7:24:800");
	    if (my $errmsg = RRDs::error ())
	    {
		die ("RRDs::create: $errmsg");
	    }
	}

	if (-e $RRD)
	{
	    my @cmd = ($RRD, '-t', $ds, "N:$sms");
	    RRDs::update (@cmd);
	    if (my $errmsg = RRDs::error ())
	    {
		if ($errmsg =~ m/illegal attempt to update using time \d+ when last update time is \d+/i)
		{
		    # this error is ignored.
		    warn ("RRDs::update: $errmsg") if ($Debug);
		}
		else
		{
		    die ("RRDs::update: $errmsg");
		}
	    }
	}
    } # if ($RRD)
}
