Changeset 702 for trunk/cgi-bin/IPDB.pm
- Timestamp:
- 02/23/15 18:16:11 (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/cgi-bin/IPDB.pm
r699 r702 32 32 &getMasterList &getTypeList &getPoolSelect &findAllocateFrom 33 33 &ipParent &subParent &blockParent &getBreadCrumbs &getRoutedCity 34 &allocateBlock &updateBlock & deleteBlock &getBlockData &getBlockRDNS &getRDNSbyIP34 &allocateBlock &updateBlock &splitBlock &deleteBlock &getBlockData &getBlockRDNS &getRDNSbyIP 35 35 &getNodeList &getNodeName &getNodeInfo 36 36 &mailNotify … … 47 47 &getMasterList &getTypeList &getPoolSelect &findAllocateFrom 48 48 &ipParent &subParent &blockParent &getBreadCrumbs &getRoutedCity 49 &allocateBlock &updateBlock & deleteBlock &getBlockData &getBlockRDNS &getRDNSbyIP49 &allocateBlock &updateBlock &splitBlock &deleteBlock &getBlockData &getBlockRDNS &getRDNSbyIP 50 50 &getNodeList &getNodeName &getNodeInfo 51 51 &mailNotify … … 1453 1453 1454 1454 1455 ## IPDB::splitBlock() 1456 # Splits an existing allocation into two or more smaller allocations based on a passed netmask 1457 # Duplicates all other data 1458 # Returns an arrayref to a list of hashrefs with ID and CIDR keys for the list of new allocations. 1459 # Should probably commit DNS magic to realign DNS data 1460 sub splitBlock { 1461 my $dbh = shift; 1462 my $id = shift; 1463 my $basetype = shift; 1464 my $newmask = shift; 1465 1466 ##fixme: set errstr on errors so caller can suitably clue-by-four the user 1467 return if $basetype ne 'b'; # only netblocks allowed! 1468 1469 my $binfo = getBlockData($dbh, $id); 1470 return if !$binfo; 1471 1472 return if $newmask !~ /^\d+$/; 1473 1474 my @ret; 1475 my $block = new NetAddr::IP $binfo->{block}; 1476 my $oldmask = $block->masklen; 1477 1478 # Fail if the block to split is "too small" - eg, can't split a v4 /32 at all 1479 # failure modes: 1480 # difference between $oldmask and $newmask is negative or 0 1481 if ($newmask - $oldmask <= 0) { 1482 $errstr = "Can't split a /$oldmask allocation into /$newmask pieces"; 1483 return; 1484 } 1485 # # difference between $oldmask and $newmask is > n, for arbitrary n? 1486 # if ($newmask - $oldmask > 42) { # because 42 1487 # } 1488 # $oldmask > n, for arbitrary n? At least check limits of data type. 1489 if ($block->{isv6}) { 1490 if ($newmask - $oldmask > 128) { 1491 $errstr = "Impossible IPv6 mask length /$newmask requested"; 1492 return; 1493 } 1494 } else { 1495 if ($newmask - $oldmask > 32) { 1496 $errstr = "Impossible IPv4 mask length /$newmask requested"; 1497 return; 1498 } 1499 } 1500 1501 my @newblocks = $block->split($newmask); 1502 1503 local $dbh->{AutoCommit} = 0; 1504 local $dbh->{RaiseError} = 1; 1505 1506 eval { 1507 # line up a list of fields and values. Be nice if there was a handy way to do, 1508 # direct in SQL, something like 1509 # "INSERT INTO foo (f1,f2,f3) VALUES (newf1,(SELECT oldf2,oldf3 FROM foo WHERE baz))" 1510 my @fieldlist = qw(type city description notes circuitid privdata custid swip vrf vlan rdns parent_id master_id); 1511 my $fields_sql = join(',', @fieldlist); 1512 my @vals; 1513 foreach (@fieldlist) { 1514 push @vals, $binfo->{$_}; 1515 } 1516 # note the first block in the split for return 1517 push @ret, {nid => $id, nblock => "$newblocks[0]"}; 1518 1519 # prepare 1520 my $idsth = $dbh->prepare("SELECT currval('allocations_id_seq')"); 1521 my $poolsth = $dbh->prepare("INSERT INTO allocations (cidr, $fields_sql)". 1522 " VALUES (?".',?'x(scalar(@fieldlist)).")"); 1523 my $poolchildsth = $dbh->prepare("UPDATE poolips SET parent_id = ? WHERE ip << ? AND parent_id = ?"); 1524 my $nbsth = $dbh->prepare("DELETE FROM poolips WHERE parent_id = ? AND ip = ?"); 1525 1526 # set up update of existing block 1527 $dbh->do("UPDATE allocations SET cidr = ? WHERE id = ?", undef, ("$newblocks[0]", $id) ); 1528 1529 # axe the net, gw, and bcast IPs as necessary when splitting a "normal" pool 1530 if ($binfo->{type} =~ /.d/) { 1531 $newblocks[0]--; 1532 $nbsth->execute($id, $newblocks[0]->addr); 1533 } 1534 1535 # Loop over the new blocks that are not the base block 1536 for (my $i = 1; $i <= $#newblocks; $i++) { 1537 # add the new pool 1538 $poolsth->execute($newblocks[$i], @vals); 1539 # fetch the ID of the entry we just added... 1540 $idsth->execute(); 1541 my ($nid) = $idsth->fetchrow_array(); 1542 # ... so we can pass back the list of blocks and IDs... 1543 push @ret, {nid => $nid, nblock => "$newblocks[$i]"}; 1544 # axe the net, gw, and bcast IPs as necessary when splitting a "normal" pool 1545 if ($binfo->{type} =~ /.d/) { 1546 # net 1547 $nbsth->execute($id, $newblocks[$i]->addr); 1548 $newblocks[$i]++; 1549 # gw 1550 $nbsth->execute($id, $newblocks[$i]->addr); 1551 $newblocks[$i]--; 1552 $newblocks[$i]--; 1553 # bcast 1554 $nbsth->execute($id, $newblocks[$i]->addr); 1555 $newblocks[$i]++; 1556 } 1557 # ... and update the existing IPs with the new parent_id 1558 $poolchildsth->execute($nid, $newblocks[$i], $id); 1559 } 1560 1561 $dbh->commit; 1562 }; 1563 if ($@) { 1564 $errstr = "Error splitting $binfo->{block}: $@"; 1565 $dbh->rollback; 1566 return; 1567 } 1568 1569 return \@ret; 1570 } # end splitBlock() 1571 1572 1455 1573 ## IPDB::deleteBlock() 1456 1574 # Removes an allocation from the database, including deleting IPs
Note:
See TracChangeset
for help on using the changeset viewer.