Changeset 774
- Timestamp:
- 09/09/15 18:05:19 (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/cgi-bin/IPDB.pm
r773 r774 1898 1898 my $dbh = shift; 1899 1899 my %args = @_; 1900 # my $id = shift;1901 # my $basetype = shift;1902 # my $newmask = shift;1903 1900 1904 1901 ##fixme: set errstr on errors so caller can suitably clue-by-four the user … … 1959 1956 my $allocsth = $dbh->prepare("INSERT INTO allocations (cidr, $fields_sql)". 1960 1957 " VALUES (?".',?'x(scalar(@fieldlist)).")"); 1958 my $allocsth2 = $dbh->prepare(qq( 1959 INSERT INTO allocations (cidr, $fields_sql) 1960 SELECT ? AS cidr, $fields_sql 1961 FROM allocations 1962 WHERE id = ? 1963 ) ); 1961 1964 my $nbsth = $dbh->prepare("DELETE FROM poolips WHERE parent_id = ? AND ip = ?"); 1962 1965 my $upd_psth = $dbh->prepare("UPDATE allocations SET parent_id = ? WHERE parent_id = ? AND cidr <<= ?"); … … 1967 1970 my $pool_msth = $dbh->prepare("UPDATE poolips SET master_id = ? WHERE master_id = ? AND ip <<= ?"); 1968 1971 1969 # set up update of existing block 1970 $dbh->do("UPDATE allocations SET cidr = ? WHERE id = ?", undef, ("$newblocks[0]", $args{id}) ); 1971 1972 # axe the new bcast IP from the smaller pool at the "base" block, if it's a "normal" pool 1973 if ($binfo->{type} =~ /.d/) { 1974 $newblocks[0]--; 1975 $nbsth->execute($args{id}, $newblocks[0]->addr); 1976 } 1977 1978 # Holder for freeblocks-to-delete. Should be impossible to have more than one... 1979 my %fbdel; 1980 1981 # Loop over the new blocks that are not the base block 1982 for (my $i = 1; $i <= $#newblocks; $i++) { 1983 # add the new allocation 1984 $allocsth->execute($newblocks[$i], @vals); 1985 # fetch the ID of the entry we just added... 1986 $idsth->execute(); 1987 my ($nid) = $idsth->fetchrow_array(); 1988 # ... so we can pass back the list of blocks and IDs... 1989 push @ret, {nid => $nid, nblock => "$newblocks[$i]"}; 1990 # axe the net, gw, and bcast IPs as necessary when splitting a "normal" pool 1991 if ($binfo->{type} =~ /.d/) { 1992 # net 1993 $nbsth->execute($args{id}, $newblocks[$i]->addr); 1994 $newblocks[$i]++; 1995 # gw 1996 $nbsth->execute($args{id}, $newblocks[$i]->addr); 1997 $newblocks[$i]--; 1998 $newblocks[$i]--; 1999 # bcast 2000 $nbsth->execute($args{id}, $newblocks[$i]->addr); 2001 $newblocks[$i]++; 2002 } # $binfo->{type} =~ /.d/ 2003 2004 # Check for free blocks larger than the new mask length, and split those as needed. 2005 if ($binfo->{type} =~ /.[cm]/) { 2006 # get a "list" of freeblocks bigger than the allocation in the parent. there's only one, right? 2007 my $fblist = $dbh->selectall_arrayref("SELECT id FROM freeblocks WHERE cidr >> ? AND parent_id = ? ", 2008 {Slice=>{}}, $newblocks[$i], $args{id}); 2009 if (@$fblist) { 2010 # create a new freeblock for the new block we created earlier 2011 $dbh->do(q{ 2012 INSERT INTO freeblocks (cidr, parent_id, master_id, city, routed,vrf) 2013 SELECT ? AS cidr, ? AS parent_id, master_id, city, routed, vrf FROM freeblocks 2014 WHERE id = ? 2015 }, undef, ($newblocks[$i], $nid, $fblist->[0]->{id}) ); 2016 $fbdel{$fblist->[0]->{id}}++; 1972 my @clist; 1973 _getChildren($dbh, $args{id}, $binfo->{master_id}, \@clist, $block); 1974 1975 my @processlist; 1976 push @processlist, { id => $args{id}, cidr => $block, mask => $block->masklen, type => $binfo->{type} }; 1977 foreach (@clist) { 1978 $_->{cidr} = new NetAddr::IP $_->{cidr}; 1979 if ($_->{cidr}->masklen < $args{newmask}) { 1980 $_->{mask} = $_->{cidr}->masklen; 1981 push @processlist, $_; 1982 } 1983 } 1984 1985 @processlist = sort { $b->{cidr}->masklen <=> $a->{cidr}->masklen } @processlist; 1986 1987 foreach my $pr (@processlist) { 1988 my @nbset = $pr->{cidr}->split($args{newmask}); 1989 1990 # set up update of existing block 1991 $dbh->do("UPDATE allocations SET cidr = ? WHERE id = ?", undef, ("$nbset[0]", $pr->{id}) ); 1992 1993 # axe the new bcast IP from the smaller pool at the "base" block, if it's a "normal" pool 1994 if ($pr->{type} =~ /.d/) { 1995 $nbset[0]--; 1996 $nbsth->execute($pr->{id}, $nbset[0]->addr); 1997 } 1998 1999 # Holder for freeblocks-to-delete. Should be impossible to have more than one... 2000 my %fbdel; 2001 2002 # Loop over the new blocks that are not the base block 2003 for (my $i = 1; $i <= $#nbset; $i++) { 2004 # add the new allocation 2005 $allocsth2->execute($nbset[$i], $pr->{id}); 2006 2007 # fetch the ID of the entry we just added... 2008 $idsth->execute(); 2009 my ($nid) = $idsth->fetchrow_array(); 2010 # ... so we can pass back the list of blocks and IDs... 2011 push @ret, {nid => $nid, nblock => "$nbset[$i]"}; 2012 # axe the net, gw, and bcast IPs as necessary when splitting a "normal" pool 2013 if ($pr->{type} =~ /.d/) { 2014 # net 2015 $nbsth->execute($pr->{id}, $nbset[$i]->addr); 2016 $nbset[$i]++; 2017 # gw 2018 $nbsth->execute($pr->{id}, $nbset[$i]->addr); 2019 $nbset[$i]--; 2020 $nbset[$i]--; 2021 # bcast 2022 $nbsth->execute($pr->{id}, $nbset[$i]->addr); 2023 $nbset[$i]++; 2024 } # $binfo->{type} =~ /.d/ 2025 2026 # Check for free blocks larger than the new mask length, and split those as needed. 2027 if ($pr->{type} =~ /.[cm]/) { 2028 # get a "list" of freeblocks bigger than the allocation in the parent. there's only one, right? 2029 my $fblist = $dbh->selectall_arrayref("SELECT id FROM freeblocks WHERE cidr >> ? AND parent_id = ? ", 2030 {Slice=>{}}, $nbset[$i], $pr->{id}); 2031 if (@$fblist) { 2032 # create a new freeblock for the new block we created earlier 2033 $dbh->do(q{ 2034 INSERT INTO freeblocks (cidr, parent_id, master_id, city, routed,vrf) 2035 SELECT ? AS cidr, ? AS parent_id, master_id, city, routed, vrf FROM freeblocks 2036 WHERE id = ? 2037 }, undef, ($nbset[$i], $nid, $fblist->[0]->{id}) ); 2038 $fbdel{$fblist->[0]->{id}}++; 2039 } 2040 } # $binfo->{type} =~ /.[cm]/ 2041 2042 # Reparent allocations, freeblocks, and pool IPs. 2043 $upd_psth->execute($nid, $pr->{id}, $nbset[$i]); 2044 $fb_psth->execute($nid, $pr->{id}, $nbset[$i]); 2045 $pool_psth->execute($nid, $pr->{id}, $nbset[$i]); 2046 2047 # Update master if we've split a master block 2048 if ($pr->{type} eq 'mm') { 2049 $upd_msth->execute($nid, $pr->{id}, $nbset[$i]); 2050 $fb_msth->execute($nid, $pr->{id}, $nbset[$i]); 2051 $pool_msth->execute($nid, $pr->{id}, $nbset[$i]); 2017 2052 } 2018 } # $binfo->{type} =~ /.[cm]/2019 2020 # Reparent allocations, freeblocks, and pool IPs.2021 $upd_psth->execute($nid, $args{id}, $newblocks[$i]);2022 $fb_psth->execute($nid, $args{id}, $newblocks[$i]);2023 $pool_psth->execute($nid, $args{id}, $newblocks[$i]);2024 2025 # Update master if we've split a master block2026 if ($binfo->{type} eq 'mm') {2027 $upd_msth->execute($nid, $args{id}, $newblocks[$i]);2028 $fb_msth->execute($nid, $args{id}, $newblocks[$i]);2029 $pool_msth->execute($nid, $args{id}, $newblocks[$i]);2030 }2031 2053 2032 2054 ##fixme: 2055 # 2015/09/09 not sure if the latest rewrite has covered this case complete or not 2033 2056 # Still missing one edge case - megasplitting a large block such that "many" children also need to be split. 2034 2057 # I'm going to call this "unsupported" because I really can't imagine a sane reason for doing this. 2035 2058 # Should probably check and error out at least 2036 2059 2037 } # for (... @newblocks) 2038 2039 $dbh->do("DELETE FROM freeblocks WHERE id IN (".join(',', keys %fbdel).")") if %fbdel; 2060 } # for (... @nbset) 2061 2062 if (%fbdel) { 2063 my $delfblist = $dbh->selectall_arrayref(q{ 2064 SELECT cidr,parent_id,id FROM freeblocks 2065 WHERE id in ( 2066 }.join(',', keys %fbdel).")", {Slice=>{}} ); 2067 $dbh->do("DELETE FROM freeblocks WHERE id IN (".join(',', keys %fbdel).")") if %fbdel; 2068 } 2069 2070 } # foreach @processlist 2040 2071 2041 2072 $dbh->commit;
Note:
See TracChangeset
for help on using the changeset viewer.