Changeset 29425
- Timestamp:
- Oct 14, 2010, 5:13:27 PM (16 years ago)
- File:
-
- 1 edited
-
trunk/Nebulous-Server/bin/neb-admin (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Nebulous-Server/bin/neb-admin
r24632 r29425 27 27 $limit, 28 28 $pending, 29 $balance, 30 $balance_N_sources, 31 $balance_M_destinations, 29 32 $removal, 30 33 $verbose, … … 42 45 'pass|p=s' => \$dbpass, 43 46 'pendingreplicate|r' => \$pending, 44 'pendingremoval' => \$removal, 47 'pendingbalance|b' => \$balance, 48 'balancesources|N=s' => \$balance_N_sources, 49 'balancedestinations|M=s' => \$balance_M_destinations, 50 # 'pendingremoval' => \$removal, 45 51 'so_id_start=i' => \$so_id_start, 46 52 'so_id_range=i' => \$so_id_range, … … 54 60 pod2usage( -msg => "--limit is meaningless without --pendingreplicate", 55 61 -exitval => 2 ) 56 if defined $limit and not defined $pending;62 if defined $limit and not (defined $pending or defined $balance); 57 63 pod2usage( -msg => "no operation specified", -exitval => 2 ) 58 unless defined $pending or defined $removal; 59 64 unless defined $pending or defined $balance; 65 pod2usage( -msg => "--pendingbalance needs --balancesources and --balancedestinations options", 66 -exitval => 2) 67 if defined $balance and not (defined $balance_N_sources or defined $balance_M_destinations); 60 68 # set default limit to 5 61 69 $limit ||= 5; … … 84 92 } elsif ($removal) { 85 93 removal(); 94 } elsif ($balance) { 95 balance(); 86 96 } else { 87 97 die "THIS SHOULD NOT HAPPEN"; … … 137 147 AND so.so_id < $so_id_end 138 148 GROUP BY so_id 139 HAVING available_instances < instances OR instances <copies149 HAVING available_instances != instances OR instances != copies 140 150 LIMIT $limit" 141 151 ); 152 142 153 $query->execute; 143 144 # $dbh->do("DROP TABLE IF EXISTS mymountedvol");145 154 146 155 my @rows; … … 168 177 my $vol_name = $obj->{volume_name}; 169 178 my $vol_host = $obj->{volume_host}; 170 my $available = $obj->{available_instances} || 0;179 my $available = $obj->{available_instances} || 0; 171 180 my $need_recovery = $obj->{need_recovery}; 172 181 my $recoverable = $obj->{recoverable}; … … 189 198 190 199 my $need = $copies - $available; 191 $need = 0 if $need < 0;192 200 my $cmd = 'neb-stat'; 201 # $need = 0 if $need < 0; 193 202 next unless $need; 203 204 if ($need > 0) { 205 $cmd = 'neb-replicate'; 206 } 207 elsif ($need < 0) { 208 $cmd = 'neb-cull'; 209 } 194 210 195 211 my %md = ( 196 212 key => $key, 213 command => $cmd, 197 214 need_copies => $need, 198 215 volume_name => $vol_name, 199 216 volume_host => $vol_host, 217 218 # has => $has, 219 available => $available, 220 xattr_copies => $copies, 221 # recoverable => $recoverable, 222 # need_recovery => $need_recovery, 223 200 224 ); 201 225 # print "$key $cmd $need $vol_name $vol_host\n"; 202 226 print_metadata("replicatePending", \%md); 227 print "\n"; 228 } 229 230 # use a different exit status if we hit the limit (likely more files pending) 231 if ($Npending == $limit) { 232 exit 1; 233 } 234 exit 0; 235 } 236 237 sub balance 238 { 239 # so_id, ext_id, instances, available_instances, need_recovery, recoverable 240 # XXX don't remove the temp table code -- testing w/o it 241 # $dbh->do("CREATE TEMPORARY TABLE mymountedvol LIKE mountedvol"); 242 # $dbh->do("INSERT INTO mymountedvol SELECT * FROM mountedvol"); 243 244 if (not defined $so_id_start) { $so_id_start = 0; } 245 if (not defined $so_id_range) { $so_id_range = 100000; } 246 my $so_id_end = $so_id_start + $so_id_range; 247 248 # XXX check if so_id_start is beyond MAX(so_id): if so, exit with exit status 10 249 { 250 my $query = $dbh->prepare("SELECT MAX(so_id) from storage_object"); 251 $query->execute; 252 my $answer = $query->fetchrow_arrayref; 253 my $max_so_id = $$answer[0]; 254 $query->finish; 255 256 if ($so_id_start > $max_so_id) { 257 print STDERR "at end of so_id range, reset please\n"; 258 exit 10; 259 } 260 } 261 262 # Calculate the average disk usage 263 my $average = 0; 264 my $avg_query = $dbh->prepare( 265 "select sum(used)/sum(total) AS average from mountedvol WHERE available = 1 AND allocate = 1" 266 ); 267 $avg_query->execute(); 268 while (my $row = $avg_query->fetchrow_hashref) { 269 $average = $row->{average}; 270 } 271 $avg_query->finish; 272 print STDERR "average: $average\n"; 273 if ($average == 0) { 274 exit 1; 275 } 276 # I truly am sorry for this statement. 277 my $query = $dbh->prepare( 278 " 279 SELECT * FROM ( 280 -- U Randomize the list of all possible source/destination matches,then group by so_id to select one at random 281 SELECT T.*,volume.cab_id AS source_cab_id,volume.name AS source_name,volume.host AS source_host, 282 destination.vol_id AS destination_vol_id,destination.cab_id AS destination_cab_id, 283 destination.name AS destination_name,destination.host AS destination_host FROM ( 284 -- V Ensure that the copy we found on the source volume is the second copy instance 285 SELECT K.vol_id AS here,K.ins_id,K.so_id,ext_id,value AS user_copies,MAXins_id,instance.vol_id AS there FROM ( 286 -- W Determine what the second copy instance is 287 SELECT V.*,MAX(instance.ins_id) AS MAXins_id FROM ( 288 -- X Determine which hosts have instances of an object 289 SELECT vol_id,ins_id,so_id,ext_id,value FROM 290 storage_object JOIN storage_object_xattr USING(so_id) JOIN instance USING(so_id) 291 WHERE vol_id IN ( 292 -- Y Extra select for debugging purposes 293 SELECT vol_id FROM ( 294 -- Z Ran hosts by R (need to be a source) and return top N 295 SELECT mountedvol.vol_id,mountedvol.name,mountedvol.available,mountedvol.allocate,total,used, 296 (used / total) AS D,total * ((used / total) - $average ) AS R, -- average 297 cab_id FROM 298 mountedvol JOIN volume USING(vol_id) 299 WHERE mountedvol.available = 1 AND mountedvol.allocate = 1 300 ORDER BY R DESC LIMIT $balance_N_sources -- N 301 ) AS ranked_sources 302 -- Z End 303 ) 304 -- Y End 305 AND name = 'user.copies' AND value >= 2 306 AND so_id >= $so_id_start -- so_id_start 307 AND so_id < $so_id_end -- so_id_end 308 LIMIT $limit -- limit 309 ) AS V -- volumes that host a copy 310 -- X End 311 LEFT OUTER JOIN instance USING(so_id) GROUP BY so_id 312 ) AS K -- copies that are the second copy 313 -- W End 314 JOIN instance ON MAXins_id = instance.ins_id GROUP BY so_id 315 ) AS T -- matched copies that I know the second copy is on my source volume 316 -- V End 317 JOIN volume on T.here = volume.vol_id RIGHT JOIN ( 318 -- Y2 Chose a random destination from the list 319 SELECT vol_id,cab_id,name,host FROM ( 320 -- Z2 Reverse rank hosts by R and return top M 321 SELECT mountedvol.vol_id,mountedvol.name,mountedvol.host,mountedvol.available,mountedvol.allocate,total,used, 322 (used / total) AS D,total * ((used / total) - $average ) AS R, -- average 323 cab_id FROM 324 mountedvol JOIN volume USING(vol_id) 325 WHERE mountedvol.available = 1 AND mountedvol.allocate = 1 326 ORDER BY R ASC LIMIT $balance_M_destinations -- M 327 ) AS ranked_destinations 328 -- Z2 End 329 ORDER BY RAND() 330 ) AS destination 331 -- Y2 End 332 ON destination.cab_id != volume.cab_id 333 WHERE here = there 334 ORDER BY RAND() 335 ) AS results 336 -- U End 337 GROUP BY so_id 338 " ); 339 340 $query->execute(); 341 342 343 344 my @rows; 345 while (my $row = $query->fetchrow_hashref) { 346 push @rows, $row; 347 } 348 $query->finish; 349 350 print STDERR "No rows found\n" unless scalar @rows; 351 exit unless scalar @rows; 352 353 # compare number of responses to limit below 354 my $Npending = @rows; 355 356 print "balancePending MULTI\n\n"; 357 358 foreach my $obj (@rows) { 359 if (defined $verbose) { 360 require Data::Dumper; 361 print Data::Dumper::Dumper($obj); 362 } 363 364 365 my $here = $obj->{here}; 366 my $there = $obj->{there}; 367 my $ins_id = $obj->{ins_id}; 368 my $max_ins_id = $obj->{MAXins_id}; 369 370 my $so_id = $obj->{so_id}; 371 my $key = $obj->{ext_id}; 372 my $copies = $obj->{user_copies}; 373 374 my $source_vol_id = $obj->{here}; 375 my $source_cab_id = $obj->{source_cab_id}; 376 my $source_name = $obj->{source_name}; 377 my $source_host = $obj->{source_host}; 378 379 my $destination_vol_id = $obj->{destination_vol_id}; 380 my $destination_cab_id = $obj->{destination_cab_id}; 381 my $destination_name = $obj->{destination_name}; 382 my $destination_host = $obj->{destination_host}; 383 384 unless ($here == $there) { next; } 385 unless ($ins_id == $max_ins_id) { next; } 386 unless ($source_cab_id != $destination_cab_id) { next; } 387 388 my %md = ( 389 key => $key, 390 copies => $copies, 391 so_id => $so_id, 392 source_vol_id => $source_vol_id, 393 source_cab_id => $source_cab_id, 394 source_name => $source_name, 395 source_host => $source_host, 396 destination_vol_id => $destination_vol_id, 397 destination_cab_id => $destination_cab_id, 398 destination_name => $destination_name, 399 destination_host => $destination_host, 400 # key => $key, 401 # command => $cmd, 402 # need_copies => $need, 403 # volume_name => $vol_name, 404 # volume_host => $vol_host, 405 406 # # has => $has, 407 # available => $available, 408 # xattr_copies => $copies, 409 # # recoverable => $recoverable, 410 # # need_recovery => $need_recovery, 411 412 ); 413 # print "$key $cmd $need $vol_name $vol_host\n"; 414 print_metadata("balancePending", \%md); 203 415 print "\n"; 204 416 }
Note:
See TracChangeset
for help on using the changeset viewer.
