Changeset 77
- Timestamp:
- 11/19/04 17:43:36 (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/cgi-bin/IPDB.pm
r69 r77 14 14 use warnings; 15 15 use Exporter; 16 use DBI; 16 17 use Net::SMTP; 17 18 use POSIX; 18 19 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 19 20 20 $VERSION = 1.0;21 $VERSION = 2.0; 21 22 @ISA = qw(Exporter); 22 @EXPORT_OK = qw(&connectDB &checkDBSanity &allocateBlock &mailNotify); 23 @EXPORT_OK = qw(&initIPDBGlocals &connectDB &finish &checkDBSanity &allocateBlock 24 &initPool &mailNotify); 23 25 24 26 @EXPORT = (); # Export nothing by default. 25 %EXPORT_TAGS = ( ALL => [qw( &connectDB &checkDBSanity &allocateBlock &mailNotify)] 27 %EXPORT_TAGS = ( ALL => [qw( &initIPDBGlocals &connectDB &checkDBSanity 28 &allocateBlock &initPool &mailNotify)] 26 29 ); 27 30 28 31 ## 32 ## Global variables 33 ## 34 our %disp_alloctypes; 35 our %list_alloctypes; 36 37 # Let's initialize the globals. 38 ## IPDB::initIPDBGlobals() 39 # Initialize all globals. Takes a database handle, returns a success or error code 40 sub initIPDBGlobals { 41 my $dbh = $_[0]; 42 my $sth; 43 44 $sth = $dbh->prepare("select type,dispname from alloctypes"); 45 $sth->execute; 46 return (undef,$sth->errstr) if $sth->err; 47 48 while (my @data = $sth->fetchrow_array) { 49 $disp_alloctypes{$data[0]} = $data[1]; 50 } 51 return (1,"OK"); 52 } # end initIPDBGlobals 53 54 55 ## IPDB::connectDB() 29 56 # Creates connection to IPDB. 30 # Default is a PostgreSQL db; could be any DBMS with the 31 # right changes. MySQL in comments. Note that some DBMS's don't 32 # support transactions, this is a Bad Thing! 57 # Requires the database name, username, and password. 33 58 # Returns a handle to the db. 59 # Set up for a PostgreSQL db; could be any transactional DBMS with the 60 # right changes. 61 # This definition should be sub connectDB($$$) to be technically correct, 62 # but this breaks. GRR. 34 63 sub connectDB { 64 my ($dbname,$user,$pass) = @_; 35 65 my $dbh; 36 my $DSN = "DBI:Pg:dbname= ipdb";37 my $user = 'ipdb';38 my $pw = 'ipdbpwd';66 my $DSN = "DBI:Pg:dbname=$dbname"; 67 # my $user = 'ipdb'; 68 # my $pw = 'ipdbpwd'; 39 69 40 70 # Note that we want to autocommit by default, and we will turn it off locally as necessary. 41 $dbh = DBI->connect($DSN, $user, $pw, { AutoCommit => 1 } ) 42 or return undef if(!$dbh); 43 44 return $dbh; 71 # We may not want to print gobbledygook errors; YMMV. Have to ponder that further. 72 $dbh = DBI->connect($DSN, $user, $pass, { 73 AutoCommit => 1, 74 PrintError => 0 75 }) 76 or return (undef, $DBI::errstr) if(!$dbh); 77 78 # Return here if we can't select. Note that this indicates a 79 # problem executing the select. 80 my $sth = $dbh->prepare('select cidr from masterblocks'); 81 $sth->execute(); 82 return (undef,$DBI::errstr) if ($sth->err); 83 84 # See if the select returned anything (or null data). This should 85 # succeed if the select executed, but... 86 $sth->fetchrow(); 87 return (undef,$DBI::errstr) if ($sth->err); 88 89 # If we get here, we should be OK. 90 return ($dbh,"DB connection OK"); 45 91 } # end connectDB 92 93 94 ## IPDB::finish() 95 # Cleans up after database handles and so on. 96 # Requires a database handle 97 sub finish { 98 my $dbh = $_[0]; 99 $dbh->disconnect; 100 } # end finish 101 46 102 47 103 # Quick check to see if the db is responding. A full integrity … … 69 125 70 126 71 # 127 ## IPDB::allocateBlock() 72 128 # Does all of the magic of actually allocating a netblock 73 sub allocateBlock($) { 74 } 75 76 77 # mailNotify() 129 # Requires database handle, block to allocate, custid, type, city, 130 # description, notes, circuit ID, block to allocate from, 131 # Returns a success code and optional error message. 132 sub allocateBlock { 133 my ($dbh,undef,undef,$custid,$type,$city,$desc,$notes,$circid) = @_; 134 135 my $cidr = new NetAddr::IP $_[1]; 136 my $alloc_from = new NetAddr::IP $_[2]; 137 my $sth; 138 139 # Enable transactions and error handling 140 local $dbh->{AutoCommit} = 0; # These need to be local so we don't 141 local $dbh->{RaiseError} = 1; # step on our toes by accident. 142 143 if ($type =~ /^[cdsmw]i$/) { 144 eval { 145 # We'll just have to put up with the oddities caused by SQL (un)sort order 146 $sth = $dbh->prepare("select * from poolips where pool='$alloc_from'". 147 " and available='y' order by ip"); 148 $sth->execute; 149 150 # update poolips set custid='$custid',city='$city',available='n', 151 # description='$desc',notes='$notes',circuitid='$circid' 152 # where ip=(select ip from poolips where pool='$alloc_from' 153 # and available='y' order by ip limit 1); 154 ##err Need better handling here; what if there's no free IPs when this sub gets called? 155 my @data = $sth->fetchrow_array; 156 my $cidr = $data[1]; 157 158 $sth = $dbh->prepare("update poolips set custid='$custid',". 159 "city='$city',available='n',description='$desc',notes='$notes'". 160 "circuitid='$circid'". 161 " where ip='$cidr'"); 162 $sth->execute; 163 ##err handle the error 164 }; 165 if ($@) { 166 # failure 167 } else { 168 # success 169 } 170 171 } else { # end IP-from-pool allocation 172 # Set $cidr here as it may not be a valid IP address elsewhere. 173 # my $cidr = new NetAddr::IP $webvar{fullcidr}; 174 175 if ($cidr == $alloc_from) { 176 # Easiest case- insert in one table, delete in the other, and go home. More or less. 177 # insert into allocations values (cidr,custid,type,city,desc) and 178 # delete from freeblocks where cidr='cidr' 179 # For data safety on non-transaction DBs, we delete first. 180 181 eval { 182 if ($type eq 'rr') { 183 $sth = $dbh->prepare("update freeblocks set routed='y',city='$city'". 184 " where cidr='$cidr'"); 185 $sth->execute; 186 $sth = $dbh->prepare("insert into routed values ('$cidr',". 187 $cidr->masklen.",'$city')"); 188 $sth->execute; 189 } else { 190 # common stuff for end-use, dialup, dynDSL, pools, etc, etc. 191 ##err How to handle pools? 192 ##workhere 193 #print "IPDB.pm: $cidr\n"; 194 $sth = $dbh->prepare("delete from freeblocks where cidr='$cidr'"); 195 $sth->execute; 196 197 $sth = $dbh->prepare("insert into allocations values ('$cidr',". 198 "'$custid','$type','$city','$desc','$notes',". 199 $cidr->masklen.",'$circid')"); 200 $sth->execute; 201 ## if $type =~ /^[cdsmw]p$/ initpool($dbh,$cidr,$type) 202 } # routing vs non-routing netblock 203 $dbh->commit; 204 }; # end of eval 205 ##err 206 if ($@) { 207 eval { $dbh->rollback; }; 208 return (2,$@); 209 } else { 210 ## do we return here or ? 211 return (1,"OK"); 212 # Success 213 } # error handler 214 215 } else { # cidr != alloc_from 216 217 # Hard case. Allocation is smaller than free block. 218 my $wantmaskbits = $cidr->masklen; 219 my $maskbits = $alloc_from->masklen; 220 221 my @newfreeblocks; # Holds free blocks generated from splitting the source freeblock. 222 223 # This determines which blocks will be left "free" after allocation. We take the 224 # block we're allocating from, and split it in half. We see which half the wanted 225 # block is in, and repeat until the wanted block is equal to one of the halves. 226 my $i=0; 227 my $tmp_from = $alloc_from; # So we don't munge $alloc_from 228 while ($maskbits++ < $wantmaskbits) { 229 my @subblocks = $tmp_from->split($maskbits); 230 $newfreeblocks[$i++] = (($cidr->within($subblocks[0])) ? $subblocks[1] : $subblocks[0]); 231 $tmp_from = ( ($cidr->within($subblocks[0])) ? $subblocks[0] : $subblocks[1] ); 232 } # while 233 234 # Begin SQL transaction block 235 eval { 236 # Delete old freeblocks entry 237 $sth = $dbh->prepare("delete from freeblocks where cidr='$alloc_from'"); 238 $sth->execute(); 239 240 # now we have to do some magic for routing blocks 241 if ($type eq 'rr') { 242 # Insert the new freeblocks entries 243 # Note that non-routed blocks are assigned to <NULL> 244 $sth = $dbh->prepare("insert into freeblocks values (?, ?, '<NULL>','n')"); 245 foreach my $block (@newfreeblocks) { 246 $sth->execute("$block", $block->masklen); 247 } 248 # Insert the entry in the routed table 249 $sth = $dbh->prepare("insert into routed values ('$cidr',". 250 $cidr->masklen.",'$city')"); 251 $sth->execute; 252 # Insert the (almost) same entry in the freeblocks table 253 $sth = $dbh->prepare("insert into freeblocks values ('$cidr',". 254 $cidr->masklen.",'$city','y')"); 255 $sth->execute; 256 257 } else { # done with alloctype == rr 258 259 # Insert the new freeblocks entries 260 $sth = $dbh->prepare("insert into freeblocks values (?, ?, ". 261 "(select city from routed where cidr >>= '$cidr'),'y')"); 262 foreach my $block (@newfreeblocks) { 263 $sth->execute("$block", $block->masklen); 264 } 265 # Insert the allocations entry 266 $sth = $dbh->prepare("insert into allocations values ('$cidr',". 267 "'$custid','$type','$city','$desc','$notes',".$cidr->masklen. 268 ",'$circid')"); 269 $sth->execute; 270 ##err do we initPool here, or force the caller to do it? 271 # Flexibility says we let the caller do it, to allow more options. 272 } # done with netblock alloctype != rr 273 $dbh->commit; 274 }; # end eval 275 if ($@) { 276 eval { $dbh->rollback; }; 277 return (2,$@); 278 } else { 279 ##err 280 return (1,"OK"); 281 } 282 283 } # end fullcidr != alloc_from 284 285 } # end static-IP vs netblock allocation 286 287 } # end allocateBlock() 288 289 290 ## IPDB::initPool() 291 # Initializes a pool 292 # Requires a database handle, the pool CIDR, type, city, and a parameter 293 # indicating whether the pool should allow allocation of literally every 294 # IP, or if it should reserve network/gateway/broadcast IPs 295 sub initPool { 296 my ($dbh,undef,$type,$city,$class) = @_; 297 my $pool = new NetAddr::IP $_[1]; 298 299 my $pooltype = ($type =~ /^(.)p$/); 300 my $sth; 301 302 # Enable transactions and error handling 303 local $dbh->{AutoCommit} = 0; # These need to be local so we don't 304 local $dbh->{RaiseError} = 1; # step on our toes by accident. 305 306 # Begin SQL transaction block 307 eval { 308 # have to insert all pool IPs into poolips table as "unallocated". 309 $sth = $dbh->prepare("insert into poolips values ('$pool',". 310 " ?, '6750400', '$city', '$pooltype', 'y', '', '', '')"); 311 my @poolip_list = $pool->hostenum; 312 if ($class) { # (real netblock) 313 for (my $i=1; $i<=$#poolip_list; $i++) { 314 $sth->execute($poolip_list[$i]->addr); 315 } 316 } else { # (DSL-ish block - *all* IPs available 317 $sth->execute($pool->addr); 318 for (my $i=0; $i<=$#poolip_list; $i++) { 319 $sth->execute($poolip_list[$i]->addr); 320 } 321 $pool--; 322 $sth->execute($pool->addr); 323 } 324 $dbh->commit; 325 }; # end eval 326 if ($@) { 327 eval { $dbh->rollback; }; 328 print "$@\n"; 329 return (2,"$@"); 330 } else { 331 ##err 332 return (1,"OK"); 333 } 334 335 } # end initPool() 336 337 338 ## IPDB::mailNotify() 78 339 # Sends notification mail to recipients regarding an IPDB operation 79 340 sub mailNotify ($$$) {
Note:
See TracChangeset
for help on using the changeset viewer.