Changeset 633 for trunk/cgi-bin/IPDB.pm


Ignore:
Timestamp:
10/08/14 18:01:55 (10 years ago)
Author:
Kris Deugau
Message:

/trunk

Commit 7/mumble for work done intermittently over the past ~year.
See #5, comment 25:

  • Netblock assignment
    • Update several supporting data-grabber subs in IPDB.pm
    • Update assignment sub
    • Update data-entry, confirmation, and acceptance/error page templates and related main.cgi sections
File:
1 edited

Legend:

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

    r632 r633  
    738738  my $failmsg = "No suitable free block found\n";
    739739
     740  my @vallist;
     741  my $sql;
     742
     743  # Free pool IPs should be easy.
     744  if ($type =~ /^.i$/) {
     745    # User may get an IP from the wrong VRF.  User should not be using admin tools to allocate static IPs.
     746    $sql = "SELECT id, ip, parent_id FROM poolips WHERE ip = ?";
     747    @vallist = ($optargs{gimme});
     748  } else {
     749
    740750## Set up the SQL to find out what freeblock we can (probably) use for an allocation.
    741751## Very large systems will require development of a reserve system (possibly an extension
     
    743753## Also populate a value list for the DBI call.
    744754
    745   my @vallist = ($maskbits);
    746   my $sql = "SELECT cidr,rdepth FROM freeblocks WHERE masklen(cidr) <= ?";
     755    @vallist = ($maskbits);
     756    $sql = "SELECT id,cidr,parent_id FROM freeblocks WHERE masklen(cidr) <= ?";
    747757
    748758# cases, strict rules
     
    765775##fixme:  strict-or-not flag
    766776
     777##fixme:  config or UI flag for "Strict" mode
     778# if ($strictmode) {
     779if (0) {
    767780  if ($type =~ /^(.)r$/) {
    768781    push @vallist, $1;
     
    773786    $sql .= " AND routed = 'r'";
    774787  }
    775 
    776   # for PPP(oE) and container types, the POP city is the one attached to the pool.
    777   # individual allocations get listed with the customer city site.
    778   ##fixme:  chain cities to align roughly with a full layer-2 node graph
    779   $city = $pop if $type !~ /^.[pc]$/;
    780   if ($type ne 'rm' && $city) {
    781     $sql .= " AND city = ?";
    782     push @vallist, $city;
    783   }
    784   # Allow specifying an arbitrary full block, instead of a master
    785   if ($optargs{gimme}) {
    786     $sql .= " AND cidr >>= ?";
    787     push @vallist, $optargs{gimme};
    788   }
    789   # if a specific master was requested, allow the requestor to self->shoot(foot)
    790   if ($optargs{master} && $optargs{master} ne '-') {
    791     $sql .= " AND cidr <<= ?" if $optargs{master} ne '-';
    792     push @vallist, $optargs{master};
    793   } else {
    794     # if a specific master was NOT requested, filter out the RFC 1918 private networks
    795     if (!$optargs{allowpriv}) {
    796       $sql .= " AND NOT (cidr <<= '192.168.0.0/16' OR cidr <<= '10.0.0.0/8' OR cidr <<= '172.16.0.0/12')";
    797     }
    798   }
    799   # Sorting and limiting, since we don't (currently) care to provide a selection of
    800   # blocks to carve up.  This preserves something resembling optimal usage of the IP
    801   # space by forcing contiguous allocations and free blocks as much as possible.
    802   $sql .= " ORDER BY maskbits DESC,cidr LIMIT 1";
    803 
    804   my ($fbfound,$fbdepth) = $dbh->selectrow_array($sql, undef, @vallist);
    805   return $fbfound,$fbdepth;
     788}
     789
     790    # for PPP(oE) and container types, the POP city is the one attached to the pool.
     791    # individual allocations get listed with the customer city site.
     792    ##fixme:  chain cities to align roughly with a full layer-2 node graph
     793    $city = $pop if $type !~ /^.[pc]$/;
     794    if ($type ne 'rm' && $city) {
     795      $sql .= " AND city = ?";
     796      push @vallist, $city;
     797    }
     798    # Allow specifying an arbitrary full block, instead of a master
     799    if ($optargs{gimme}) {
     800      $sql .= " AND cidr >>= ?";
     801      push @vallist, $optargs{gimme};
     802    }
     803    # if a specific master was requested, allow the requestor to self->shoot(foot)
     804    if ($optargs{master} && $optargs{master} ne '-') {
     805      $sql .= " AND master_id = ?";
     806# if $optargs{master} ne '-';
     807      push @vallist, $optargs{master};
     808    } else {
     809      # if a specific master was NOT requested, filter out the RFC 1918 private networks
     810      if (!$optargs{allowpriv}) {
     811        $sql .= " AND NOT (cidr <<= '192.168.0.0/16' OR cidr <<= '10.0.0.0/8' OR cidr <<= '172.16.0.0/12')";
     812      }
     813    }
     814    # Sorting and limiting, since we don't (currently) care to provide a selection of
     815    # blocks to carve up.  This preserves something resembling optimal usage of the IP
     816    # space by forcing contiguous allocations and free blocks as much as possible.
     817    $sql .= " ORDER BY masklen(cidr) DESC,cidr LIMIT 1";
     818  } # done setting up SQL for free CIDR block
     819
     820  my ($fbid,$fbfound,$fbparent) = $dbh->selectrow_array($sql, undef, @vallist);
     821  return $fbid,$fbfound,$fbparent;
    806822} # end findAllocateFrom()
    807823
     
    872888
    873889  $args{cidr} = new NetAddr::IP $args{cidr};
    874   $args{alloc_from} = new NetAddr::IP $args{alloc_from};
    875890
    876891  $args{desc} = '' if !$args{desc};
     
    883898  my $sth;
    884899
    885   # Snag the "type" of the freeblock (alloc_from) "just in case"
    886   $sth = $dbh->prepare("select routed from freeblocks where cidr='$args{alloc_from}'");
    887   $sth->execute;
    888   my ($alloc_from_type) = $sth->fetchrow_array;
     900  # Snag the "type" of the freeblock and its CIDR
     901  my ($alloc_from_type, $alloc_from, $fbparent, $fcity, $fbmaster) =
     902        $dbh->selectrow_array("SELECT routed,cidr,parent_id,city,master_id FROM freeblocks WHERE id = ?",
     903        undef, $args{fbid});
     904  $alloc_from = new NetAddr::IP $alloc_from;
    889905
    890906  # To contain the error message, if any.
     
    908924                undef, ($args{alloc_from}) );
    909925      }
    910       $dbh->do("UPDATE poolips SET custid=?,city=?,available='n',description=?,notes=?,circuitid=?,privdata=?,vrf=?,rdns=? ".
    911         "WHERE ip=?", undef, ($args{custid}, $args{city}, $args{desc}, $args{notes}, $args{circid},
    912                 $args{privdata}, $args{vrf}, $args{rdns}, $args{cidr}) );
     926      $dbh->do("UPDATE poolips SET custid = ?, city = ?,available='n', description = ?, notes = ?, ".
     927        "circuitid = ?, privdata = ?, vrf = ?, rdns = ? ".
     928        "WHERE ip = ? AND parent_id = ?", undef,
     929                ($args{custid}, $args{city}, $args{desc}, $args{notes},
     930                $args{circid}, $args{privdata}, $args{vrf}, $args{rdns},
     931                $args{cidr}, $args{parent}) );
    913932
    914933# node hack
     
    931950  } else { # end IP-from-pool allocation
    932951
    933     if ($args{cidr} == $args{alloc_from}) {
     952    if ($args{cidr} == $alloc_from) {
    934953      # Easiest case- insert in one table, delete in the other, and go home.  More or less.
    935954      # insert into allocations values (cidr,custid,type,city,desc) and
     
    940959        $msg = "Unable to allocate $args{cidr} as '$disp_alloctypes{$args{type}}'";
    941960
    942         # Get old freeblocks parent/depth/routed for new entries... before we delete it.
    943         my ($fparent) = $dbh->selectrow_array("SELECT parent FROM freeblocks WHERE cidr=? AND rdepth=?",
    944                 undef, ($args{alloc_from}, $args{rdepth}) );
     961        # Insert the allocations entry
     962        $dbh->do("INSERT INTO allocations ".
     963                "(cidr,parent_id,master_id,vrf,custid,type,city,description,notes,circuitid,privdata,rdns)".
     964                " VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", undef,
     965                ($args{cidr}, $fbparent, $fbmaster, $args{vrf}, $args{custid}, $args{type}, $args{city},
     966                $args{desc}, $args{notes}, $args{circid}, $args{privdata}, $args{rdns}) );
     967        my ($bid) = $dbh->selectrow_array("SELECT currval('allocations_id_seq')");
    945968
    946969        # Munge freeblocks
     
    948971          # special case - block is a routed or container/"reserve" block
    949972          my $rtype = $1;
    950           $dbh->do("UPDATE freeblocks SET routed=?,rdepth=rdepth+1,city=?,parent=? WHERE cidr=? AND rdepth=?",
    951                 undef, ($rtype, $args{city}, $args{cidr}, $args{cidr}, $args{rdepth}) );
     973          $dbh->do("UPDATE freeblocks SET routed = ?,city = ?,parent_id = ? WHERE id = ?",
     974                undef, ($rtype, $args{city}, $bid, $args{fbid}) );
    952975        } else {
    953976          # "normal" case
    954           $dbh->do("DELETE FROM freeblocks WHERE cidr=? AND rdepth=?", undef, ($args{cidr}, $args{rdepth}));
     977          $dbh->do("DELETE FROM freeblocks WHERE id = ?", undef, ($args{fbid}) );
    955978        }
    956 
    957         # Insert the allocations entry
    958         $dbh->do("INSERT INTO allocations ".
    959                 "(cidr,parent,vrf,rdepth,custid,type,city,description,notes,circuitid,privdata,rdns)".
    960                 " VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", undef,
    961                 ($args{cidr}, $fparent, $args{vrf}, $args{rdepth}, $args{custid}, $args{type}, $args{city},
    962                 $args{desc}, $args{notes}, $args{circid}, $args{privdata}, $args{rdns}) );
    963979
    964980        # And initialize the pool, if necessary
     
    967983        if ($args{type} =~ /^.p$/) {
    968984          $msg = "Could not initialize IPs in new $disp_alloctypes{$args{type}} $args{cidr}";
    969           my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "all", $args{rdepth}+1);
     985          my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "all", $bid);
    970986          die $rmsg if $code eq 'FAIL';
    971987        } elsif ($args{type} =~ /^.d$/) {
    972988          $msg = "Could not initialize IPs in new $disp_alloctypes{$args{type}} $args{cidr}";
    973           my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "normal", $args{rdepth}+1);
     989          my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "normal", $bid);
    974990          die $rmsg if $code eq 'FAIL';
    975991        }
     
    9921008
    9931009      # Hard case.  Allocation is smaller than free block.
     1010
     1011      # make sure new allocation is in fact within freeblock.  *sigh*
     1012      return ('FAIL',"Requested allocation $args{cidr} is not within $alloc_from")
     1013        if !$alloc_from->contains($args{cidr});
    9941014      my $wantmaskbits = $args{cidr}->masklen;
    995       my $maskbits = $args{alloc_from}->masklen;
     1015      my $maskbits = $alloc_from->masklen;
    9961016
    9971017      my @newfreeblocks;        # Holds free blocks generated from splitting the source freeblock.
     
    10011021      # block is in, and repeat until the wanted block is equal to one of the halves.
    10021022      my $i=0;
    1003       my $tmp_from = $args{alloc_from}; # So we don't munge $args{alloc_from}
     1023      my $tmp_from = $alloc_from;       # So we don't munge $args{alloc_from}
    10041024      while ($maskbits++ < $wantmaskbits) {
    10051025        my @subblocks = $tmp_from->split($maskbits);
     
    10121032        $msg = "Unable to allocate $args{cidr} as '$disp_alloctypes{$args{type}}'";
    10131033
    1014         # Get old freeblocks parent/depth/routed for new entries
    1015         my ($fparent,$fcity,$wasrouted) = $dbh->selectrow_array("SELECT parent,city,routed FROM freeblocks".
    1016                 " WHERE cidr=? AND rdepth=?", undef, ($args{alloc_from}, $args{rdepth}) );
    1017 
    10181034        # Delete old freeblocks entry
    1019         $dbh->do("DELETE FROM freeblocks WHERE cidr=? AND rdepth=?", undef, ($args{alloc_from}, $args{rdepth}) );
     1035        $dbh->do("DELETE FROM freeblocks WHERE id = ?", undef, ($args{fbid}) );
    10201036
    10211037        # Insert new list of smaller free blocks left over
    1022         $sth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,vrf,parent,rdepth) VALUES (?,?,?,?,?,?)");
     1038        $sth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,vrf,parent_id,master_id) VALUES (?,?,?,?,?,?)");
    10231039        foreach my $block (@newfreeblocks) {
    1024           $sth->execute($block, $fcity, $wasrouted, $args{vrf}, $fparent, $args{rdepth});
     1040          $sth->execute($block, $fcity, $alloc_from_type, $args{vrf}, $fbparent, $fbmaster);
    10251041        }
     1042
     1043        # Insert the allocations entry
     1044        $dbh->do("INSERT INTO allocations ".
     1045                "(cidr,parent_id,master_id,vrf,custid,type,city,description,notes,circuitid,privdata,rdns)".
     1046                " VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", undef,
     1047                ($args{cidr}, $fbparent, $fbmaster, $args{vrf}, $args{custid}, $args{type}, $args{city},
     1048                $args{desc}, $args{notes}, $args{circid}, $args{privdata}, $args{rdns}) );
     1049        my ($bid) = $dbh->selectrow_array("SELECT currval('allocations_id_seq')");
    10261050
    10271051        # For routed/container types, add a freeblock within the allocated block so we can subdivide it further
    10281052        if ($args{type} =~ /(.)[mc]/) { # rm and .c types - containers
    10291053          my $rtype = $1;
    1030           $sth->execute($args{cidr}, $args{city}, $rtype, $args{vrf}, $args{cidr}, $args{rdepth}+1);
     1054          $sth->execute($args{cidr}, $args{city}, $rtype, $args{vrf}, $bid, $fbmaster);
    10311055        }
    1032 
    1033         # Insert the allocations entry
    1034         $dbh->do("INSERT INTO allocations ".
    1035                 "(cidr,parent,vrf,rdepth,custid,type,city,description,notes,circuitid,privdata,rdns)".
    1036                 " VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", undef,
    1037                 ($args{cidr}, $fparent, $args{vrf}, $args{rdepth}, $args{custid}, $args{type}, $args{city},
    1038                 $args{desc}, $args{notes}, $args{circid}, $args{privdata}, $args{rdns}) );
    10391056
    10401057        # And initialize the pool, if necessary
     
    10431060        if ($args{type} =~ /^.p$/) {
    10441061          $msg = "Could not initialize IPs in new $disp_alloctypes{$args{type}} $args{cidr}";
    1045           my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "all", $args{rdepth}+1);
     1062          my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "all", $bid);
    10461063          die $rmsg if $code eq 'FAIL';
    10471064        } elsif ($args{type} =~ /^.d$/) {
    10481065          $msg = "Could not initialize IPs in new $disp_alloctypes{$args{type}} $args{cidr}";
    1049           my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "normal", $args{rdepth}+1);
     1066          my ($code,$rmsg) = initPool($dbh, $args{cidr}, $args{type}, $args{city}, "normal", $bid);
    10501067          die $rmsg if $code eq 'FAIL';
    10511068        }
     
    10861103# function and should ONLY EVER get called from allocateBlock()
    10871104sub initPool {
    1088   my ($dbh,undef,$type,$city,$class,$rdepth) = @_;
     1105  my ($dbh,undef,$type,$city,$class,$parent) = @_;
    10891106  my $pool = new NetAddr::IP $_[1];
    10901107
     
    10951112  return ('FAIL',"Refusing to create oversized static IP pool") if $pool->masklen <= 20;
    10961113
    1097 ##fixme Need to just replace 2nd char of type with i rather than capturing 1st char of type
     1114  my ($pcustid) = $dbh->selectrow_array("SELECT def_custid FROM alloctypes WHERE type=?", undef, ($type) );
    10981115  $type =~ s/[pd]$/i/;
    10991116  my $sth;
     
    11081125  eval {
    11091126    # have to insert all pool IPs into poolips table as "unallocated".
    1110     $sth = $dbh->prepare("INSERT INTO poolips (pool,ip,custid,city,type,rdepth)".
    1111         " VALUES ('$pool', ?, '$defcustid', ?, '$type', $rdepth)");
     1127    $sth = $dbh->prepare("INSERT INTO poolips (ip,custid,city,type,parent_id) VALUES (?,?,?,?,?)");
    11121128    my @poolip_list = $pool->hostenum;
    11131129    if ($class eq 'all') { # (DSL-ish block - *all* IPs available
    11141130      if ($pool->addr !~ /\.0$/) {      # .0 causes weirdness.
    1115         $sth->execute($pool->addr, $city);
     1131        $sth->execute($pool->addr, $pcustid, $city, $type, $parent);
    11161132      }
    11171133      for (my $i=0; $i<=$#poolip_list; $i++) {
    1118         $sth->execute($poolip_list[$i]->addr, $city);
     1134        $sth->execute($poolip_list[$i]->addr, $pcustid, $city, $type, $parent);
    11191135      }
    11201136      $pool--;
    11211137      if ($pool->addr !~ /\.255$/) {    # .255 can cause weirdness.
    1122         $sth->execute($pool->addr, $city);
     1138        $sth->execute($pool->addr, $pcustid, $city, $type, $parent);
    11231139      }
    11241140    } else { # (real netblock)
    11251141      for (my $i=1; $i<=$#poolip_list; $i++) {
    1126         $sth->execute($poolip_list[$i]->addr, $city);
    1127       }
    1128     }
    1129     $dbh->commit;
     1142        $sth->execute($poolip_list[$i]->addr, $pcustid, $city, $type, $parent);
     1143      }
     1144    }
     1145# don't commit here!  the caller may not be done.
     1146#    $dbh->commit;
    11301147  };
    11311148  if ($@) {
    11321149    $msg = $@;
    1133     eval { $dbh->rollback; };
     1150# Don't roll back!  It's up to the caller to handle this.
     1151#    eval { $dbh->rollback; };
    11341152    return ('FAIL',$msg);
    11351153  } else {
Note: See TracChangeset for help on using the changeset viewer.