Changeset 692


Ignore:
Timestamp:
02/11/15 18:43:22 (9 years ago)
Author:
Kris Deugau
Message:

/trunk

Start adding support for advisory "reserved block" assignments - when
creating a new assignment, flag an equal-sized block ahead or behind
to expand the assignment in the future. See #24.

  • free block assignment
  • guided assignment (still needs tweaking to dodge existing reserved blocks)
  • note flagged blocks in free block list
Location:
trunk
Files:
5 edited

Legend:

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

    r691 r692  
    674674  $args{vrf} = '' if !$args{vrf};
    675675
    676   my $sth = $dbh->prepare("SELECT cidr,id FROM freeblocks WHERE parent_id = ? ORDER BY cidr");
     676  my $sth = $dbh->prepare(q(
     677        SELECT f.cidr,f.id,allocations.cidr
     678        FROM freeblocks f
     679        LEFT JOIN allocations ON f.reserve_for = allocations.id
     680        WHERE f.parent_id = ?
     681        ORDER BY f.cidr
     682        ) );
    677683#  $sth->execute($args{parent}, $args{vrf});
    678684  $sth->execute($args{parent});
    679685  my @flist;
    680   while (my ($cidr,$id) = $sth->fetchrow_array()) {
     686  while (my ($cidr,$id,$resv) = $sth->fetchrow_array()) {
    681687    $cidr = new NetAddr::IP $cidr;
    682688    my %row = (
     
    685691        fbid => $id,
    686692        fbparent => $args{parent},
     693        resv => $resv,
    687694        );
    688695    push @flist, \%row;
     
    985992        undef, $args{fbid});
    986993  $alloc_from = new NetAddr::IP $alloc_from;
     994  return ('FAIL',"Failed to allocate $args{cidr};  intended free block was used by another allocation.")
     995        if !$fbparent;
     996##fixme:  fail here if !$alloc_from
     997# also consider "lock for allocation" due to multistep allocation process
    987998
    988999  # To contain the error message, if any.
     
    11171128        $dbh->do("DELETE FROM freeblocks WHERE id = ?", undef, ($args{fbid}) );
    11181129
    1119         # Insert new list of smaller free blocks left over
    1120         $sth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,vrf,parent_id,master_id) VALUES (?,?,?,?,?,?)");
    1121         foreach my $block (@newfreeblocks) {
    1122           $sth->execute($block, $fcity, $alloc_from_type, $args{vrf}, $fbparent, $fbmaster);
    1123         }
    1124 
    11251130        # Insert the allocations entry
    11261131        $dbh->do("INSERT INTO allocations ".
     
    11301135                $args{desc}, $args{notes}, $args{circid}, $args{privdata}, $args{rdns}) );
    11311136        my ($bid) = $dbh->selectrow_array("SELECT currval('allocations_id_seq')");
     1137
     1138        # Insert new list of smaller free blocks left over. Flag the one that matches the
     1139        # masklength of the new allocation, if a reserve block was requested.
     1140        $sth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,vrf,parent_id,master_id,reserve_for) ".
     1141                "VALUES (?,?,?,?,?,?,?)");
     1142        foreach my $block (@newfreeblocks) {
     1143          $sth->execute($block, $fcity, $alloc_from_type, $args{vrf}, $fbparent, $fbmaster,
     1144                ($block->masklen == $wantmaskbits ? $bid : 0));
     1145        }
    11321146
    11331147        # For routed/container types, add a freeblock within the allocated block so we can subdivide it further
     
    17141728  my ($btype) = $dbh->selectrow_array("SELECT type FROM allocations WHERE id=?", undef, ($id) );
    17151729
     1730  # Note city, vrf, parent_id and master_id removed due to JOIN uncertainty for block allocations
     1731  my $commonfields = q(custid, type, circuitid, description, notes, modifystamp AS lastmod,
     1732        privdata, vlan, rdns);
     1733
    17161734  if ($type eq 'i') {
    1717     my $binfo = $dbh->selectrow_hashref("SELECT ip AS block, custid, type, city, circuitid, description,".
    1718         " notes, modifystamp AS lastmod, privdata, vrf, vlan, rdns, parent_id, master_id".
    1719         " FROM poolips WHERE id = ?", undef, ($id) );
     1735    my $binfo = $dbh->selectrow_hashref(qq(
     1736        SELECT ip AS block, city, vrf, parent_id, master_id, $commonfields
     1737        FROM poolips WHERE id = ?
     1738        ), undef, ($id) );
    17201739    return $binfo;
    17211740  } else {
    1722     my $binfo = $dbh->selectrow_hashref("SELECT cidr AS block, custid, type, city, circuitid, ".
    1723         "description, notes, modifystamp AS lastmod, privdata, vrf, vlan, swip, rdns, parent_id, master_id".
    1724         " FROM allocations WHERE id = ?", undef, ($id) );
     1741    my $binfo = $dbh->selectrow_hashref(qq(
     1742        SELECT a.cidr AS block, a.city, a.vrf, a.parent_id, a.master_id, swip, $commonfields,
     1743                f.cidr AS reserve, f.id as reserve_id
     1744        FROM allocations a LEFT JOIN freeblocks f ON a.id=f.reserve_for
     1745        WHERE a.id = ?
     1746        ), undef, ($id) );
    17251747    return $binfo;
    17261748  }
  • trunk/cgi-bin/main.cgi

    r691 r692  
    410410
    411411  my $cidr;
     412  my $resv;   # Reserved for expansion.
    412413  my $alloc_from;
    413414  my $fbid = $webvar{fbid};
     
    443444      $alloc_from = new NetAddr::IP $webvar{allocfrom};
    444445      $webvar{maskbits} = $cidr->masklen;
     446      # Some additional checks are needed for reserving free space
     447      if ($webvar{reserve}) {
     448        if ($cidr == $alloc_from) {
     449# We could still squirm and fiddle to try to find a way to reserve space, but the storage model for
     450# IPDB means that all continguous free space is kept in the smallest number of strict CIDR netblocks
     451# possible.  (In theory.)  If the request and the freeblock are the same, it is theoretically impossible
     452# to reserve an equivalent-sized block either ahead or behind the requested one, because the pair
     453# together would never be a strict CIDR block.
     454          $page->param(warning => "Can't reserve space for expansion;  free block and requested allocation are the same.");
     455          delete $webvar{reserve};
     456        } else {
     457          # Find which new free block will match the reqested block.
     458          # Take the requested mask, shift by one
     459          my $tmpmask = $webvar{maskbits};
     460          $tmpmask--;
     461          # find the subnets with that mask in the selected free block
     462          my @pieces = $alloc_from->split($tmpmask);
     463          foreach my $slice (@pieces) {
     464            if ($slice->contains($cidr)) {
     465              # For the subnet that contains the requested block, split that in two,
     466              # and flag/cache the one that's not the requested block.
     467              my @bits = $slice->split($webvar{maskbits});
     468              if ($bits[0] == $cidr) {
     469                $resv = $bits[1];
     470              } else {
     471                $resv = $bits[0];
     472              }
     473            }
     474          }
     475        }
     476      } # reserve block check
     477
    445478    } else { # done with direct freeblocks assignment
    446479
     
    465498          }
    466499          $failmsg .= "You will have to route another superblock to $webvar{pop}<br>\n".
    467                 "from one of the master blocks or chose a smaller blocksize.";
     500                "from one of the master blocks";
     501          if ($webvar{reserve}) {
     502            $failmsg .= ', choose a smaller blocksize, or uncheck "Reserve space for expansion".';
     503          } else {
     504            $failmsg .= " or chose a smaller blocksize.";
     505          }
    468506        }
    469507      }
    470508
    471 ## fixme:  add rdepth?
     509      # if requesting extra space "reserved for expansion", we need to find a free
     510      # block at least double the size of the request.
     511      if ($webvar{reserve}) {
     512        $webvar{maskbits}--;
     513      }
     514
    472515      ($fbid,$cidr,$p_id) = findAllocateFrom($ip_dbh, $webvar{maskbits}, $webvar{alloctype},
    473516        $webvar{city}, $webvar{pop}, (master => $webvar{allocfrom}, allowpriv => $webvar{allowpriv}) );
     
    478521      $cidr = new NetAddr::IP $cidr;
    479522
    480 # this chunk now specific to "guided" allocation;  freeblock-select can now slice-n-dice on its own.     
    481523      $alloc_from = "$cidr";
     524
     525      # when autofinding a block to allocate from, use the first piece of the found
     526      # block for the allocation, and the next piece for the "reserved for expansion".
     527      if ($webvar{reserve}) {
     528        # reset the mask to the real requested one, now that we've got a
     529        # block large enough for the request plus reserve
     530        $webvar{maskbits}++;
     531        ($cidr,$resv) = $cidr->split($webvar{maskbits});
     532      }
     533
    482534      # If the block to be allocated is smaller than the one we found,
    483535      # figure out the "real" block to be allocated.
     
    524576## end node hack
    525577
     578  # reserve for expansion
     579  $page->param(reserve => $webvar{reserve});
     580  # probably just preventing a little log noise doing this;  could just set the param
     581  # all the time since it won't be shown if the reserve param above isn't set.
     582#  if ($webvar{reserve}) {
     583    $page->param(resvblock => $resv);
     584#  }
     585
    526586  # Stick in the allocation data
    527587  $page->param(alloc_type => $webvar{alloctype});
     
    592652        cidr            => $webvar{fullcidr},
    593653        fbid            => $webvar{fbid},
     654        reserve         => $webvar{reserve},
    594655        parent          => $webvar{parent},
    595656        custid          => $webvar{custid},
  • trunk/templates/assign.tmpl

    r691 r692  
    3131<input name="block" value="<TMPL_VAR NAME=block>" size="40">
    3232<input type="hidden" name="fbassign" value="y">
     33&nbsp;Reserve space to expand block in future
     34<input type="checkbox" name="reserve">
    3335</td>
    3436</TMPL_IF>
     
    6668<tr>
    6769<td>Subnet CIDR mask length:</td>
    68 <td valign="top">&nbsp;/&nbsp;<input type="text" name="maskbits" size="3" maxlength="3"></td>
     70<td valign="top">&nbsp;/&nbsp;<input type="text" name="maskbits" size="3" maxlength="3">
     71&nbsp;Reserve space to expand block in future
     72<input type="checkbox" name="reserve">
     73</td>
    6974</tr>
    7075</TMPL_UNLESS>
  • trunk/templates/confirm.tmpl

    r691 r692  
    77<TMPL_ELSE>
    88<div class="indent">
    9 
     9<TMPL_IF warning>
     10<div class="center warning">
     11<TMPL_VAR NAME=warning>
     12</div>
     13</TMPL_IF>
    1014<form method="POST" action="main.cgi" class="regular">
    1115<fieldset><legend class="noshow">&nbsp;</legend>
     
    1519<tr>
    1620<td>CIDR block to be allocated:</td>
    17 <td><TMPL_VAR NAME=cidr></td>
     21<td><TMPL_VAR NAME=cidr> <TMPL_IF resvblock>(<TMPL_VAR NAME=resvblock> reserved for expansion)</TMPL_IF></td>
    1822</tr>
    1923
     
    119123<input type="hidden" name="parent" value="<TMPL_VAR NAME=parent>">
    120124<input type="hidden" name="fbid" value="<TMPL_VAR NAME=fbid>">
     125<TMPL_IF resvblock><input type="hidden" name="reserve" value="<TMPL_VAR NAME=reserve>"></TMPL_IF>
    121126<input type="hidden" name="fullcidr" value="<TMPL_VAR NAME=cidr>">
    122127<input type="hidden" name="rdns" value="<TMPL_VAR NAME=rdns>">
  • trunk/templates/showsubs.tmpl

    r687 r692  
    106106<TMPL_VAR NAME=fblock>
    107107</TMPL_IF>
     108<TMPL_IF resv><br>(Reserved to expand <TMPL_VAR NAME=resv>)</TMPL_IF>
    108109</td>
    109110<td><TMPL_VAR NAME=frange></td>
Note: See TracChangeset for help on using the changeset viewer.