-
-
Save jeviolle/e749f31e8d6dbe0f8808 to your computer and use it in GitHub Desktop.
openldap monitoring script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# Buchan Milne <[email protected]> 20051213 | |
# Script to monitor OpenLDAP performance and sync-replication status via | |
# Hobbit (may also still work with BigBrother). | |
# | |
# 1)Install Net::LDAP (perl-ldap) and Date::Manip (perl-DateManip) | |
# 2)Run as task from hobbitserver.cfg (or BBEXT in bbdef.sh for BigBrother) | |
# 3)Use ncv in hobbit to collect data: | |
# -add "ol=ncv" to TEST2RRD, and "ncv" to GRAPHS in hobbitserver.cfg | |
# -add NCV_ol="ReadWaiters:GAUGE,WriteWaiters:GAUGE,CurrentConnections:GAUGE" | |
# to hobbitserver.cfg | |
# 4)Add something like the contents of hobbitgraph-ol.cfg to hobbitgraph.cfg | |
# 5)Ensure monitor backend in OpenLDAP 2.1 or later is configured for | |
# anonymous access from the display server | |
# 6)Add "ol" to hosts in bb-hosts to monitor with this script | |
use strict; | |
use Net::LDAP; | |
use Date::Manip; | |
my ($slave,$bbhost,$ldap_message,$ldap_entry,$monitor,$tmp,$content,$status,$base); | |
my (@slaves,@values); | |
my %ldap; | |
my (%ldap_perf,%performance,%master); | |
my $service = "ol"; | |
my @slave_states = ("in sync", "not a sync-repl slave", "could not check master", "out of sync"); | |
my @state_colours = ("OK", "NONE", "NONE", "WARN","ERR"); | |
my @state_names = ("green", "clear", "clear", "yellow","red"); | |
if ( $ENV{'BBHOME'} ) { | |
# Use bbhostgrep if available (hobbit), otherwise use a hardcoded list | |
# of servers: | |
if ( -f "$ENV{'BBHOME'}/bin/bbhostgrep" ) { | |
print "DEBUG Found bbhostgrep\n" if $ENV{DEBUG}; | |
open (BBHOSTGREP, $ENV{BBHOME} . "/bin/bbhostgrep " . $service . " |") or die $*; | |
while (<BBHOSTGREP>) { | |
my ($junk,$host); | |
($junk,$host) = split ' '; | |
print "DEBUG Adding $host to server list\n" if $ENV{DEBUG}; | |
push @slaves, $host; | |
} | |
close BBHOSTGREP; | |
} else { | |
print "DEBUG Couldn't find bbhostgrep\n" if $ENV{DEBUG}; | |
#@slaves = ('master.domain.com', 'ldap1.domain.com', 'ldap2.domain.com'); | |
@slaves = ('localhost'); | |
} | |
@state_colours = ("&green", "&clear", "&clear", "&yellow","&red"); | |
} else { | |
@slaves = @ARGV; | |
} | |
foreach $slave (@slaves) { | |
%master = (); | |
$status = 0; | |
$content = ""; | |
print "DEBUG Using $slave\n" if $ENV{DEBUG}; | |
$bbhost = $slave; | |
$bbhost =~ s/\./\,/g; | |
if ($ldap{$slave} ne undef or $ldap{$slave} = Net::LDAP->new( $slave, async=> 1 ) ) { | |
print "DEBUG Binding to $slave\n" if $ENV{DEBUG}; | |
$ldap_message = $ldap{$slave}->bind; | |
# Get monitor context | |
$ldap_message = $ldap{$slave}->search( | |
base => '', | |
scope => 'base', | |
filter => '(objectclass=*)', | |
attrs => ['monitorContext'] | |
); | |
$ldap_message->code && die $ldap_message->error; | |
$ldap_entry = $ldap_message->entry(0); | |
$monitor = $ldap_entry->get_value('monitorContext'); | |
#$ldap_message = $ldap->root_dse(); | |
#$ldap_message->code && die $ldap_message->error; | |
#$monitor = $ldap_message->get_value('monitorContext'); | |
print "DEBUG Monitor context for $slave: $monitor\n" if $ENV{DEBUG}; | |
%performance = &get_perf($slave,$monitor,$ldap{$slave}); | |
$content = "\n"; | |
foreach ( sort keys %performance ) { | |
$content .= sprintf "%s : %s\n",$_,$performance{$_}; | |
} | |
# Get databases that have a master | |
$ldap_message = $ldap{$slave}->search( | |
base => $monitor, | |
scope => 'sub', | |
filter => '(&(namingContexts=*)(MonitorUpdateRef=*))', | |
attrs => [ 'monitorupdateref', 'namingContexts' ] | |
); | |
if ( $ldap_message->count == 0 ) { | |
$content .= "$state_colours[0] Not a syncrepl slave\n"; | |
} else { | |
$content .= "Replication status of slave databases\n"; | |
} | |
for $ldap_entry ( $ldap_message->all_entries ) { | |
$master{$ldap_entry->get_value('namingContexts')} = $ldap_entry->get_value('monitorupdateref'); | |
} | |
for ( keys ( %master )) { | |
my ($slave_status,$msg) = &check_slave($slave,$master{$_},$_,\%ldap); | |
$content .= sprintf("%s %s %s %s\n", $state_colours[$slave_status],$_,$slave_states[$slave_status],$msg); | |
$status = ($status lt $slave_status) ? $slave_status : $status; | |
} | |
} else { | |
$status = 4; | |
$content = "$@\n"; | |
} | |
if ( $ENV{BBHOME} eq "" ) { | |
print $state_colours[$status] . " $slave " . `date`; | |
print $content; | |
} else { | |
my $line = "status " . $bbhost . "." . $service . " " . $state_names[$status] . " " . `date` . "\n"; | |
$line .= $content; | |
if ( $ENV{BB} ) { | |
system ("$ENV{BB}", "$ENV{BBDISP}", "$line"); | |
} else { | |
print "$line"; | |
} | |
} | |
} | |
# clean up ldap connections | |
foreach (keys %ldap) { | |
next if not defined ($ldap{$_}); | |
print "DEBUG Unbinding from $_\n" if $ENV{DEBUG}; | |
$ldap{$_}->unbind; | |
} | |
sub get_contextcsn { | |
my ($c_ldapserver,$c_base,$c_ldap) = @_; | |
my $c_message; | |
my $c_entry; | |
my $bound = 'TRUE'; | |
$c_message = $c_ldap->search( | |
base => $c_base, | |
scope => 'base', | |
filter => '(objectclass=*)', | |
attrs => ['contextCSN'] | |
); | |
$c_message->code && return $c_message->error; | |
$c_entry = $c_message->entry(0); | |
return $c_entry->get_value('contextCSN'); | |
} | |
sub get_perf { | |
my ($ldapserver,$base,$ldapconn) = @_; | |
my ($message,$entry,$dn,$value,$monitortype,$monitorfilter,$firstattrib); | |
my $bound =' TRUE'; | |
my %perf; | |
my @monitorattribs; | |
if ( $ldapconn == undef ) { | |
$bound = 'FALSE'; | |
printf "DEBUG Binding to $ldapserver\n" if $ENV{DEBUG}; | |
$ldapconn = Net::LDAP->new( $ldapserver, async => 1) or die "$@" unless defined ( $ldapconn); | |
$message = $ldapconn->bind; | |
} | |
# search on monitorcontext for structuralobjectclass | |
# OL 2.1 = structuralObjectClass: monitor | |
# OL 2.2 and later = structuralObjectClass: monitorServer | |
$message = $ldapconn->search( | |
base => $base, | |
filter => '(objectclass=*)', | |
scope => 'base', | |
attrs => ['structuralObjectClass'] | |
); | |
$message->code && die $message->error; | |
$monitortype = $message->entry(0)->get_value('structuralObjectClass'); | |
print "DEBUG monitor is " . $monitortype . "\n" if $ENV{DEBUG}; | |
if ( $monitortype eq "monitorServer" ) { | |
$monitorfilter = '(& | |
(| | |
(objectclass=monitorCounterObject) | |
(objectclass=monitorOperation) | |
(objectclass=monitorContainer) | |
) | |
(| | |
(monitorcounter=*) | |
(monitorOpInitiated=*) | |
) | |
)'; | |
@monitorattribs = ['monitorCounter', 'monitorOpInitiated', 'monitorOpCompleted', 'dn']; | |
$firstattrib = 'monitorCounter'; | |
} elsif ( $monitortype eq 'monitor' ) { | |
$monitorfilter = '(objectclass=monitor)'; | |
@monitorattribs = ['description', 'dn']; | |
$firstattrib = 'description'; | |
} | |
# counters: | |
print "DEBUG Searching under $base with filter $monitorfilter on $ldapserver\n" if $ENV{DEBUG}; | |
$message = $ldapconn->search( | |
base => $base, | |
scope => 'sub', | |
filter => $monitorfilter, | |
attrs => @monitorattribs | |
); | |
$message->code && die $message->error; | |
foreach $entry ( $message->all_entries ) { | |
$dn = $entry->dn; | |
next if ($dn =~ m/(cn=(Connections|Backends|Databases|Listeners|Time|TLS|SASL|Log)|(^cn=Monitor))/); | |
print "DEBUG got $dn\n" if $ENV{DEBUG}; | |
$dn =~ s/,$base$//; | |
$dn =~ s/cn=//g; | |
$dn =~ s/\,/ /g; | |
$dn =~ s/ Operations//g; | |
$dn =~ s/Operations/Operation/g; | |
$dn =~ s/Statistics//g; | |
print "DEBUG getting $firstattrib for $dn\n" if $ENV{DEBUG}; | |
$value = $entry->get_value($firstattrib); | |
if ( $value eq "" ) { | |
$value = $dn . " Initiated"; | |
$perf{$value} = $entry->get_value('monitorOpInitiated'); | |
$value = $dn . " Completed"; | |
$perf{$value} = $entry->get_value('monitorOpCompleted'); | |
} else { | |
$perf{$dn} = $value; | |
} | |
print "DEBUG $dn:\t $value, $perf{$dn}\n" if $ENV{DEBUG}; | |
} | |
print "DEBUG Finished search results\n" if $ENV{DEBUG}; | |
return %perf; | |
} | |
sub check_slave { | |
my ($slave,$master,$db,$ldap) = @_; | |
if ($ldap{$master{$_}} eq undef) { | |
print "DEBUG Binding to master $master{$_}\n" if $ENV{DEBUG}; | |
$ldap{$master{$_}} = Net::LDAP->new( $master{$_}, async=> 1) or return (2,""); | |
$ldap{$master{$_}}->bind or return (2,""); | |
} | |
my ($mastercsn,$slavecsn); | |
print "DEBUG Checking $master for $db\n" if $ENV{DEBUG}; | |
$slavecsn = &get_contextcsn($slave,$db,$$ldap{$slave}) or return (1,""); | |
$mastercsn = &get_contextcsn($master,$db,$$ldap{$master}) or return (2,""); | |
if ($slavecsn == $mastercsn){ | |
return (0,""); | |
} else { | |
my $slavetime = $slavecsn; | |
my $mastertime = $mastercsn; | |
my $time; | |
$slavetime =~ s/#.*//g; | |
$mastertime =~ s/#.*//g; | |
$time = DateCalc($mastertime,$slavetime); | |
$time =~ s/^(.)0:0:/$1/; | |
$time =~ s/^\+(.*)$/$1 ahead/g; | |
$time =~ s/^\-(.*)$/$1 behind/g; | |
foreach ("weeks","days") { $time =~s/:/ $_ /;} | |
$time =~ s/:/-/g; | |
return (3,$time); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment