#!/usr/bin/perl -w

# Originally by Emmanuel BUU <emmanuel.buu@ives.fr> (c) IVèS 2008
# Adapted for scripts.mit.edu by Mitchell Berger <mitchb@mit.edu>

use Net::LDAP;
use strict;

my $nl  = $ENV{'USE_NEWLINES'} ? "\n" : "";
my $tab = $ENV{'USE_NEWLINES'} ? "  " : "";

# Nagios codes
my %ERRORS=('OK'=>0, 'WARNING'=>1, 'CRITICAL'=>2, 'UNKNOWN'=>3, 'DEPENDENT'=>4);

my $ldapserver = 'ldapi://%2fvar%2frun%2fslapd-scripts.socket';
my $user = 'cn=Directory Manager';
my $passwdfile = '/etc/signup-ldap-pw';
my $configBase = "cn=config";
my $replicatedBase = "dc=scripts,dc=mit,dc=edu";
my $server="nsDS5ReplicaHost";
my $status="nsds5replicaLastUpdateStatus";
my $laststart="nsds5replicaLastUpdateStart";
my $lastend="nsds5replicaLastUpdateEnd";
 
my $ldap=ConnectLdap();
my $result=LDAPSearch($ldap,"objectClass=nsDS5ReplicationAgreement","",$configBase);
my @entries = $result->entries;
my $replicaErrors = 0;
my $conflictErrors = 0;
my $errorstring = "Replication error(s): $nl";
foreach my $entr ( @entries ) {
    my $servername=$entr->get_value($server);
    my $serverstatus=$entr->get_value($status);
    my $serverlaststart=$entr->get_value($laststart);
    my $serverlastend=$entr->get_value($lastend);
    my $statuscode = $serverstatus;
    $statuscode =~ s/^(?|([-0123456789]+)|Error \(([-0123456789]+)\)) (.*)$/$1/;
    $serverlaststart =~ s/(....)(..)(..)(..)(..)(..)./$1-$2-$3\ $4:$5:$6/;
    $serverlastend =~ s/(....)(..)(..)(..)(..)(..)./$1-$2-$3\ $4:$5:$6/;
    print "Replication to $servername last operation $serverlaststart $nl";
    print $tab . "Status: $serverstatus.     $nl";
    if ($statuscode) {
        $replicaErrors++;
        $errorstring = $errorstring . $serverstatus . ", ";
    }
}
print "$nl";

$result=LDAPSearch($ldap,"nsds5ReplConflict=*",["nsds5ReplConflict"],$replicatedBase);
@entries = $result->entries;
foreach my $entr ( @entries ) {
    my $conflictingDN=$entr->dn();
    my $conflictDesc=$entr->get_value("nsds5ReplConflict");
    print "Conflict found for DN $conflictingDN $nl";
    print $tab . "Reason: $conflictDesc.     $nl";
    $conflictErrors++;
    $errorstring = $errorstring . $conflictDesc . ", ";
}
print "$nl";

if ($conflictErrors > 0) {
    &nagios_return("CRITICAL", $errorstring);
} elsif ($replicaErrors > 0) {
    &nagios_return("WARNING", $errorstring);
} else {
    &nagios_return("OK", "All replicas are OK and no conflicts are present");
}

sub ConnectLdap {
    my $ldap = Net::LDAP->new ( $ldapserver ) or die "$@";
    open (PASSWD, $passwdfile) || &nagios_return("CRITICAL", "Could not read credentials");
    my $passwd = <PASSWD>;
    close (PASSWD);
    my $mesg = $ldap->bind ( "$user", password => "$passwd" , version => 3 );
    if ($mesg->code) {
        &nagios_return("CRITICAL", "Failed to bind to LDAP: " . $mesg->error);
    }
    return $ldap;
}

sub LDAPSearch {
    my ($ldap,$searchString,$attrs,$base) = @_;
    my $result = $ldap->search ( base    => "$base",
                                 scope   => "sub",
                                 filter  => "$searchString",
                                 attrs   =>  $attrs
                               );
}

sub nagios_return($$) {
    my ($ret, $message) = @_;
    my ($retval, $retstr);
    if (defined($ERRORS{$ret})) {
        $retval = $ERRORS{$ret};
        $retstr = $ret;
    } else {
        $retstr = 'UNKNOWN';
        $retval = $ERRORS{$retstr};
    }
    $message = "$retstr - $message\n";
    print $message;
    exit $retval;
}

