# -*- perl -*-
#
# $Revision: 1.5 $
package afsd;

require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(&print_usage &print_version &service_test);
use lib $main::runtimedir;
use csl_utils qw($TIMEOUT %ERRORS);
use strict;

sub print_usage ();
sub print_version ();
sub service_test (%);

my $badipok = 7000;
my $warning = 9;
my $critical = 3;

sub print_usage () {

    print "
Usage:  Check afsd service.
Options:
    -H <hostname> -P <portnumber> [--verbose]
    --help
    --version
    --usage
";
    return $ERRORS{'OK'};
}

sub print_version () {
    my $version = '$Revision: 1.5 $';
    $version =~ s/^\$Revision: //;
    $version =~ s/ \$\s*$//;

    print "afsd.pm - $version\n";
    return $ERRORS{'OK'};
}

sub service_test (%) {
    my %options = @_;

    if ($options{"verbose"}) {
        foreach my $opt (sort keys(%options)) {
            if ($options{$opt}) {
                print "$opt - $options{$opt}\n";
            }
        }
    }

    my $host = $options{"opt_H"};

    if ((!$host) || ($host eq "")) {
        print "\nHost name not specified.\n";
        &print_usage();
        return $ERRORS{'OK'};
    }

    my $port = $options{"opt_P"};

    if ((!$port) || ($port eq "")) {
        print "\nPort number not specified.\n";
        &print_usage();
        return $ERRORS{'OK'};
    }

    my $output = "";
    my $progstatus = "OK";
    my @ports = split(",", $port);

    my $rxdebug = "/usr/afsws/etc/rxdebug";
    my ($status, $return);

    my $alrmtimout = ($TIMEOUT/($#ports+1))-1;
    $alrmtimout = 3 if ($alrmtimout<3);

    PORT: foreach my $port (@ports) {

        $return = "Port $port: server timed out";
        $status = "CRITICAL";
        my $lastip = "";
        my %badips;
        my $badipcount = 0;
        my $threads;

        $SIG{'ALRM'} = sub {
            $output .= "$status: $return";

            print "$output\n";
            print "Exit status: $status\n" if $options{"verbose"};
            exit $ERRORS{"CRITICAL"};
        };
        alarm(($TIMEOUT/($#ports+1))-1);

        print "$rxdebug -rxstats $host $port\n" if $options{"verbose"};

        open CMD, "$rxdebug -rxstats $host $port 2>&1 |";

        LOOP: while ( <CMD> ) {
            if ( /WARNING/ ) {
                $status = "CRITICAL";
                $return = "Port $port: $_";
                chomp $return;
                last LOOP;
            } elsif ( /packets:.*packet reclaims:.*calls:.*used FDs:.*/ ) {
                $status = "OK";
                $return = "Port $port: $_";
                chomp $return;
            } elsif ( /Connection from host (\d+\.\d+\.\d+\.\d+)/ ) {
                $lastip = $1;
            } elsif ( /mode:\serror/ ) {
                $status = "CRITICAL";
                $badips{$lastip}++;
                $badipcount++;
            } elsif ($port == 7000) {
                if ( /^(\d+) threads are idle/) {
                    $threads = $1;
                }
            }
        }

        if ($port == 7000) {
            $threads = 0 unless ($threads);

            if ($threads <= $critical) {
                $status = "CRITICAL";
                $return = "NOT ENOUGH THREADS: $threads: $return";
            } elsif ($threads <= $warning) {
                $status = "WARNING";
                $return = "NOT ENOUGH THREADS: $threads: $return";
            }
        }
        if ($badipcount <= $badipok) {
            $status = "OK";
        }

        print "$status - $threads - $return\n" if $options{"verbose"};

        my $printthreads = "";
        $printthreads = "($threads threads)" if ($threads);
        if ($badipcount) {
            my $returnadd = "$printthreads ERROR IPS: ";
            foreach my $ips (keys %badips) {
                $returnadd .= "$ips ($badips{$ips} times): ";
            }
            $return = "$returnadd: $return";
        }
        $output .= "$status: $return, ";


        if ($ERRORS{$status}) {
            $progstatus = $status;
        }
    }
    chomp $output;
    chomp $output;
    print "$output\n";
    print "Exit status: $status\n" if $options{"verbose"};

    exit $ERRORS{$progstatus};
}

