Changeset 872 for trunk/DNSDB


Ignore:
Timestamp:
09/29/22 13:00:28 (2 years ago)
Author:
Kris Deugau
Message:

/trunk

BIND export, unwinding dev saves, 24 of many many

  • Add domain export loop, with most of the first-pass changes
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/DNSDB/ExportBIND.pm

    r871 r872  
    195195
    196196  } # revsth->fetch
     197
     198
     199
     200## and now the domains
     201
     202  $soasth = $dnsdb->{dbh}->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".
     203        "FROM records WHERE domain_id=? AND type=6");
     204  $recsth = $dnsdb->{dbh}->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location,extract(epoch from stamp),expires,stampactive ".
     205        "FROM records WHERE domain_id=? AND NOT type=6");
     206#      "FROM records WHERE domain_id=? AND type < 65280");     # Just exclude all types relating to rDNS
     207
     208  # Fetch active zone list
     209  my $domsth = $dnsdb->{dbh}->prepare("SELECT domain_id,domain,status,changed FROM domains WHERE status=1 ORDER BY domain_id");
     210  # Unflag changed zones, so we can maybe cache the export and not redo everything every time
     211  $zonesth = $dnsdb->{dbh}->prepare("UPDATE domains SET changed='n' WHERE domain_id=?");
     212  $domsth->execute();
     213
     214  while (my ($domid,$dom,$domstat,$changed) = $domsth->fetchrow_array) {
     215
     216    # fetch a list of views/locations present in the zone.  we need to publish a file for each one.
     217    # in the event that no locations are present (~~ $viewlist is empty), /%view collapses to nothing in the zone path
     218    my $tmplocs = $dnsdb->{dbh}->selectall_arrayref("SELECT DISTINCT location FROM records WHERE domain_id = ?", undef, $domid);
     219    my @loclist;
     220    foreach my $tloc (@{$tmplocs}) {
     221      push @loclist, ($tloc->[0] eq '' ? 'common' : $tloc->[0]);
     222    }
     223    my %zonefiles;  # zone file handles
     224
     225    eval {
     226
     227##fixme:  use tmpfile module for more secure temp files?  want the zone name at least in it anyway, not sure that works...
     228      my $zfile = $dom;  # can probably drop this intermediate
     229      my $tmpcache = "tmp.$zfile.$$";   # safety net.  don't overwrite a previous known-good file
     230      foreach my $loc (@loclist) {
     231        my $zfilepath = $dnsdb->{bind_export_zone_path};
     232        $zfilepath =~ s/\%view/$loc/;
     233        $zfilepath =~ s/\%zone/$zfile/;
     234#        $zfilepath =~ s/\%arpazone/$arpazone/;
     235
     236        # Just In Case(TM)
     237        $zfilepath =~ s,[^\w./-],_,g;
     238
     239#      open $zonefiles{$loc}, ">", $zfilepath;
     240print "open zonefile for '$loc', '$zfilepath'\n";
     241
     242
     243        # write fresh records if:
     244        #  - the zone contains ALIAS pseudorecords, which need to cascade changes from the upstream CNAME farm at every opportunity
     245        if ( ($dnsdb->{dbh}->selectrow_array("SELECT count(*) FROM records WHERE domain_id = ? AND type=65300", undef, $domid))[0] ) {
     246          $changed = 1;  # abuse this flag for zones with ALIAS records
     247          # also update the serial number, because while it shouldn't matter purely for serving
     248          # records, it WILL matter if AXFR becomes part of the publishing infrastructure
     249          $dnsdb->_updateserial(domain_id => $domid);
     250        }
     251        #  - the zone contains records which expire in less than 10 minutes or became valid less than 10 minutes ago
     252        # note, no need to multi-bump the serial
     253        elsif ( ($dnsdb->{dbh}->selectrow_array("SELECT COUNT(*) FROM records WHERE domain_id = ? AND ".
     254                "stampactive='t' AND @(extract(epoch from stamp-now())) < 600", undef, $domid))[0] ) {
     255          $changed = 1;
     256          $dnsdb->_updateserial(domain_id => $domid);
     257        }
     258#        if (!$self->{usecache} || $self->{force_refresh} || $changed || !-e $cachefile || -z $cachefile) {
     259        if ($dnsdb->{force_refresh} || $changed || !-e $zfilepath || -z $zfilepath) {
     260          open $zonefiles{$loc}, ">", $zfilepath or die "Error creating temporary file $zfilepath: $!\n";
     261
     262#          if ($self->{usecache}) {
     263#            open ZONECACHE, ">$tmpcache" or die "Error creating temporary file $tmpcache: $!\n";
     264#            $zonefilehandle = *ZONECACHE;
     265#          }
     266
     267          # need to fetch this separately so the SOA comes first in the flatfile....
     268          # Just In Case we need/want to reimport from the flatfile later on.
     269          $soasth->execute($domid);
     270          my (@zsoa) = $soasth->fetchrow_array();
     271
     272          # drop in a header line so we know when things went KABOOM
     273          printf {$zonefiles{$loc}} "; %s in view %s exported %s\n", $arpazone, $loc, scalar(localtime)
     274                or die "Error writing header [$cidr, '$loc']: $!\n";
     275
     276          printrec_bind(\%zonefiles, \@loclist, $zsoa[7], 'n', \%recflags, $dom,
     277            $zsoa[0], $zsoa[1], $zsoa[2], $zsoa[3], $zsoa[4], $zsoa[5], $zsoa[6], $loc, '');
     278
     279#          $self->_printrec_tiny($zonefilehandle, $zsoa[7], 'n',\%recflags,$dom,
     280#            $zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],$zsoa[8],'');
     281
     282        # tag the zonefile for publication in the view
     283        push @{$viewzones{$loc}}, $arpazone;
     284      } # foreach @loclist
     285
     286      $recsth->execute($domid);
     287      while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc,$stamp,$expires,$stampactive) = $recsth->fetchrow_array) {
     288        next if $recflags{$recid};
     289
     290        # Check for out-of-zone data
     291        $host = $dom if $host eq '@';
     292        if ($host !~ /$dom$/i) {
     293          warn "Not exporting out-of-zone record $host $type $val, $ttl (zone $dom)\n";
     294          next;
     295        }
     296
     297        # Spaces are evil.
     298        $host =~ s/^\s+//;
     299        $host =~ s/\s+$//;
     300        if ($typemap{$type} ne 'TXT') {
     301          # Leading or trailng spaces could be legit in TXT records.
     302          $val =~ s/^\s+//;
     303          $val =~ s/\s+$//;
     304        }
     305        $recflags{$recid} = 1;
     306
     307        printrec_bind(\%zonefiles, \@loclist, $recid, 'n', \%recflags, $dom,
     308          $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp, $expires, $stampactive);
     309
     310      } # while ($recsth)
     311
     312
     313#        if ($self->{usecache}) {
     314#          close ZONECACHE; # force the file to be written
     315#          # catch obvious write errors that leave an empty temp file
     316#          if (-s $tmpcache) {
     317#            rename $tmpcache, $cachefile
     318#              or die "Error overwriting cache file $cachefile with temporary file: $!\n";
     319#          }
     320#        }
     321
     322      } # if $changed or cache filesize is 0
     323
     324    };
     325    if ($@) {
     326      die "error writing ".($dnsdb->{usecache} ? 'new data for ' : '')."$revzone: $@\n";
     327      # error!  something borked, and we should be able to fall back on the old cache file
     328      # report the error, somehow.
     329    } else {
     330      # mark zone as unmodified.  Only do this if no errors, that way
     331      # export failures should recover a little more automatically.
     332      $zonesth->execute($revid);
     333    }
     334
     335#    if ($dnsdb->{usecache}) {
     336#      # We've already made as sure as we can that a cached zone file is "good",
     337#      # although possibly stale/obsolete due to errors creating a new one.
     338#      eval {
     339#        open CACHE, "<$cachefile" or die $!;
     340#        print $datafile $_ or die "error copying cached $revzone to master file: $!" while <CACHE>;
     341#        close CACHE;
     342#      };
     343#      die $@ if $@;
     344#    }
     345
     346  } # domsth->fetch
    197347
    198348
Note: See TracChangeset for help on using the changeset viewer.