#!/usr/bin/perl # # MoveCeiling v0.2 written 061206:1122 by BJP # # MoveCeiling will watch and automatically increase the size of an AIX filesystem # given user-specified parameters. # # Usage: moveceiling # Example: moveceiling 500 /tmp 64 30 3200 5 foo@bar.com # English: Keep 500MB free in /tmp. If you have to add space, add it in 64MB chunks. Check out the situation every 30 seconds. Preserve 3200MB in the volume group. Remind me every 5 times you have to increase space, and send that reminder to foo@bar.com # use Mail::Sendmail; $ceilingSize=$ARGV[0]; $targetFS=$ARGV[1]; $incrementSize=$ARGV[2]; $sleepTime=$ARGV[3]; $preserveAmount=$ARGV[4]; $notifyCounter=$ARGV[5]; $mailRecipient=$ARGV[6]; $mailSender=$ENV{"USER"}."\@"."localhost"; if ($#ARGV!=6) { showUsage(); exit(); } spinUpRoutine(); mainRoutine(); spinDownRoutine(); sub showUsage() { print "\n MoveCeiling's job is to watch a filesystem, and increase it's size if the\n"; print " amount of free space in that filesystem falls below threshold. MoveCeiling\n"; print " is much smarter than it used to be, but you should still use it with caution. \n"; print "\n"; print " Usage: moveceiling \n"; print " Example: moveceiling 500 /tmp 64 30 5 foo\@bar.com\n"; print " In English: Every 30 seconds, check to see if /tmp has at least 500MB free. \n"; print " If it sinks below 500MB, add another 64MB. For every 5 times I \n"; print " add more space, i'll send a status message to foo\@bar.com.\n"; print "\n\n"; exit(); } sub spinUpRoutine() { print "\nMoveCeiling: I will make sure $targetFS has at least $ceilingSize MB free."; print "\nMoveCeiling: If I have to increase it's size, I will do so in $incrementSize MB increments."; print "\nMoveCeiling: Every $notifyCounter times I do so, i'll drop a note to $mailRecipient."; print "\nMoveCeiling: I'll stop adding storage if the volume group has less than $preserveAmount MB remaining."; print "\nMoveCeiling: Starting up..\n"; ## Check to see if the filesystem actually exists... @dfContents=split(/\s+/,`df -m | grep " $targetFS\$"`); if(length($targetFS)==length($dfContents[6])) { print "MoveCeiling: Examining $dfContents[6]..\n"; } else { print "MoveCeiling: Uh-oh.. Can't find the filesystem you specified ($targetFS)..! Exiting.\n\n"; exit(); } ## So far so good. Pull up the VG info for this filesystem.. $dfContents[0]=~/\/dev\//; $targetLV=$'; @lslvContents=split(/\s+/,`lslv $targetLV|head -n1` ); $targetVG=$lslvContents[5]; print "MoveCeiling: $targetFS belongs to logical volume $targetLV inside $targetVG.\n"; @lsvgDump=split(/\s+/,`lsvg -L $targetVG | head -n4 | tail -n1`); $lsvgDump[6]=~/\(/; $targetVGSpaceRemaining=$'; print "MoveCeiling: $targetVG has $targetVGSpaceRemaining MB remaining, of which $preserveAmount MB will be preserved.\n\n"; } sub mainRoutine() { while(true) { @dfContents=split(/\s+/,`df -m | grep " $targetFS\$"`); chomp($dateString=`date`); print "MoveCeiling: $dfContents[2] MB remaining in $targetFS as of $dateString.\n"; @lsvgDump=split(/\s+/,`lsvg -L $targetVG | head -n4 | tail -n1`); $lsvgDump[6]=~/\(/; $targetVGSpaceRemaining=$'; if($dfContents[2] < $ceilingSize) # Tricky logic time.. { if($targetVGSpaceRemaining >= ($preserveAmount+$incrementSize)) { print "MoveCeiling: Less than $ceilingSize MB remaining! Adding $incrementSize MB to $targetFS..\n"; system("echo `date` -- MoveCeiling: Less than $ceilingSize MB remaining! Adding $incrementSize MB to $targetFS.. >>/tmp/moveceiling.log"); `chfs -a size=+"$incrementSize"M $targetFS`; $incrementCounter++; if($incrementCounter==$notifyCounter) { sendNotification(); $incrementCounter=0; } } else { system("echo `date` -- MoveCeiling: Preserve limit reached. Committing suicide. $targetFS last seen with $dfContents[2] MB free, $targetVGSpaceRemaiing MB remaining in $targetVG. >>/tmp/moveceiling.log"); print "MoveCeiling: Increasing $targetFS by $incrementSize MB would eat into the preserved area! \n"; print "MoveCeiling: Preparing suicide note to $mailRecipient..\n"; sendSuicideNote(); print "MoveCeiling: My hands are tied! I'm sorry!\n"; spinDownRoutine(); exit(); } } else { print "MoveCeiling: More than $ceilingSize MB remaining..No increase needed.\n"; } print "MoveCeiling: $targetVGSpaceRemaining MB remaining in $targetVG. Sleeping for $sleepTime seconds..\n\n"; sleep($sleepTime); } } sub sendSuicideNote() { %mail=( To => $mailRecipient, From => $mailSender, Subject => "MoveCeiling Suicide Notice", Message => "Preserve limit reached -- Data loss may be imminent. $targetFS last seen with $dfContents[2] MB free, $targetVGSpaceRemaining MB remaining in $targetVG. ); sendmail(%mail); print "MoveCeiling: Suicide note sent.\n"; } sub sendNotification() { print "MoveCeiling: Sending a friendly reminder to $mailRecipient..\n"; %mail=( To => $mailRecipient, From => $mailSender, Subject => "MoveCeiling Update", Message => "$targetFS still growing. Now at $dfContents[2] MB in size with $targetVGSpaceRemaining MB remaining in $targetVG." ); sendmail(%mail); print "MoveCeiling: Mail sent.\n"; } sub spinDownRoutine() { print "MoveCeiling: Spinning down..\n\n"; }