143 lines
4.1 KiB
Perl
143 lines
4.1 KiB
Perl
#! /usr/bin/perl
|
|
|
|
#
|
|
# Author: Kevin C. Miller <kevinm@andrew.cmu.edu>
|
|
# http://www.andrew.cmu.edu/~kevinm/dhcp/failover.html
|
|
#
|
|
# The copyright is with the author. We (SuSE) include this script
|
|
# with his permission.
|
|
#
|
|
|
|
# NOTE: you have to edit this script to make it functional for you.
|
|
|
|
## Reset IPs that are stuck in some weird state on the DHCP servers
|
|
## You can run it standalone, and it just reports statistics
|
|
##
|
|
## Or run with option '-reset' to reset many of the problem IPs
|
|
## Or run with option '-primary' to only reset problem IPs on the primary
|
|
##
|
|
## ** Note: You probably want to run -primary if you are in a low-free-IP
|
|
## situation. In this case -reset may enter a race condition and
|
|
## reset valid IPs on the secondary.
|
|
|
|
use strict;
|
|
|
|
my $PRIMARY = "/afs/andrew/usr/kevinm/dhcp1";
|
|
my $PRIMARY_IP = '128.2.4.2';
|
|
my $SEC = "/afs/andrew/usr/kevinm/dhcp3";
|
|
my $SEC_IP = '128.2.32.38';
|
|
|
|
my $RESET = "/afs/andrew/usr/kevinm/bin/clearip";
|
|
my %curstate;
|
|
my %nextstate;
|
|
|
|
my ($TotalPrimary, $TotalSecondary) = (0,0);
|
|
my ($LeasesDiff, $LeasesEq) = (0,0);
|
|
open(FILE, $PRIMARY)
|
|
|| die "Cannot open primary $PRIMARY";
|
|
while(<FILE>) {
|
|
next if ($_ =~ /^\#/);
|
|
my @a = split(/\s+/, $_);
|
|
$curstate{$a[0]} = $a[1];
|
|
$nextstate{$a[0]} = $a[3];
|
|
$TotalPrimary++;
|
|
}
|
|
close(FILE);
|
|
|
|
my @ResetPrimary;
|
|
my @ResetSecondary;
|
|
open(FILE, $SEC)
|
|
|| die "Cannot open secondary $SEC";
|
|
while(<FILE>) {
|
|
next if ($_ =~ /^\#/);
|
|
my @a = split(/\s+/, $_);
|
|
my ($key, $cur, $next) = ($a[0], $a[1], $a[3]);
|
|
$TotalSecondary++;
|
|
if ($curstate{$key} ne $cur &&
|
|
($nextstate{$key} ne $next ||
|
|
$nextstate{$key} eq '' && $next eq '')) {
|
|
## There is some difference
|
|
$LeasesDiff++;
|
|
if ($curstate{$key} eq 'active' &&
|
|
$nextstate{$key} eq 'expired' &&
|
|
$cur eq 'expired' && $next eq 'free') {
|
|
# Reset both
|
|
push(@ResetPrimary, $key);
|
|
push(@ResetSecondary, $key);
|
|
}elsif($curstate{$key} eq 'expired' &&
|
|
$nextstate{$key} eq 'free' &&
|
|
$cur eq 'active' &&
|
|
$next eq 'expired') {
|
|
# Reset both
|
|
push(@ResetPrimary, $key);
|
|
push(@ResetSecondary, $key);
|
|
}elsif( ($curstate{$key} eq 'backup' &&
|
|
$cur eq 'free') ) {
|
|
# Reset both
|
|
push(@ResetPrimary, $key);
|
|
push(@ResetSecondary, $key);
|
|
}elsif($curstate{$key} eq 'expired' &&
|
|
$nextstate{$key} eq 'free' &&
|
|
$cur eq 'free') {
|
|
# Reset both
|
|
push(@ResetPrimary, $key);
|
|
push(@ResetSecondary, $key);
|
|
}elsif(!defined $curstate{$key} &&
|
|
!defined $nextstate{$key}) {
|
|
push(@ResetSecondary, $key);
|
|
}
|
|
|
|
# There are other tests that could be made (primary
|
|
# thinks the lease is 'backup', secondary doesn't know
|
|
# about it).. etc.
|
|
}else{
|
|
# No difference in state
|
|
$LeasesEq++;
|
|
}
|
|
delete $curstate{$key};
|
|
delete $nextstate{$key};
|
|
}
|
|
|
|
# Go through all the IPs on the primary that aren't defined
|
|
# on the secondary at all.
|
|
foreach my $key (keys %curstate) {
|
|
if ($curstate{$key} eq 'backup') {
|
|
push(@ResetPrimary, $key);
|
|
}
|
|
}
|
|
|
|
if ($ARGV[0] eq '-reset') {
|
|
reset_ips($PRIMARY_IP, $SEC_IP, \@ResetPrimary,
|
|
\@ResetSecondary, $RESET);
|
|
}elsif($ARGV[0] eq '-primary') {
|
|
reset_ips($PRIMARY_IP, '', \@ResetPrimary, [], $RESET);
|
|
}
|
|
|
|
# Print statistics
|
|
print "Leases compared. Primary: $TotalPrimary Secondary: $TotalSecondary\n";
|
|
print " Different: $LeasesDiff Equal: $LeasesEq\n";
|
|
print " (Different+Equal may not add up to Primary, due to \n";
|
|
print " missing entries in the leases file.)\n";
|
|
|
|
exit(1);
|
|
|
|
## ***********************************************************************
|
|
# Arguments:
|
|
# - IP Address of primary DHCP server
|
|
# - IP Address of secondary DHCP server
|
|
# - Reference to an array of IPs to reset on the primary
|
|
# - Reference to an array of IPs to reset on the secondary
|
|
# - Reset script
|
|
sub reset_ips {
|
|
my ($PrimaryIP, $SecIP, $rResetPrimary, $rResetSec, $Prog) = @_;
|
|
|
|
foreach my $IP (@$rResetPrimary) {
|
|
print "Resetting $IP on $PrimaryIP\n";
|
|
`$Prog $IP $PrimaryIP`;
|
|
}
|
|
foreach my $IP (@$rResetSec) {
|
|
print "Resetting $IP on $SecIP\n";
|
|
`$Prog $IP $SecIP`;
|
|
}
|
|
}
|