Changeset 713


Ignore:
Timestamp:
03/25/15 17:18:30 (9 years ago)
Author:
Kris Deugau
Message:

/trunk

Review and revise splitBlock() and shrinkBlock() to properly handle
n-depth nested allocation structures, as well as making sure master
blocks can be shrunk or split without leaving dangling data. See #7.

File:
1 edited

Legend:

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

    r712 r713  
    14601460# Returns an arrayref to a list of hashrefs with ID and CIDR keys for the list of new allocations.
    14611461# Should probably commit DNS magic to realign DNS data
     1462# Mostly works but may return Strange Things(TM) if used on a master block
    14621463sub splitBlock {
    14631464  my $dbh = shift;
     
    15221523    # prepare
    15231524    my $idsth = $dbh->prepare("SELECT currval('allocations_id_seq')");
    1524     my $poolsth = $dbh->prepare("INSERT INTO allocations (cidr, $fields_sql)".
     1525    my $allocsth = $dbh->prepare("INSERT INTO allocations (cidr, $fields_sql)".
    15251526        " VALUES (?".',?'x(scalar(@fieldlist)).")");
    1526     my $poolchildsth = $dbh->prepare("UPDATE poolips SET parent_id = ? WHERE ip << ? AND parent_id = ?");
    15271527    my $nbsth = $dbh->prepare("DELETE FROM poolips WHERE parent_id = ? AND ip = ?");
     1528    my $upd_psth = $dbh->prepare("UPDATE allocations SET parent_id = ? WHERE parent_id = ? AND cidr <<= ?");
     1529    my $upd_msth = $dbh->prepare("UPDATE allocations SET master_id = ? WHERE master_id = ? AND cidr <<= ?");
     1530    my $fb_psth = $dbh->prepare("UPDATE freeblocks SET parent_id = ? WHERE parent_id = ? AND cidr <<= ?");
     1531    my $fb_msth = $dbh->prepare("UPDATE freeblocks SET master_id = ? WHERE master_id = ? AND cidr <<= ?");
     1532    my $pool_psth = $dbh->prepare("UPDATE poolips SET parent_id = ? WHERE parent_id = ? AND ip << ?");
     1533    my $pool_msth = $dbh->prepare("UPDATE poolips SET master_id = ? WHERE master_id = ? AND ip <<= ?");
    15281534
    15291535    # set up update of existing block
    15301536    $dbh->do("UPDATE allocations SET cidr = ? WHERE id = ?", undef, ("$newblocks[0]", $args{id}) );
    15311537
    1532     # axe the net, gw, and bcast IPs as necessary when splitting a "normal" pool
     1538    # axe the new bcast IP from the smaller pool at the "base" block, if it's a "normal" pool
    15331539    if ($binfo->{type} =~ /.d/) {
    15341540      $newblocks[0]--;
     
    15381544    # Loop over the new blocks that are not the base block
    15391545    for (my $i = 1; $i <= $#newblocks; $i++) {
    1540       # add the new pool
    1541       $poolsth->execute($newblocks[$i], @vals);
     1546      # add the new allocation
     1547      $allocsth->execute($newblocks[$i], @vals);
    15421548      # fetch the ID of the entry we just added...
    15431549      $idsth->execute();
     
    15581564        $newblocks[$i]++;
    15591565      }
    1560       # ... and update the existing IPs with the new parent_id
    1561       $poolchildsth->execute($nid, $newblocks[$i], $args{id});
    1562     }
     1566
     1567      # Reparent allocations, freeblocks, and pool IPs. 
     1568      $upd_psth->execute($nid, $args{id}, $newblocks[$i]);
     1569      $fb_psth->execute($nid, $args{id}, $newblocks[$i]);
     1570      $pool_psth->execute($nid, $args{id}, $newblocks[$i]);
     1571
     1572      # Update master if we've split a master block
     1573      if ($binfo->{type} eq 'mm') {
     1574        $upd_msth->execute($nid, $args{id}, $newblocks[$i]);
     1575        $fb_msth->execute($nid, $args{id}, $newblocks[$i]);
     1576        $pool_msth->execute($nid, $args{id}, $newblocks[$i]);
     1577      }
     1578
     1579    } # for (... @newblocks)
    15631580
    15641581    $dbh->commit;
     
    16141631  local $dbh->{RaiseError} = 1;
    16151632
    1616   my $fbsth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,vrf,parent_id,master_id) VALUES (?,?,?,?,?,?)");
     1633  my $addfbsth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,vrf,parent_id,master_id) VALUES (?,?,?,?,?,?)");
    16171634  my $idsth = $dbh->prepare("SELECT currval('freeblocks_id_seq')");
    16181635  my $poolsth = $dbh->prepare("DELETE FROM poolips WHERE parent_id = ? AND ip << ?");
    16191636  my $netsth = $dbh->prepare("DELETE FROM poolips WHERE parent_id = ? AND ip = ?");
     1637  my $allocsth = $dbh->prepare("DELETE FROM allocations WHERE parent_id = ? AND cidr <<= ?");
     1638  my $delfbsth = $dbh->prepare("DELETE FROM freeblocks WHERE parent_id = ? AND cidr <<= ?");
     1639
     1640##fixme:  turn this into a public/top-level sub?
     1641  sub getchildren {
     1642    my $dbh = shift;
     1643    my $id = shift;
     1644    my $master = shift;
     1645    my $retlist = shift;  # better than trying to return complex structures recursively. Ow.
     1646    my $cidr = shift;
     1647
     1648    if (!$cidr) {
     1649      my $bd = getBlockData($dbh, $id);
     1650      $cidr = $bd->{cidr};
     1651    }
     1652
     1653    my $sth = $dbh->prepare(q(
     1654        SELECT id,cidr,type FROM allocations
     1655        WHERE parent_id = ? AND master_id = ? AND cidr <<= ?
     1656        ) );
     1657    $sth->execute($id, $master, $cidr);
     1658    while (my $row = $sth->fetchrow_hashref) {
     1659      push @$retlist, $row;
     1660      getchildren($dbh, $row->{id}, $master, $retlist, $cidr);
     1661    }
     1662  }
    16201663
    16211664  my @ret;
     
    16341677    # set new freeblocks, and clean up any IP pool entries if needed.
    16351678    foreach my $newfree (@wb2) {
    1636       # add as freeblock
    1637       $fbsth->execute($newfree, $pinfo->{city}, (split //, $pinfo->{type})[1], $pinfo->{vrf},
    1638         $binfo->{parent_id}, $binfo->{master_id});
    1639       $idsth->execute;
    1640       my ($nid) = $idsth->fetchrow_array();
    1641       # add to return list
    1642       push @ret, {fbid => $nid, newfree => "$newfree", fbparent => $binfo->{parent_id} };
    1643       # clean up pool IPs if necessary
    1644       if ($binfo->{type} =~ /.[dp]/) {
    1645         $poolsth->execute($id, $newfree);
    1646       }
    1647     }
     1679      my @clist;
     1680      # the block we're munging
     1681      push @clist, { id => $id, type => $binfo->{type}, cidr => $binfo->{block} };
     1682      getchildren($dbh, $id, $binfo->{master_id}, \@clist, $newfree);
     1683
     1684      foreach my $goner (@clist) {
     1685        $poolsth->execute($goner->{id}, $newfree) if $goner->{type} =~ /.[dp]/;
     1686        $allocsth->execute($goner->{id}, $newfree);
     1687        $delfbsth->execute($goner->{id}, $newfree);
     1688      }
     1689
     1690      # No pinfo means we're shrinking a master block, which means the free space is returned outside of IPDB.
     1691      if ($pinfo) {
     1692        $addfbsth->execute($newfree, $pinfo->{city}, 'm', $pinfo->{vrf}, $binfo->{parent_id}, $pinfo->{master_id});
     1693        $idsth->execute;
     1694        my ($nid) = $idsth->fetchrow_array();
     1695        # add to return list
     1696        push @ret, {fbid => $nid, newfree => "$newfree", fbparent => $binfo->{parent_id} };
     1697      }
     1698
     1699    } # $newfree (@wb2)
    16481700
    16491701    # additional cleanup on net/gw/bcast IPs in pool
Note: See TracChangeset for help on using the changeset viewer.