Changeset 93


Ignore:
Timestamp:
12/01/04 15:29:09 (19 years ago)
Author:
Kris Deugau
Message:

/trunk

Add deleteBlock() sub

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/cgi-bin/IPDB.pm

    r80 r93  
    2222@ISA            = qw(Exporter);
    2323@EXPORT_OK      = qw(&initIPDBGlocals &connectDB &finish &checkDBSanity &allocateBlock
    24                         &mailNotify);
     24                        &deleteBlock &mailNotify);
    2525
    2626@EXPORT         = (); # Export nothing by default.
    2727%EXPORT_TAGS    = ( ALL => [qw( &initIPDBGlocals &connectDB &finish &checkDBSanity
    28                                 &allocateBlock &mailNotify)]
     28                                &allocateBlock &deleteBlock &mailNotify)]
    2929                  );
    3030
     
    337337
    338338
     339## IPDB::deleteBlock()
     340# Removes an allocation from the database, including deleting IPs
     341# from poolips and recombining entries in freeblocks if possible
     342# Also handles "deleting" a static IP allocation, and removal of a master
     343# Requires a database handle, the block to delete, and the type of block
     344sub deleteBlock {
     345  my ($dbh,undef,$type) = @_;
     346  my $cidr = new NetAddr::IP $_[1];
     347
     348  my $sth;
     349
     350  # To contain the error message, if any.
     351  my $msg = "Unknown error deallocating $type $cidr";
     352  # Enable transactions and exception-on-errors... but only for this sub
     353  local $dbh->{AutoCommit} = 0;
     354  local $dbh->{RaiseError} = 1;
     355
     356  # First case.  The "block" is a static IP
     357  # Note that we still need some additional code in the odd case
     358  # of a netblock-aligned contiguous group of static IPs
     359  if ($type =~ /^.i$/) {
     360
     361    eval {
     362      $msg = "Unable to deallocate $type $cidr";
     363      $sth = $dbh->prepare("update poolips set custid='6750400',available='y',".
     364        "city=(select city from allocations ".
     365        "where cidr=(select pool from poolips where ip='$cidr')),".
     366        "description='',notes='',circuitid='' where ip='$cidr'");
     367      $sth->execute;
     368      $dbh->commit;
     369    };
     370    if ($@) {
     371      eval { $dbh->rollback; };
     372      return ('FAIL',$msg);
     373    } else {
     374      return ('OK',"OK");
     375    }
     376
     377  } elsif ($type eq 'mm') { # end alloctype =~ /.i/
     378
     379    $msg = "Unable to delete master block $cidr";
     380    eval {
     381      $sth = $dbh->prepare("delete from masterblocks where cidr='$cidr'");
     382      $sth->execute;
     383      $sth = $dbh->prepare("delete from freeblocks where cidr='$cidr'");
     384      $sth->execute;
     385      $dbh->commit;
     386    };
     387    if ($@) {
     388      eval { $dbh->rollback; };
     389      return ('FAIL', $msg);
     390    } else {
     391      return ('OK',"OK");
     392    }
     393
     394  } else { # end alloctype master block case
     395
     396    ## This is a big block; but it HAS to be done in a chunk.  Any removal
     397    ## of a netblock allocation may result in a larger chunk of free
     398    ## contiguous IP space - which may in turn be combined into a single
     399    ## netblock rather than a number of smaller netblocks.
     400
     401    eval {
     402
     403      if ($type eq 'rr') {
     404        $msg = "Unable to remove routing allocation $cidr";
     405        $sth = $dbh->prepare("delete from routed where cidr='$cidr'");
     406        $sth->execute;
     407        # Make sure block getting deleted is properly accounted for.
     408        $sth = $dbh->prepare("update freeblocks set routed='n',city='<NULL>'".
     409                " where cidr='$cidr'");
     410        $sth->execute;
     411        # Set up query to start compacting free blocks.
     412        $sth = $dbh->prepare("select * from freeblocks where ".
     413                "maskbits<=".$cidr->masklen." and routed='n' order by maskbits desc");
     414
     415      } else { # end alloctype routing case
     416
     417        $sth = $dbh->prepare("delete from allocations where cidr='$cidr'");
     418        $sth->execute;
     419        # Special case - delete pool IPs
     420        if ($type =~ /^.p$/) {
     421          # We have to delete the IPs from the pool listing.
     422          $sth = $dbh->prepare("delete from poolips where pool='$cidr'");
     423          $sth->execute;
     424        }
     425
     426        # Set up query for compacting free blocks.
     427        $sth = $dbh->prepare("select * from freeblocks where cidr << ".
     428                "(select cidr from routed where cidr >> '$cidr') ".
     429                " and maskbits<=".$cidr->masklen." and routed='y' order by maskbits desc");
     430
     431      } # end alloctype general case
     432
     433      # Now we look for larger-or-equal-sized free blocks in the same master (routed)
     434      # (super)block. If there aren't any, we can't combine blocks anyway.  If there
     435      # are, we check to see if we can combine blocks.
     436      # Execute the statement prepared in the if-else above.
     437
     438      $sth->execute;
     439
     440# NetAddr::IP->compact() attempts to produce the smallest inclusive block
     441# from the caller and the passed terms.
     442# EG:  if you call $cidr->compact($ip1,$ip2,$ip3) when $cidr, $ip1, $ip2,
     443#       and $ip3 are consecutive /27's starting on .0 (.0-.31, .32-.63,
     444#       .64-.95, and .96-.128), you will get an array containing a single
     445#       /25 as element 0 (.0-.127).  Order is not important;  you could have
     446#       $cidr=.32/27, $ip1=.96/27, $ip2=.0/27, and $ip3=.64/27.
     447
     448      my (@together, @combinelist);
     449      my $i=0;
     450      while (my @data = $sth->fetchrow_array) {
     451        my $testIP = new NetAddr::IP $data[0];
     452        @together = $testIP->compact($cidr);
     453        my $num = @together;
     454        if ($num == 1) {
     455          $cidr = $together[0];
     456          $combinelist[$i++] = $testIP;
     457        }
     458      }
     459
     460      # Clear old freeblocks entries - if any.  $i==0 if not.
     461      if ($i>0) {
     462        $sth = $dbh->prepare("delete from freeblocks where cidr=?");
     463        foreach my $block (@combinelist) {
     464          $sth->execute("$block");
     465        }
     466      }
     467
     468      # insert "new" freeblocks entry
     469      if ($type eq 'rr') {
     470        $sth = $dbh->prepare("insert into freeblocks values ('$cidr',".$cidr->masklen.
     471                ",'<NULL>','n')");
     472      } else {
     473        $sth = $dbh->prepare("insert into freeblocks values ('$cidr',".$cidr->masklen.
     474                ",(select city from routed where cidr >>= '$cidr'),'y')");
     475      }
     476      $sth->execute;
     477
     478      # If we got here, we've succeeded.  Whew!
     479      $dbh->commit;
     480    }; # end eval
     481    if ($@) {
     482      eval { $dbh->rollback; };
     483      return ('FAIL', $msg);
     484    } else {
     485      return ('OK',"OK");
     486    }
     487
     488  } # end alloctype != netblock
     489
     490} # end deleteBlock()
     491
     492
    339493## IPDB::mailNotify()
    340494# Sends notification mail to recipients regarding an IPDB operation
Note: See TracChangeset for help on using the changeset viewer.