hm...
authorheiko
Tue, 24 Dec 2002 02:05:56 +0000
changeset 6 f7de068b5bea
parent 5 96a0d63303c6
child 7 836e273e9992
hm...
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 (<LOGFILE>) {
 	    
 	    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 "", <F>;
 
-	# 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);