# HG changeset patch # User heiko # Date 1040695556 0 # Node ID f7de068b5beadfbbd56a5b50eb36573afb7205a5 # Parent 96a0d63303c6ca1563895e08e226aa866d4f210b hm... diff -r 96a0d63303c6 -r f7de068b5bea master_watcher --- a/master_watcher Tue Dec 24 00:15:01 2002 +0000 +++ b/master_watcher Tue Dec 24 02:05:56 2002 +0000 @@ -3,7 +3,7 @@ Usage: $ME [options] -l --logfile=s Name of the logfile we've to read [$opt_logfile] -z --zonesdir=s Where the named.conf's are expected [$opt_zonesdir] - -u --[no]update Update the "masters"-entries [$opt_update] + -u --[no]update Update the \"masters\"-entries [$opt_update] -f --[no]follow Follow the end of the logfile [$opt_follow] -d --[no]debug extra debug output [$opt_debug] -h --help This text [$opt_help] @@ -68,10 +68,9 @@ my $opt_debug = 0; my $naptime = 60; -my $inode = 0; -sub updateFile($@); +sub updateFile($$$); sub debug($;@) { syslog(LOG_DEBUG, "DEBUG " . shift @_, @_) if $opt_debug; } MAIN: { @@ -95,9 +94,8 @@ } open (LOGFILE, $_ = "<$opt_logfile") or die "Can't open $_: $!\n"; - $inode = (LOGFILE->stat)[1]; for (;;) { - my (%masters, my %missing); + my (%masters, %missing, %nomasters); while () { my ($domain, $ip); @@ -130,6 +128,7 @@ debug("Missing file for $domain\n"); $missing{$domain} = 1; + next; }; # Wenn wir ein "... loaded" finden, dann fehlt das File nicht gänzlich! @@ -139,15 +138,29 @@ debug("Missing file for $domain is not longer missing\n"); delete $missing{$domain}; + next; + }; + + /\[([\d.]+)\] not authoritative for (\S+), SOA/ and do { + my ($master, $domain) = ($1, $2); + next if exists $nomasters{$domain}->{$master}; + + debug "$master isn't a auth. master for $domain\n"; + $masters{$domain}->{$master} = 1; # sieht blöd aus, wird aber gebraucht, + # weil wir nur die bearbeiten, die einen + # master haben + $nomasters{$domain}->{$master} = 1; + next; }; } # Jetzt sind wir erstmal durch und verarbeiten alles my $changed = 0; foreach my $domain (sort ($opt_update ? keys %masters : keys %missing)) { - $changed += updateFile($domain, keys %{$masters{$domain}}); + $changed += updateFile($domain, [keys %{$masters{$domain}}], [keys %{$nomasters{$domain}}]); delete $masters{$domain}; delete $missing{$domain} if exists $missing{$domain}; + delete $nomasters{$domain} if exists $nomasters{$domain}; } debug "$changed changes."; @@ -163,59 +176,72 @@ } last if !$opt_follow; - debug("Sleeping for $naptime seconds\n"); + syslog LOG_INFO, "Sleeping for $naptime seconds\n"; sleep $naptime; - if ((LOGFILE->stat())[1] != $inode) { + if ((LOGFILE->stat())[1] != (stat($opt_logfile))[1]) { # new file to follow syslog(LOG_NOTICE, "Logfile changed, re-open it.\n"); open(LOGFILE, $_ = "<$opt_logfile") or die "Can't open $_: $!\n"; - $inode = (LOGFILE->stat())[1]; } else { LOGFILE->clearerr(); } } } -sub updateFile($@) +sub updateFile($$$) { local $_; - my $domain = shift; - my %new_masters = map { $_, 1 } @_; - my %old_masters = (); + my $domain = $_[0]; + my @new_masters = @{$_[1]}; + my @no_masters = @{$_[2]}; + + my %masters = (); my $masters; + my $file = "$opt_zonesdir/$domain"; + debug "updateFile: $domain, @new_masters, @no_masters\n"; + if (-f $file) { # Das File ist also schon da, wir müssen nur mal gucken, ob die Master, # von denen wir ein NOTIFY erhalten haben, auch in unserer Datei stehen. - # Vorerst entfernen wir keinen Master, wir fügen lediglich welche hinzu, - # wenn Sie noch nicht dabei sind. # open (F, $_ = "+<$file") or die "Can't open $_: $!\n"; flock(F, LOCK_EX); seek(F, 0, 0); $_ = join "", ; - # Liste der Master raussuchen + # Liste der Master raussuchen, darus noch die löschen, die uns + # die Mitarbeit verweigert haben.. /^(\s*masters\s*{\s*)(.*?);(\s*}\s*;)(\s*\/\/.*?\n)/ims; - %old_masters = map { $_, 1 } split/\s*;\s*/, $2; + %masters = map { $_, 1 } split/\s*;\s*/, $2; + $masters = %masters; # für den späteren Vergleich - # Aus den neuen löschen wir die, die bereits bekannt sind - delete @new_masters{keys %old_masters}; + # noch unsere neuen hinzufügen... + @masters{@new_masters} = map { 1 } @new_masters; - # Wenn nun noch welche übring sind, dann müssen wir diese - # mit eintragen. Ansonsten haben wir fertig. - if (not %new_masters) { - debug("Uptodate file for $domain\n"); + # nun die weg, die sich nicht zuständig fühlen + delete @masters{@no_masters}; + + # Wenn sich nach alldem nichts verändert hat, haben wir fertig. + if ($masters eq %masters) { + debug("File is up-to-date for $domain\n"); syslog(LOG_NOTICE, "No changes made for $domain (no \"loaded\" seen, defective master?)\n") unless $opt_update; close(F); return 0; } - syslog(LOG_NOTICE, "Updated masters list for $domain\n"); - $masters = join ";", keys %old_masters, keys %new_masters; + if (not %masters) { + syslog LOG_NOTICE, "REMOVING $file (empty masters list)\n"; + close F; + unlink $file; + return 1; + } + + $masters = join ";", keys %masters; + syslog(LOG_NOTICE, "Updated masters ($masters) list for $domain\n"); s/^(\s*masters\s*{\s*)(.*?);(\s*}\s*;)/$1$masters;$3/ims; truncate(F, 0); @@ -228,7 +254,15 @@ my $date = localtime(); - $masters = join "; ", keys %new_masters; + my %new_masters = map { $_, 1 } @new_masters; + delete @new_masters{@no_masters}; + + if (not %new_masters) { + syslog LOG_INFO, "not creating $file (empty masters list)\n"; + return 0; + } + + $masters = join "; ", @new_masters; -d $opt_zonesdir or mkpath($opt_zonesdir, 0, 0755);