#!/usr/bin/perl
#
# Program: LDAP Statistics Gatherer <ldap-gather.pl>
#
# Author: Ryan Matteson <matty@daemons.net>
#
# Current Version: 1.0
#
# Last Updated: 11-20-2004
#
# Purpose: 
#   ldap-gather is a Perl script designed to extract various performance
#   metrics from an OpenLDAP server
#
# 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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Installation: 
#   Copy the Perl script to a suitable location
# 
# Usage (script should be run as a non-privileged user): 
#   $ ./ldap-gather.pl
#   Usage: ldap-gather.pl [ -s server ] [ -p port ] [ -d dir ] [ -h ]
# 
# Examples:
#  Grab the statistics from ldap.daemons.net and store them in the
#  directory /var/ldap_data 
#  $ ldap-gather.pl -s ldap.daemons.net -p 389 -d /var/ldap_data

use Net::LDAP;
use Getopt::Std;
use Time::Local;

#######################################
#  Global variables get set to 0 here #
#######################################
my $searchResults = 0;
my $ldap = 0;
my $mesg = 0;
my $initiated_operations = 0;
my $total_connections = 0;
my $bytes_sent = 0;
my $completed_operations = 0;
my $referrals_sent = 0;
my $entries_sent = 0;
my $bind_operations = 0;
my $unbind_operations = 0;
my $add_operations = 0;
my $delete_operations = 0;
my $modify_operations = 0;
my $compare_operations = 0;
my $search_operations = 0;
my $write_waiters = 0;
my $read_waiters = 0;
my $modrdn_operations = 0;
my $timestamp = time();
my ($ss, $mm, $hr, $md, $mo, $yr, $wd, $yd, $isdst) = localtime(time());
my $year = 2000 + ($yr - 100);
my $filename = "ldapallator-$year-$mo-$md-000";
my $dir = 0;
my $ldap_file = 0;
my $write_waiters = 0;
my $read_waiters = 0;


###################################
# Get the arguments from the user #
###################################

%options=();
getopts("hp:s:d:",\%options);

if ( defined $options{s} ) {
        $server  = $options{s};
}

if ( defined $options{p} ) {
        $port = $options{p};
}

if ( defined $options{d} ) {
	$dir = $options{d};
}

if (defined $options{h} ) {
        printf("Usage: ldap-gather.pl [ -s server ] [ -p port ] [ -d delay ] [ -h ]\n");
        exit(1)
}

if ( ( ! $server ) || (! $port )  || (! $dir)) {
       printf("Usage: ldap-gather.pl [ -s server ] [ -p port ] [ -d dir ] [ -h ]\n");
        exit(1);
}


######################################
# Open the file if it doesn't exist  #
######################################
$ldap_file = "$dir/$filename";

if ( -e $ldap_file ) {
	open (LDAPFILE, ">>$ldap_file") || die "ERROR: Couldn't open $ldap_file in append mode\n";

} else {
	open(LDAPFILE, ">$ldap_file") || die "ERROR: Couldn't open $ldap_file in write mode\n";

	print LDAPFILE ("TIMESTAMP TOTAL_CONNECTIONS BYTES_SENT INITIATED_OPERATIONS COMPLETED_OPERATIONS REFERRALS_SENT ENTRIES_SENT BIND_OPERATIONS UNBIND_OPERATIONS ADD_OPERATIONS DELETE_OPERATIONS MODIFY_OPERATIONS COMPARE_OPERATIONS SEARCH_OPERATIONS MODRDN_OPERATIONS WRITE_WAITERS READ_WAITERS\n");
}



######################################
# Create new connection to server    #
######################################
$ldap = new Net::LDAP($server, port=> $port) 
	or die($@);

######################################
# Send a bind operation to DS        #
######################################
$ldap->bind(
           "base"     => "",
           "version"  => 3
) or die($@);

#################################################
# Get all of the values from the monitor branch #
#################################################
$searchResults = $ldap->search (
        "base"   => "cn=monitor",
        "filter" => "(objectclass=*)",
        "scope"  => "sub"
) or die($@);

foreach my $entry ($searchResults->entries) {

	if ( $entry->dn =~ /^cn=Total,cn=Connections,cn=Monitor$/ ) {
                $total_connections = ${$entry->get('description')}[0];

	} elsif ( $entry->dn =~ /^cn=Bytes,cn=Statistics,cn=Monitor$/ ) {
		$bytes_sent = ${$entry->get('description')}[0];

	} elsif ( $entry->dn =~ /^cn=Completed,cn=Operations,cn=Monitor$/ ) {
		$completed_operations = ${$entry->get('description')}[0];

	} elsif ( $entry->dn =~ /^cn=Initiated,cn=Operations,cn=Monitor$/ ) {
                $initiated_operations = ${$entry->get('description')}[0];

	} elsif ( $entry->dn =~ /^cn=Referrals,cn=Statistics,cn=Monitor$/ ) {
                $referrals_sent = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /$cn=Entries,cn=Statistics,cn=Monitor$/ ) {
                $entries_sent = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=Bind,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $bind_operations = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=Unbind,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $unbind_operations = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=Add,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $add_operations = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=Delete,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $delete_operations = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=cn=Modify,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $modify_operations = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=Compare,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $compare_operations = ${$entry->get('description')}[0];

        }  elsif ( $entry->dn =~ /^cn=Search,cn=Completed,cn=Operations,cn=Monitor$/ ) {
                $search_operations = ${$entry->get('description')}[0];

	}  elsif ( $entry->dn =~ /^cn=Modrdn,cn=Completed,cn=Operations,cn=Monitor$/ ) {
       		$modrdn_operations = ${$entry->get('description')}[0];

        } elsif ( $entry->dn =~ /^cn=Write Waiters,cn=Monitor$/ ) {
                @write_waiters =  split(/=/, ${$entry->get('description')}[0]);

        } elsif ( $entry->dn =~ /^cn=Read Waiters,cn=Monitor$/ ) {
                @read_waiters = split(/=/, ${$entry->get('description')}[0]);
        } 
}

print (LDAPFILE  "$timestamp $total_connections $bytes_sent $initiated_operations $completed_operations $referrals_sent $entries_sent $bind_operations $unbind_operations $add_operations $delete_operations $modify_operations $compare_operations $search_operations $modrdn_operations $write_waiters[1] $read_waiters[1]\n");

close(LDAPFILE);
