Changeset 365 for branches


Ignore:
Timestamp:
10/09/07 13:06:45 (17 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Add new sub to IPDB.pm: addMaster()
Sub is more complex than original stub in main.cgi; allows adding a
master that is a superset of an existing master
Minor bugfix on removing a master; make sure to delete all relevant freeblocks

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/cgi-bin/IPDB.pm

    r362 r365  
    1616use DBI;
    1717use Net::SMTP;
     18use NetAddr::IP qw( Compact );
    1819use POSIX;
    1920use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
     
    2425        %disp_alloctypes %list_alloctypes %def_custids @citylist @poplist @masterblocks
    2526        %allocated %free %routed %bigfree %IPDBacl
    26         &initIPDBGlobals &connectDB &finish &checkDBSanity &allocateBlock &deleteBlock
    27         &getBlockData &mailNotify
     27        &initIPDBGlobals &connectDB &finish &checkDBSanity &allocateBlock &addMaster
     28        &deleteBlock &getBlockData &mailNotify
    2829        );
    2930
     
    3334                @masterblocks %allocated %free %routed %bigfree %IPDBacl
    3435                &initIPDBGlobals &connectDB &finish &checkDBSanity &allocateBlock
    35                 &deleteBlock &getBlockData &mailNotify
     36                &addMaster &deleteBlock &getBlockData &mailNotify
    3637                )]
    3738        );
     
    179180#  $dbh->disconnect;
    180181} # end checkDBSanity
     182
     183
     184## IPDB::addMaster()
     185# Does all the magic necessary to sucessfully add a master block
     186# Requires database handle, block to add
     187# Returns failure code and error message or success code and "message"
     188sub addMaster {
     189  my $dbh = shift;
     190  my $cidr = new NetAddr::IP shift;
     191
     192  # Allow transactions, and raise an exception on errors so we can catch it later.
     193  # Use local to make sure these get "reset" properly on exiting this block
     194  local $dbh->{AutoCommit} = 0;
     195  local $dbh->{RaiseError} = 1;
     196
     197  # Wrap all the SQL in a transaction
     198  eval {
     199    my $sth = $dbh->prepare("select count(*) from masterblocks where cidr <<= '$cidr'");
     200    $sth->execute;
     201    my @data = $sth->fetchrow_array;
     202
     203    if ($data[0] eq 0) {
     204      # First case - master is brand-spanking-new.
     205##fixme: rwhois should be globally-flagable somewhere, much like a number of other things
     206## maybe a db table called "config"?
     207      $sth = $dbh->prepare("insert into masterblocks (cidr,rwhois) values ('$cidr','y')");
     208      $sth->execute;
     209
     210# Unrouted blocks aren't associated with a city (yet).  We don't rely on this
     211# elsewhere though;  legacy data may have traps and pitfalls in it to break this.
     212# Thus the "routed" flag.
     213
     214      $sth = $dbh->prepare("insert into freeblocks (cidr,maskbits,city,routed)".
     215        " values ('$cidr',".$cidr->masklen.",'<NULL>','n')");
     216      $sth->execute;
     217
     218      # If we get here, everything is happy.  Commit changes.
     219      $dbh->commit;
     220
     221    } # new master does not contain existing master(s)
     222    else {
     223
     224      # collect the master(s) we're going to absorb, and snag the longest netmask while we're at it.
     225      my $smallmask = $cidr->masklen;
     226      $sth = $dbh->prepare("select cidr as mask from masterblocks where cidr <<= '$cidr'");
     227      $sth->execute;
     228      my @cmasters;
     229      while (my @data = $sth->fetchrow_array) {
     230        my $master = new NetAddr::IP $data[0];
     231        push @cmasters, $master;
     232        $smallmask = $master->masklen if $master->masklen > $smallmask;
     233      }
     234
     235      # split the new master, and keep only those blocks not part of an existing master
     236      my @blocklist;
     237      foreach my $seg ($cidr->split($smallmask)) {
     238        my $contained = 0;
     239        foreach my $master (@cmasters) {
     240          $contained = 1 if $master->contains($seg);
     241        }
     242        push @blocklist, $seg if !$contained;
     243      }
     244
     245      # collect the unrouted free blocks within the new master
     246      $sth = $dbh->prepare("select cidr from freeblocks where ".
     247                "maskbits>=$smallmask and cidr <<= '$cidr' and routed='n'");
     248      $sth->execute;
     249      while (my @data = $sth->fetchrow_array) {
     250        my $freeblock = new NetAddr::IP $data[0];
     251        push @blocklist, $freeblock;
     252      }
     253
     254      # combine the set of free blocks we should have now.
     255      @blocklist = Compact(@blocklist);
     256
     257      # and now insert the new data.  Make sure to delete old masters too.
     258
     259      # freeblocks
     260      $sth = $dbh->prepare("delete from freeblocks where cidr <<= ?");
     261      my $sth2 = $dbh->prepare("insert into freeblocks (cidr,maskbits,city,routed) values (?,?,'<NULL>','n')");
     262      foreach my $newblock (@blocklist) {
     263        $sth->execute("$newblock");
     264        $sth2->execute("$newblock", $newblock->masklen);
     265      }
     266
     267      # master
     268      $sth = $dbh->prepare("delete from masterblocks where cidr <<= '$cidr'");
     269      $sth->execute;
     270      $sth = $dbh->prepare("insert into masterblocks (cidr,rwhois) values ('$cidr','y')");
     271      $sth->execute;
     272
     273      # *whew*  If we got here, we likely suceeded.
     274      $dbh->commit;
     275    } # new master contained existing master(s)
     276  }; # end eval
     277
     278  if ($@) {
     279    my $msg = $@;
     280    eval { $dbh->rollback; };
     281    return ('FAIL',$msg);
     282  } else {
     283    return ('OK','OK');
     284  }
     285} # end addMaster
    181286
    182287
     
    511616      $sth = $dbh->prepare("delete from masterblocks where cidr='$cidr'");
    512617      $sth->execute;
    513       $sth = $dbh->prepare("delete from freeblocks where cidr='$cidr'");
     618      $sth = $dbh->prepare("delete from freeblocks where cidr <<= '$cidr'");
    514619      $sth->execute;
    515620      $dbh->commit;
Note: See TracChangeset for help on using the changeset viewer.