#!/usr/local/bin/perl

#####################################################################
##
## Rcs_ID="$RCSfile: monitorjb,v $"
## Rcs_ID="$Revision: 1.2 $ $Date: 2000/03/01 23:33:10 $"
##
#####################################################################

# Script:	monitorLibraryCapacities.pl
# Description:	check each VM pool in TLDs in the Enterprise backup complex for 
#		a pretermined number of empty tapes.
# Parameters:	<-m master> # optional. specify the NBU master for the complex to be examined.
#		<-a address-list> # optional.  specify the email recipients to send the 
#		report to.  If ommitted, output goes to STDOUT.  addresses should be comma
#		delimited.

use Getopt::Std;

$minTapesPerPool = 10 ;			# minimum no. of tapes per VM pool
$scratchPool = "Scratch" ;		# special pool
$addressee = "";			# email recipient list (comma delimit the addresses)
$mailSubject = "" ; # mail subject
$master = `hostname`;				# NBU master server for the complex
chomp $master ;
$totalTapesRequired = 0;		# total number of tapes to be added to the libraries
					# in the NBU complex.
$skipLibrary = "bogus";			# this library requires no tapes
%skipPools = 	(
	OldElvisTapes => 1
		) ;

&getParms; 
&getRobots;
&unassignedTapeCountByRobot;
&getFreeSlotsInRobots;
&checkPoolsInRobots; 
&mailReport if ($addressee ne "");

# collect commandline parameters:
sub getParms { 
	getopt('amfs', \%options); 
	if(defined($options{'s'})) {
		$scratchPool = $options{'s'}; 
		}
	if(defined($options{'f'})) {
		$minTapesPerPool = $options{'f'}; 
		}
	if(defined($options{'m'})) {
		$master = $options{'m'}; 
		}
	$addressee = $options{'a'} if (defined($options{'a'}));
	if($addressee eq "") { 
		$FD = STDOUT; 
		}
	else	{
		open(EMAIL, ">/tmp/monitorLibraryCapacity.mail") || die "$0: $!";
		$FD = EMAIL; 
		}
	}

# determine the robot hosts in the NBU complex
sub getRobots { 
	open (ROBOTLIST, "/usr/openv/netbackup/bin/admincmd/bpstulist -M $master -l |")
  		|| die "$0: $!";
	while(<ROBOTLIST>) {
        	($stuname,$fake,$robothost,$fake,$robotnum) = split('\s+', $_) ;
		next if ($robotnum < 0) ;
		$robotHostsByNum{$robotnum} = $robothost if (!defined ($robotHostsByNum{$robotnum}));
		$stuNames{$robotnum} = $stuname;
		$available{$robotnum}->{$scratchPool} = 0;
		}
	close(ROBOTLIST);
	}

# inventory each unassigned tapes in each library in the NBU complex
sub unassignedTapeCountByRobot { 
	foreach $robotnum (keys %robotHostsByNum) {
		#print "$robotnum \n" ;
		open(VOL_LIST, "/usr/openv/volmgr/bin/vmquery -M $master -rn $robotnum -bx |") 
 			|| die "$0: $!";
		while(<VOL_LIST>)
			{
			next if ($. < 4);
			($media_id,$media_type,$robot_type,$tape_robotnum,$robot_slot,$side,$volume_group,$optical_partner,$mounts,$last_mount_date,$last_mount_time,$assigned_ddate,$assigned_time,$pool) = split('\s+', $_);
			next if ($robot_number eq '-'); 
			next if ($pool eq "None");
			next if (!defined($robotHostsByNum{$tape_robotnum}));
			$pools{$pool} = 1;
			if($assigned_ddate =~ /---/) { 
				#print "Available: $_\n";
				++$available{$tape_robotnum}->{$pool}; 
				}
			else
				{
				# might want this later .... 
				#print "Used: $_\n";
				++$used{$tape_robotnum}->{$pool};
				}
			}
		close(VOL_LIST);
		}
	}

# check capacity of VM pools in each tape library in the NBU complex
sub checkPoolsInRobots { 
	foreach $robotnum (keys %robotHostsByNum) {
		$scratchCount = $available{$robotnum}->{$scratchPool};
		$tapesNeeded = 0;
		$swapCount = 0;
		$addTapeCount = 0;
		foreach $pool (keys %pools) { 
			next if (defined ($skipPools{$pool})) ;
			next if (!defined($used{$robotnum}->{$pool}));
			if($available{$robotnum}->{$pool} < $minTapesPerPool) {
				$tapesforthispool=($minTapesPerPool - $available{$robotnum}->{$pool});
				$tapesNeeded += $tapesforthispool ;
				#print "Pool $pool needs $tapesforthispool tapes.\n" ;
				}
			}
		$tapesNeeded = 0 if($robotHostsByNum{$robotnum} eq $skipLibrary);
		$addTapeCount = ($tapesNeeded - $scratchCount); 
		$addTapeCount = 0 if ($addTapeCount < 0);
		$totalTapesRequired += $addTapeCount;
		$df = $freeSlots{$robotnum} - $addTapeCount; 
		$swapCount = -$df if ($df < 0);
		if ( $addTapeCount == 0 ) {
			print $FD "INFO: Robot $robotnum on $robotHostsByNum{$robotnum} has at least $minTapesPerPool free tapes per pool.\n";
		}
		else {
			if ( $freeSlots{$robotnum} >= $addTapeCount ) {
			print $FD "WARNING: Robot $robotnum on $robotHostsByNum{$robotnum} needs $addTapeCount blank tapes. It has $freeSlots{$robotnum} free slots, so you will not need to take any tapes out.\n";
			}
			else {
			print $FD "WARNING: Robot $robotnum on $robotHostsByNum{$robotnum} needs $addTapeCount blank tapes. Since it only has $freeSlots{$robotnum} free slots, you will need to take out $swapCount tapes to make room for the blank tapes.\n";
			}
		}
		}
	}

# check free slots in each tape library in the NBU complex
sub getFreeSlotsInRobots { 
	foreach $robotnum (keys %robotHostsByNum) { 
		$freeSlots{$robotnum} = 0;
		}
	foreach $robotnum (keys %robotHostsByNum) {
		open(SLOT_LIST, "/usr/openv/volmgr/bin/vmcheckxxx -rt tld -rn $robotnum -rh $robotHostsByNum{$robotnum} -list 2>&1|") || die "$0: $!";
		while(<SLOT_LIST>) { 
			if (m/robot inventory failed/) { 
				delete $freeSlots{$robotnum};
				delete $robotHostsByNum{$robotnum};
				break;
				}
			if (m/EMPTY/) {
			#print "$_\n" ;
			++$freeSlots{$robotnum} 
			}
			}
		close(SLOT_LIST);
		}
	}

# given a Unix epoch time, return a string representation
sub stringDate {
        my $ut = shift;
        ($sec,$min,$hour,$mday,$mon,$year,$wday,$startPos,$isdst) = localtime($ut);
        ++$mon;
	$year = 0 if ($year > 99); 
        return sprintf("%02d/%02d/%02d", $mon, $mday, $year);
        }

# email a summary report of tape requirements for libraries in an NBU complex
sub mailReport {
	close(EMAIL); 
	if ( $addressee eq "TNGALERT" ) {
		open(EMAIL, "/tmp/monitorLibraryCapacity.mail") || die "$0: $!" ;
	 while (<EMAIL>) {
			chomp $_ ;
			if ( $_ =~ /WARNING:/ ) {
				s/WARNING: // ;
				system("/opt/tng/tng_custom/tools/sendTrap.ksh NETBACKUP CRIT BOTH \"$_\"");
			}
			else {
				s/INFO: // ;
				system("/opt/tng/tng_custom/tools/sendTrap.ksh NETBACKUP INFO MAIL \"$_\"");
			}
		}
	}
	else {
		if($totalTapesRequired > 0) { 
			$mailSubject = "URGENT: TAPES NEEDED in the ${master} Tape Librarie(s)";
		}
		else	{
			$mailSubject = "No Tapes Needed in the ${master} Tape Librarie(s)";
		}
		system("/usr/bin/mailx -s '$mailSubject' $addressee < /tmp/monitorLibraryCapacity.mail");
	die "$0: $!" if($? != 0);
	}
	}	
