SHA256
1
0
forked from pool/dhcp
dhcp/reset-ip

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`;
}
}