#!/usr/bin/perl -w ############################################################################## # $Id$ ############################################################################## # This script performs what F5 calls Extended Content Verification (ECV). # It checks that each of the servers we load balance LDAP requests to is # responding with valid data. Any servers which aren't providing valid # data are removed from the load balancing pool. ############################################################################## use IPC::Open3; my $BALANCE = '/usr/local/bin/balance'; my %TYPES = ( 389 => 'ldap', 636 => 'ldaps', ); my $BINDHOST = 'ldap.example.com'; # Hostname or IP balance is bound to my $TESTUSER = 'temp1'; # User to lookup in LDAP sub usage { die "Usage: $0 389|636\n"; } my $port; if (scalar(@ARGV) == 1 && $ARGV[0]) { $port = $ARGV[0]; if (! exists $TYPES{$port}) { usage(); } } else { usage(); } my $type = $TYPES{$port}; my @failed_channels; open(B, "$BALANCE -b $BINDHOST -c 'show' $port |") || die; while() { next if (/^GRP/); # Header line, skip it next if (/^$/); # Skip blank lines my ($group, undef, $channel, $status, $ip, $chanport) = split; # Groups and channels can be 0 (zero) so we just make sure they # are defined. if ( !defined($group) || !defined($channel) || !$status || !$ip || !$chanport) { warn "Bad line: $_"; next; } # Don't check channels outside of group zero. It's not clear # how to disable them from the command line because specifying # the current working group is a seperate command and there # doesn't seem to be a way to chain commands. next if ($group != 0); my $pid = open3(\*CMDIN, \*CMDOUT, \*CMDERR, 'ldapsearch', '-x', '-H', "$type://$ip:$chanport/", "uid=$TESTUSER"); die "Fork failed: $!" if (! $pid); close(CMDIN); close(CMDERR); my $good = 0; while() { if (/^uid: $TESTUSER/) { $good = 1; } } close(CMDOUT); waitpid($pid, 0); if ($good && $status eq 'dis') { warn "Channel $channel with IP $ip has recovered, enabling\n"; system("$BALANCE -b $BINDHOST -c 'enable $channel' $port"); } elsif (! $good && $status eq 'ENA') { warn "Channel $channel with IP $ip has failed, disabling\n"; system("$BALANCE -b $BINDHOST -c 'disable $channel' $port"); } } close(B);