#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# perf720 src/perf/pmaix/usr/bin/pmcfg/crosslpar 1.5 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2012,2013 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
	
	## Check for RBAC authorization
	$viosfile="/usr/ios/cli/ioscli";
	if( -e ${viosfile} ) {
		# If its vios, check for vios authorization
		`/usr/bin/ckauth vios.system.perfmgr.config`;
		if( $? ) {
			exit (1);
		}
	} else {
		# If its aix, check for aix authorization
		`/usr/bin/ckauth aix.system.perfmgr.config`;
		if( $? ) {
			exit (1);
		}
	}
	
	##-- Output file name to be provided as the argument to this script
	if( $#ARGV < 0 ) {
		print "No output file provided. Please pass the output file name as the argument to this script\n";
		exit(1);
	}
	
	##-- Store filename provided as argument in OUTFILE variable
	my $OUTFILE = $ARGV[0];
	
	##-- Store config file pmconf path in PMCONF variable
	my $PMCONF="/var/perf/pm/config/pmconf";
	
	##-- Set initial value to 0, to check if HMC has idle_cycle data
	my $with_idle_cycle = 0;
	
	##-- LOGFILE contains the path for the pmcfg.log file and open the file to append the logs
	my $LOGFILE = "/var/perf/pm/daily/pmcfg.log";
	open LOGFILE, ">>$LOGFILE";
	
	##-- Getting the file name of this script
	my $ScriptName = `/usr/bin/basename $0 2>/dev/null`;
	chomp($ScriptName);
	
	##-- using temporary files which will be deleted at the end of the script
	my $tmpfile = "/tmp/${ScriptName}.$$";
	my $tmpfile1 = "/tmp/${ScriptName}_1.$$";
	
	##-- Temporary output file opened to store the output of the script
	my $TMPOUTFILE = "/tmp/${ScriptName}_out.$$";
	open TMPOUTFILE, ">$TMPOUTFILE";
	
	my $tmpval;
	my $mach;
	
	##-- Check to see if HMC is supported, if pmconf doesn't have HMC_Supported:, then update the pmconf file with HMC_Supported
	`/usr/bin/grep "HMC_Supported:" ${PMCONF}`;
	if( $? != 0 ) {
		`/usr/bin/cat ${PMCONF} > $tmpfile1`;
		`echo >> $tmpfile1`;
		`echo '# Is HMC Supported' >> $tmpfile1`;
		`echo "HMC_Supported:" >> $tmpfile1`;
		`echo >> $tmpfile1`;
		`/usr/bin/cp $tmpfile1 ${PMCONF}`;
	}
	
	##-- Get the value of HMC_Supported from pmconf
	my $hmc_sup=`/usr/bin/grep "HMC_Supported:" ${PMCONF} | /usr/bin/cut -d ':' -f 2`;
	chomp($hmc_sup);
	
	my $hr=`/usr/bin/date +'%H'` + 0;
	my $min=`/usr/bin/date +'%M'` + 0;
	
	##-- If HMC is not supported, and if script is running for second time or more in a day, exit
	if( $hmc_sup ne "" && $hmc_sup == 0 ) {
		if( !($hr == 0 && $min < 14) ) {
			exit(0);
		}
	}
	
	##--Clearing the crosslpar logs from log file
	`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: " > ${tmpfile1} 2>/dev/null`;
	`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
	
	##-- Function to write the logs passed to as string argument with time stamp and script name to the pmcfg.log file
	sub WriteLog
	{
		my $msg = shift;
		my $timestamp = `/usr/bin/date +'%T'`;	
		chomp($timestamp);
		print LOGFILE "$timestamp:$ScriptName: $msg";
	}
	
	##-- Function to exit and cleanup temp files, normal exit if exitcode is 0, else exit with errors
	sub Grace_Exit
	{
		my $exitcode = shift;
		
		##-- If the tmpfile exist, remove the tmpfile
		if( -e ${tmpfile} ) {
			$retval="";
			$retval=`/usr/bin/rm ${tmpfile} 2>&1`;
			if( $? ) {
				WriteLog "Error: ${retval}";
				WriteLog "Unable to delete temporary file ${tmpfile}!\n";
			}
		}
		
		##-- If tmpfile1 exist, remove tmpfile1
		if( -e ${tmpfile1} ) {
			$retval="";
			$retval=`/usr/bin/rm ${tmpfile1} 2>&1`;
			if( $? ) {
				WriteLog "Error: ${retval}";
				WriteLog "Unable to delete temporary file ${tmpfile1}!\n";
			}
		}
		
		##-- If normal exit
		if( $exitcode == 0 ) {
			##-- Copy the output stored in temp output file to actual output file
			$retval="";
			$retval=`/usr/bin/cp ${TMPOUTFILE} ${OUTFILE} 2>&1`;
			if( $? ) {
				WriteLog "Error: ${retval}";
				WriteLog "Unable to write to output file ${OUTFILE}\n";
			}
		}
		
		##-- Close TEMPOUTFILE
		close TMPOUTFILE;
		
		##-- Remove temporary output file
		$retval="";
		$retval=`/usr/bin/rm ${TMPOUTFILE} 2>&1`;
		if( $? ) {
			WriteLog "Error: ${retval}";
			WriteLog "Unable to delete temp output file ${TMPOUTFILE}\n";
		}
		
		##-- Close LOGFILE
		close LOGFILE;
		
		##-- Exit with exitcode
		exit($exitcode);
	}
	
	##-- Check to see if the /var filesystem has enough size to store the PM Oputput data
	##-- Get the filesystem name
	my $filesys=`/usr/bin/df -m /var/perf/pm/daily | /usr/bin/grep -iv free | /usr/bin/awk '{print \$7}' 2>/dev/null`;
	chomp($filesys);
	
	##-- Get the free space available in the filesystem
	my $freespace=`/usr/bin/df -m /var/perf/pm/daily | /usr/bin/grep -iv free | /usr/bin/awk '{print \$3}' 2>/dev/null`;
	chomp($freespace);
	
	##-- If the freespace is less than 60 MB, exit with the error msg in log file
	if( $freespace < 60 ) {
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Filesystem -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		
		##-- If free space in the filesystem is less than 60 MB, quit.
		WriteLog "Filesystem - Not Enough Free Space in FileSystem $filesys!\n";
		Grace_Exit 1;
	}
	
	##-- Check to see if the /tmp filesystem has enough size to store the temporary files
	##-- Get the filesystem name
	$filesys=`/usr/bin/df -m /tmp | /usr/bin/grep -iv free | /usr/bin/awk '{print \$7}' 2>/dev/null`;
	chomp($filesys);
	
	##-- Get the free space available in the filesystem
	$freespace=`/usr/bin/df -m /tmp | /usr/bin/grep -iv free | /usr/bin/awk '{print \$3}' 2>/dev/null`;
	chomp($freespace);
	
	##-- If the freespace is less than 60 MB, exit with the error msg in log file
	if( $freespace < 60 ) {
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Filesystem -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		
		##-- If free space in the filesystem is less than 60 MB, quit.
		WriteLog "Filesystem - Not Enough Free Space in FileSystem $filesys!\n";
		Grace_Exit 1;
	}
	
	##-- Serial number of the machine
	my $Serial_Num=`/usr/bin/uname -u | /usr/bin/cut -d "," -f 2 | /usr/bin/sed 's/..//' 2>/dev/null`;
	chomp($Serial_Num);
	
	
	##-- variables in temporary file to exchange values between parent and child process
	`echo "child:" > ${tmpfile}`;
	`echo "HmcVer:" >> ${tmpfile}`;
	`echo "HmcRel:" >> ${tmpfile}`;
	`echo "Machine:" >> ${tmpfile}`;
	`echo "AllowPerf:" >> ${tmpfile}`;
	
	##-- Get partition name of the lpar
	$Partition_Name = `/usr/bin/lparstat -i | /usr/bin/grep "Partition Name" | /usr/bin/awk '{print \$4}' 2>/dev/null`;
	chomp($Partition_Name);
	
	##-- Function to remove the crontab entry
	sub RemoveCronEntry
	{
		
		##-- Delete all the entries related to pmcfg_ext -C
		`/usr/bin/crontab -l | /usr/bin/grep "pmcfg_ext -C" >/dev/null 2>&1`;
		if( $? == 0 ) {
			##-- Delete the crontab entry
			`/usr/bin/crontab -l | /usr/bin/grep -v "pmcfg_ext -C" > ${tmpfile1}`;
			
			if( $? != 0 ) {
				WriteLog "Failed to create a temporary crontab file\n";
				return;
			}
			`/usr/bin/crontab ${tmpfile1}`;
			if( $? != 0 ) {
				WriteLog "Failed to update crontab \n";
				return;
			}
		}
	}
	
	##-- Check for Hardware Power Porcessor
	my $Power = `/usr/sbin/prtconf | /usr/bin/grep "Processor Implementation Mode:" | /usr/bin/awk '{print \$5}' 2>/dev/null`;
	chomp($Power);
	
	##-- If power processor is lower than Power 6, exit with error msg in the error log.
	if( $Power < 6 )
	{
		##-- If power processor is lower than Power 6, quit.
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Hardware -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		WriteLog "Hardware - Need Power 6 or Higher Power Processor. Quitting!\n";
		RemoveCronEntry;
		Grace_Exit 1;
	}
	
	# To Check if the lpar is managed by HMC
	#`lsrsrc -l "IBM.MCP" | /usr/bin/grep MNName 2>/dev/null`;
	#if( $? != 0 )
	#{
	#	# If lpar is stand alone and not managed by HMC, quit
	#	print LOGFILE "$ScriptName: This Lpar $Partition_Name is not managed by HMC. Quitting!\n";
	#	Grace_Exit 1;
	#}
	
	
	##-- Check if PM topasrec is enabled, if not, exit
	`/usr/bin/listtrec -P -l local_bin 2>/dev/null`;
	if( $? != 0 )
	{
		##-- If PM topasrec recording is not enabled, quit execution
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Topas -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		
		##-- If PM topasrec recording is not enabled, quit execution
		WriteLog "Topas - PM Recording is not enabled. Quitting!\n";
		Grace_Exit 1;
	}
	
	##-- Check if PM is enabled, if not enabled, exit the script
	`/usr/bin/grep "# Enabled" ${PMCONF} > /dev/null 2>&1`;
	if( $? != 0 )
	{
		##-- If PM Data Transmission is not enabled, quit
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Performance Management -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		WriteLog "Performance Management - PM Data Transmission is not enabled, Quitting!\n";
		Grace_Exit 1;
	}
	
	##-- Get HMC Name and HMC User name from config file pmconf
	$HMC_Name=`/usr/bin/grep Hmc_Name_PM ${PMCONF} | /usr/bin/cut -d ":" -f 2 2>/dev/null`;
	$HMC_User=`/usr/bin/grep Hmc_User_PM ${PMCONF} | /usr/bin/cut -d ":" -f 2 2>/dev/null`;
	chomp($HMC_Name);
	chomp($HMC_User);
	
	##-- Set HMC Version and HMC release validating variables to 0 in the tmpfile, these values are read by child process
	my $HmcVer = 0;
	my $HmcRel = 0;
	`/usr/bin/sed \"s/HmcVer:.*/HmcVer:${HmcVer}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
	`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
	`/usr/bin/sed \"s/HmcRel:.*/HmcRel:${HmcRel}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
	`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
	
	##-- Set child process return code to 0 in tmpfile
	my $inchild = 0;
	`/usr/bin/sed \"s/child:.*/child:${inchild}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
	`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
	
	##-- Check if Password-less ssh is setup from LPar to HMC
	sub Check_Ssh
	{
		##-- Check password-less ssh connection to HMC
		`/usr/bin/ssh -o 'PreferredAuthentications=publickey' -o 'StrictHostKeyChecking=no' -l ${HMC_User} ${HMC_Name} echo 2>/dev/null`;
		
		##-- If password-less ssh connection fails, return to calling function with code 1
		if( $? != 0 )
		{
			##-- If Password-Less authentication is not setup, quit.
			
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Login -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "HMC Login - Failed to login ${HMC_User} to HMC ${HMC_Name}. Password-Less SSH to HMC not setup!\n";
			return -1;
		}
		
		##-- If ssh connection passes, get HMC version
		$HmcVer = `/usr/bin/ssh -l $HMC_User $HMC_Name 'lshmc -V | grep Version | cut -d \":\" -f 2' 2>/dev/null`;
		chomp($HmcVer);
		$HmcVer =~s/"+//g;
		$HmcVer =~s/\s+//g;
		
		##-- Get HMC release
		$HmcRel = `/usr/bin/ssh -l $HMC_User $HMC_Name 'lshmc -V | grep Release | cut -d \":\" -f 2' 2>/dev/null`;
		chomp($HmcRel);
		$HmcRel =~s/"+//g;
		$HmcRel =~s/\s+//g;
		
		my $HMC_FSM = `/usr/bin/ssh -l $HMC_User $HMC_Name 'lshmc -V | grep -i build | cut -d \" \" -f 1' 2>/dev/null`;
		chomp($HMC_FSM);
		
		if( $HMC_FSM =~ /HMC/ ) {
			##-- Get first two values (x.x) of HMC release
			my $release = `echo $HmcRel | /usr/bin/awk -F \".\" '{print \$1 "." \$2}' 2>/dev/null`;
			
			##-- Check if HMC version is below 7 and Release below 7.3, return to calling function with error code -1
			if( $HmcVer < 7 || $release < 7.3 ) {
				`/usr/bin/sed "s/HMC_Supported:.*/HMC_Supported:0/" ${PMCONF} > ${tmpfile1}`;
				`/usr/bin/cp ${tmpfile1} ${PMCONF}`;
				`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Version -" > ${tmpfile1} 2>/dev/null`;
				`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
				WriteLog "HMC Version - Current HMC version is $HmcVer, release $HmcRel, Required is version 7 and release 7.3.0 or above!\n";
				return -1;
			}
		}
		
		##-- Update config file pmconf if HMC is supported
		`/usr/bin/sed "s/HMC_Supported:.*/HMC_Supported:1/" ${PMCONF} > ${tmpfile1}`;
		`/usr/bin/cp ${tmpfile1} ${PMCONF}`;
		
		##-- To get the machine names managed by HMC, filtering with the serial number
		$mach = `/usr/bin/ssh -l $HMC_User $HMC_Name 'lssyscfg -r sys -F name,serial_num | grep \"$Serial_Num\" | cut -d \",\" -f 1' 2>/dev/null`;
		chomp ( $mach );
		
		##-- If machine name is not found, return to calling function with error code -1
		if( $mach eq "" ) {
			##-- If the machine name is blank, in case of lpar not belonging to this hmc
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Machine Name -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "Machine Name - The HMC $HMC_Name does not have a machine name for this partition. Please check the HMC name!\n";
			return -1;
		}
		
		##-- Update the tmpfile with machine name to pass it from child process to parent process
		`/usr/bin/sed \"s/Machine:.*/Machine:${mach}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
		
		##-- Check if Allow Performance Collection is enabled for the partition
		$AllowPerf = `/usr/bin/ssh -l $HMC_User $HMC_Name 'lssyscfg -r lpar -m \"${mach}\" -F name,allow_perf_collection | grep -iw \"${Partition_Name}\" | cut -d \",\" -f 2' 2>/dev/null`;
		chomp($AllowPerf);
		
		##-- If Allow Performance Collection is disabled, return to calling function with return code -1
		if( $AllowPerf == 0 ) {
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Allow Performance Collection -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "Allow Performance Collection - Partition not authorised to collect data. Quiting!!\n";
			return -1;
		}
		
		return 1;
	}
	
	##-- Validate HMC Name and HMC user name is not set to NULL in config pmconf file
	$valid_hmc = 0;
	$hmc_msg = "";
	
	##-- If HMC Name is NULL, set valid_hmc value to 1
	if( $HMC_Name eq "" ) {
		$valid_hmc=1;
		$hmc_msg .= "HMC Name";
	}
	
	##-- If HMC Username is NULL, set valid_hmc value to 1
	if( $HMC_User eq "" ) {
		if( $valid_hmc == 1 ) {
		$hmc_msg .= " and HMC User";
		} else {
		$valid_hmc=1;
		$hmc_msg .= "HMC User";
		}
	}
		
	##-- If valid_hmc value is 1, means HMC Name or HMC Username is NULL, return to calling function with error code -1
	if( $valid_hmc == 1 ) {
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Info -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		WriteLog "HMC Info - Hmc info is not valid\nPlease update ${PMCONF} with $hmc_msg\n";
		Grace_Exit 1;
	}
	
	
	##-- Get current time
	my $curtime = time();
	
	##-- Set max time to 30 seconds to check ssh connection check
	my $maxtime = $curtime + 30;
	my $toloop = 0;
	
	##-- Create child process
	my $pid = fork();
	sleep 1;
	
	##-- If child process fails, exit with error
	if (not defined $pid) {
		##-- If child process failed to create, exit with error
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Child Failed -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		WriteLog "Child Failed - Not enough resourse for child process!\n";
		Grace_Exit 1;
	} elsif ($pid == 0) {
		##-- If Child process created, check ssh connection from partition to HMC
		$inchild = Check_Ssh;
		
		##-- Get the child exit status from tmpfile
		`/usr/bin/sed \"s/child:.*/child:${inchild}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
		
		##-- Exit the child process
		exit(0);
	} else {
		##-- Parent process running along with child process and monitoring the child to exit within time limit of 30 seconds, else kill the child process
		while( !$toloop ) {
			##-- Get the child process exit status
			$inchild=`/usr/bin/cat ${tmpfile} | /usr/bin/grep child | /usr/bin/cut -d \":\" -f 2 2>/dev/null`;
			chomp($inchild);
			
			##-- Get the current time
			$curtime = time();
			
			##-- If child process is complete, wait for the pid and set toloop to 1 to exit while loop
			if( $inchild == 1 ) {
				waitpid($pid,0);
				$toloop = 1;
			} elsif ( $maxtime < $curtime || $inchild == -1 ) {
				##-- If child process is taking more than maxtime (30 seconds), kill the child process and exit with time out error
				$toloop = 1;
				kill 1, $pid;
				waitpid($pid,0);
				if( $maxtime < $curtime ) {
					`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: SSH To HMC -" > ${tmpfile1} 2>/dev/null`;
					`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
					WriteLog "SSH To HMC - Timeout in checking for SSH connection to HMC ${HMC_Name} with user ${HMC_User}\n";
				}
				Grace_Exit 1;
			}
		}
	}
	
	
	##-- Convert the date format into seconds
	sub date_to_sec
	{
		my $date_time = shift;
		
		##-- Split date and time
		my @tmp = split( / /, $date_time );
		
		##-- Split date and time again
		my @tmp = (split(/\//,$tmp[0]), split(/:/,$tmp[1]));
		
		my $year = $tmp[0];
		my $mon = $tmp[1];
		my $day = $tmp[2];
		my $hr = $tmp[3];
		my $min = $tmp[4];
		my $sec = $tmp[5];
		
		my $year_tmp = $year - 1970;
		
		use integer;
		
		##-- Number of leap years since 1970 till $year
		my $leap = $year_tmp / 4;
		
		my $noleap = $year_tmp - $leap;
		
		##-- Sum of number of days in non-leap years
		my $num_days1 = $noleap * 365;
		
		##-- Sum of number of days in non-leap years
		my $num_days2 = $leap * 366;
		
		##-- Sum of number of days in leap years and non-leap years
		my $days_in_years = $num_days1 + $num_days2;
		my $day_tmp = 0;
		
		##-- Calculating the number of days from the begining of $year till $day
		##-- For each month in a year
		for my $i ( 1,2,3,4,5,6,7,8,9,10,11,12 ) {
			
			##-- Loop from first month 1 till the current month and add take sum of days in each month
			if( $i < $mon ) {
				use Switch;
				switch( $i ) {
					##-- Jump here for the months which has 31 days
					case [1,3,5,7,8,10,12]
					{
						$day_tmp = $day_tmp + 31;
					}
					##-- Jump here if it is second months
					case 2
					{
						##-- if $year is a leap year, $leapyr is 1, else 0
						my $leapyr = $year % 4;
						if ( $leapyr == 0 ) {
							$day_tmp = $day_tmp + 29;
						} else {
							$day_tmp = $day_tmp + 28;
						}
					}
					##-- Jump here for the months which has 30 days
					case [4,6,9,11]
					{
						$day_tmp = $day_tmp + 30;
					}
				}
			}
		}
		
		##-- Sum of days in current month and total days in previous months
		$day_tmp = $day_tmp + $day;
		
		##-- Sum of days in current year and total days in previous years
		$day_tmp = $day_tmp + $days_in_years - 1;
		
		##-- Convert total days in hours
		my $hr_tmp = $day_tmp * 24;
		
		##-- Add current hours to total hours from previous days
		$hr_tmp = $hr_tmp + $hr;
		
		##-- Convert total hours to mins
		my $min_tmp = $hr_tmp * 60;
		
		##-- Add current mins to total mins from previous mins
		$min_tmp = $min_tmp + $min;
		
		##-- Convert total mins to seconds
		my $sec_tmp = $min_tmp * 60;
		
		##-- Add current seconds to total seconds from previous seconds
		$sec_tmp = $sec_tmp + $sec;
		
		##-- Return the date converted value in seconds
		return $sec_tmp;
	}
	
	sub time_difference
	{
		##-- Get data in specific format from partition
		my $var = "/usr/bin/date +'%Y/%m/%d %T'";
		
		my $localdat = `$var 2>/dev/null`;
		
		##-- Get date in specific format from HMC
		my $hmcdat = `/usr/bin/ssh -l $HMC_User $HMC_Name \"date +'%Y/%m/%d %T'\" 2>/dev/null`;
		
		chomp($localdat);
		chomp($hmcdat);
		
		##-- Convert local date to seconds
		my $localsec = date_to_sec ( $localdat );
		
		##-- Convert HMC date to seconds
		my $hmcsec = date_to_sec ( $hmcdat );
		my $sign = "";
		my $tmpsec = 0;
		
		##-- If HMC time is greater than local time, difference is with negative sign
		if( $hmcsec > $localsec ) {
			$sign = "-";
			$tmpsec = $hmcsec - $localsec;
		} else {
			$tmpsec = $localsec - $hmcsec;
		}
		my $difsec = 0;
		my $difmin = 0;
		my $difhr = 0;
		
		if( $tmpsec > 60 ) {
			$difsec = $tmpsec % 60;
			$tmpsec = $tmpsec - $difsec;
			
			if( $tmpsec > 60 ) {
				$tmpsec = $tmpsec / 60;
				$difmin = $tmpsec % 60;
				$tmpsec = $tmpsec - $difmin;
				$difhr = $tmpsec / 60
			} else {
				$difmin = $tmpsec;
			}
		} else {
			$difsec = $tmpsec;
		}
		
		print TMPOUTFILE "Lpar date and time		: $localdat\n";
		print TMPOUTFILE "Hmc date and time		: $hmcdat\n";
		print TMPOUTFILE "Clock Offset				: $sign$difhr:$difmin:$difsec\n\n"; 
		
	}
	
	##-- Function to analyse the HMC Cross Lpar data
	sub analyse_data
	{
		# 
		my (@fulldata) = @{(shift)};
		my ($cfg) = (shift);
		my $hw = shift;
		
		my $cycles_per_sec = shift;
		my $intval = shift;
		my $m_serial_no = shift;
		
		my $data1 = "";
		my $data2 = "";
		
		chomp($cycles_per_sec);
		chomp($intval);
		chomp($m_serial_no);
		
		my $os_id = "";
		my $curr_min_procs = "";
		my $curr_max_procs = "";
		my $curr_min_proc_units = "";
		my $curr_max_proc_units = "";
		my $start_date = "";
		my $lpar_no = "";
		my $proc_sharing = "";
		my $num_virt_proc = "";
		my $virt_pool_id = "";
		my $conf_capacity = "";
		my $mem_alloc = "";
		my $proc_ent_time = "";
		my $used_proc_ent_time = "";
		my $donated_proc_time = "";
		my $capped_proc_time = "";
		my $uncapped_proc_time = "";
		my $lpar_name = "";
		my $idle_time = "";
		my $os_version = "";
		my $lpar_inst = "";
		
		my @tmp = split( ",", $cfg );
		chomp($tmp[1]);
		$os_version = $tmp[1];
		
		@tmp = split( ",", $hw );
		$curr_min_procs = $tmp[1];
		$curr_max_procs = $tmp[2];
		$curr_min_proc_units = $tmp[3];
		$curr_max_proc_units = $tmp[4];
		
		chomp($curr_min_procs);
		chomp($curr_max_procs);
		chomp($curr_min_proc_units);
		chomp($curr_max_proc_units);
		
		$os_id = `echo $os_version | /usr/bin/awk '{print \$1}' 2>/dev/null`;
		chomp($os_id);
		use Switch;
		switch($os_id) {
			case "AIX"
			{
				$os_id = 1;
			}
			case "OS/400"
			{
				$os_id = 0;
			}
			case "Unknown"
			{
				$os_id = -1;
			}
			case "Linux"
			{
				$os_id = 2;
			}
		}
		
		my $data_len = @fulldata;
		my @data1 = split( ",", $fulldata[0] );
		
		
		for( my $i = 1; $i < $data_len; $i++ )
		{
			my @data2 = split( ",", $fulldata[$i] );
			
			$start_date = $data1[0];
			$end_date = $data1[0];
			
			if( $data1[0] eq "" ) {
				@data1 = @data2;
				next;
			} 
			if( $data2[0] eq "" ) {
				next;
			}
			
			$lpar_no = $data1[1];
			$num_virt_proc = $data1[4];
			$virt_pool_id = $data1[5];
			$conf_capacity = $data1[6];
			$mem_alloc = $data1[7];
			$proc_ent_time = $data1[8];
			$donated_proc_time = $data1[9];
			$capped_proc_time = $data1[10];
			$uncapped_proc_time = $data1[11];
			$lpar_name = $data1[12];
			$lpar_inst = $data1[13];
			
			chomp($lpar_name);
			
			##-- If HMC output has idle_cycles, set the variable with idle_cycles value, else set to 0
			if( $with_idle_cycle == 1 ) {
				$idle_time = $data1[14];
			} else {
				$idle_time = 0;
			}
			
			if( $with_idle_cycle == 1 ) {
				$idle_time = $idle_time - $data2[14];
			}
			
			$uncapped_proc_time = $uncapped_proc_time - $data2[11];
			$lpar_inst = $lpar_inst - $data2[13];
			
			switch($data1[2])
			{
				case "ded"
				{
				$used_proc_ent_time = ( $capped_proc_time - $data2[10] ) + ( $uncapped_proc_time ) - ( $idle_time );
					$proc_sharing = 0;
					$virt_pool_id = "NA";
					$conf_capacity = "NA";
					$curr_min_proc_units = "NA";
					$curr_max_proc_units = "NA";
				}
				case "shared"
				{
				$used_proc_ent_time = ( $capped_proc_time - $data2[10] ) + ( $uncapped_proc_time );
					if( $data1[3] eq "cap" ) {
						$proc_sharing = 1
					} elsif( $data1[3] eq "uncap" ) {
						$proc_sharing = 2
					}
				}
			}
			#if( $data1[2] eq "ded" ) {
			#	$used_proc_ent_time = ( $capped_proc_time - $data2[10] ) + ( $uncapped_proc_time ) - ( $idle_time );
			#} else {
			#	$used_proc_ent_time = ( $capped_proc_time - $data2[10] ) + ( $uncapped_proc_time );
			#}
			
			if( $used_proc_ent_time > 0 ) {
				$used_proc_ent_time = $used_proc_ent_time * 1000;
				$used_proc_ent_time = int($used_proc_ent_time / $cycles_per_sec);
			} else {
				$used_proc_ent_time = 0;
			}
			
			$proc_ent_time = $proc_ent_time - $data2[8];
			$proc_ent_time = $proc_ent_time * 1000;
			$proc_ent_time = int($proc_ent_time / $cycles_per_sec);
			
			$donated_proc_time = $donated_proc_time - $data2[9];
			$donated_proc_time = $donated_proc_time * 1000;
			$donated_proc_time = int($donated_proc_time / $cycles_per_sec);
			
			$idle_time = $idle_time * 1000;
			$idle_time = int($idle_time / $cycles_per_sec);
			
			$uncapped_proc_time = $uncapped_proc_time * 1000;
			$uncapped_proc_time = int($uncapped_proc_time / $cycles_per_sec);
			
			@tmp = split(" ", $start_date);
			$start_date = $tmp[0];
			@tmp = split("/", $start_date);
			$start_date = "$tmp[2]-$tmp[0]-$tmp[1]";
			
			@tmp = split(" ", $end_date);
			$end_date = $tmp[1];
			@tmp = split(":", $end_date);
			$end_date = "$tmp[0]-$tmp[1]-$tmp[2]";
			
			print TMPOUTFILE "$start_date,$end_date,$intval,$lpar_no,$os_id,$os_version,$proc_sharing,$num_virt_proc,$virt_pool_id,$conf_capacity,$mem_alloc,$proc_ent_time,$used_proc_ent_time,$uncapped_proc_time,$donated_proc_time,$idle_time,$curr_min_procs,$curr_max_procs,$curr_min_proc_units,$curr_max_proc_units,$lpar_name,$m_serial_no,$lpar_inst\n";
			
			
			@data1 = @data2;
		}
	}
	
	
	##-- Function Main
	sub Main
	{
		my @pars="";
		
		##-- time_difference;
		time_difference;
		
		##-- To get topas recording interval
		my $topasrec_int = `/usr/bin/ps -ef | /usr/bin/grep topasrec | /usr/bin/awk -F"-s" '{ print \$2 }' | /usr/bin/awk '{ print \$1 }' 2>/dev/null`;
		
		##-- Remove unwanted blank spaces
		$topasrec_int =~s/"+//g;
		$topasrec_int =~s/\s+//g;
		chomp($topasrec_int);
		
		# print TMPOUTFILE "#<datacols>start_date,end_time,interval,lpar_id,OS_id,OS_Version,proc_sharing,num_virt_proc,virt_pool_id,conf_capacity,mem_alloc,proc_ent_time,used_proc_ent_time,uncapped_proc_time,donated_proc_time,idle_time,curr_min_procs,curr_max_procs,curr_min_proc_units,curr_max_proc_units,lpar_name,serial_number</datacols>\n";
		
		##-- To get current partition name on which this script is executing
		$Partition_Name = `/usr/bin/lparstat -i | /usr/bin/grep "Partition Name" | /usr/bin/awk '{print \$4}' 2>/dev/null`;
		chomp($Partition_Name);
		
		##-- Get machine name from the tmpfile
		$mach=`/usr/bin/cat ${tmpfile} | /usr/bin/grep Machine | /usr/bin/cut -d \":\" -f 2 2>/dev/null`;
		chomp($mach);
		
 		##-- To get the HMC recording interval
		my $mach_intv = `/usr/bin/ssh -l $HMC_User $HMC_Name 'lslparutil -r config -F sample_rate -m \"${mach}\"' 2>/dev/null`;
		chomp( $mach_intv );
		
		if(	$? ) {
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Sample Rate -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "Sample Rate - Error finding the sample rate from HMC\n";
			return -1;
		}
		
		my $is_valid=1;
		my $msg = "";
		if( $mach_intv =~ /^\d+\z/  ) {
			##-- If machine interval is set to 0
			if( $mach_intv == 0 ) {
				$is_valid = 0;
				$msg .= "Sampling Rate for the machine \"${mach}\" Interval is set to Disabled, Please enable the sampling rate in HMC going to Machine > Operations > Utilization Data > Change Sampling Rate -- ";
			}
		} else {
			##-- Or if machine interval is not set at all, set as not valid to exit
			$is_valid = 0;
			if( $msg ne "" ) {
			$msg .= " and";
			}
			$msg .= " HMC recording Interval is not set or not valid. HMC error msg: $mach_intv";
		}
		
		##-- If hmc machine interval is not valid, return to calling function with error code -1
		if( $is_valid != 1 ) {
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Sample Rate -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "Sample Rate - Unable to continue: $msg\n";
			return -1;
		}
		
		##-- If machine interval is less than 0, return with error 1
		if( ! $mach_intv > 0 ) {
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Data -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "HMC Data - HMC Recording is not enabled for HMC: \"${HMC_Name}\", Server: \"${mach}\"\nContaining LPars: ";
			
			##-- Gets the lpar names belonging to this machine for which the recording is not enabled
			@pars=`/usr/bin/ssh -l $HMC_User $HMC_Name 'lssyscfg -r lpar -m \"${mach}\" -F name' 2>/dev/null`;
			if ( $? == 0 ) {
				foreach (@pars) {
					chomp($_);
					print TMPOUTFILE "$_, ";
				}
				print TMPOUTFILE "\n\n";
			}
		} else {
			
			##-- Gets the lpar names belonging to this machine
			@pars=`/usr/bin/ssh -l $HMC_User $HMC_Name 'lssyscfg -r lpar -m \"${mach}\" -F name' 2>/dev/null`;
			
			##-- If above command is success, proceed
			if ( $? == 0 )
			{
				my $lpar_no = scalar(@pars);
				my $count;
				my $XLpar_Interval;
				
				if ( $topasrec_int > $mach_intv ) {
					$count = $topasrec_int / $mach_intv;
				} else {
					$count = 2;
				}
				
				##-- As per topasrec, its executing process every 15 min by default.
				$XLpar_Interval = `/usr/bin/grep Xlpar_Interval ${PMCONF} | /usr/bin/cut -d ':' -f 2-10 | /usr/bin/sed 's/:/#!:/g' 2>/dev/null`;
				
				if( $? != 0 || $XLpar_Interval eq "" )
				{
					$XLpar_Interval = 60;
				}
				
				##-- Convert the interval in minutes to seconds
				$XLpar_Interval = $XLpar_Interval * 60;
				
				##-- If machine interval is greater than xlpar interval, set the machine interval as xlpar interval in config file
				if( $XLpar_Interval < $mach_intv )
				{
					$XLpar_Interval = $mach_intv;
					`/var/perf/pm/bin/config_pm.sh -C $XLpar_Interval 2>/dev/null`;
				}
				
				##-- Count of number of records in an interval
				$count = ( $XLpar_Interval / $mach_intv ) + 1;
				
				##-- Number of records for n number of lpars in machine
				$count = $lpar_no * $count;
				
				my $util_cmd = "";
				
				##-- To check if HMC has idle_cycles field for lslparutil -r lpar
				`/usr/bin/ssh -l $HMC_User $HMC_Name 'lslparutil -m \"${mach}\" -r lpar -F idle_cycles' 2>/dev/null`;
				if ( $? == 0 ) {
					$with_idle_cycle = 1;
					$util_cmd = "lslparutil -m \"${mach}\" -n $count -r lpar -F time,lpar_id,curr_proc_mode,curr_sharing_mode,curr_procs,curr_shared_proc_pool_id,curr_proc_units,curr_mem,entitled_cycles,shared_cycles_while_active,capped_cycles,uncapped_cycles,lpar_name,run_latch_instructions,idle_cycles";
				} else {
					$with_idle_cycle = 0;
					$util_cmd = "lslparutil -m \"${mach}\" -n $count -r lpar -F time,lpar_id,curr_proc_mode,curr_sharing_mode,curr_procs,curr_shared_proc_pool_id,curr_proc_units,curr_mem,entitled_cycles,shared_cycles_while_active,capped_cycles,uncapped_cycles,lpar_name,run_latch_instructions";
				}
				
				##-- Commands to execute on HMC
				$fulcmd=<<EOF;
'$util_cmd;
lssyscfg -m \"${mach}\" -r lpar -F name,os_version;
lshwres -m \"${mach}\" -r proc --level lpar -F lpar_name,curr_min_procs,curr_max_procs,curr_min_proc_units,curr_max_proc_units;
lslparutil -m \"${mach}\" -r sys -F proc_cycles_per_second;
lssyscfg -m \"${mach}\" -r sys -F serial_num;'
EOF
				##-- Execute all the above commands in one ssh call
				my @mydata2 = `/usr/bin/ssh -l $HMC_User $HMC_Name $fulcmd 2>/dev/null`;
				
				print TMPOUTFILE "";
				
				##-- Count of number of records from HMC output
				$datalen = scalar(@mydata2);
				$actual_datalen = $count + $lpar_no + $lpar_no + 1;
				
				##-- If HMC output is not valid, return to calling function
				if( $datalen < $actual_datalen ) {
					chomp( $mydata2[0] );
					if ( "$mydata2[0]" =~ /invalid attribute/ ) {
						`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Data Invalid -" > ${tmpfile1} 2>/dev/null`;
						`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
						WriteLog "HMC Data Invalid - Error while data collection for HMC: \"${HMC_Name}\", Server: \"${mach}\" \n$mydata2[0]\n\n";
					} else {
						`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Data Invalid -" > ${tmpfile1} 2>/dev/null`;
						`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
						WriteLog "HMC Data Invalid - Error while data collection for HMC: \"${HMC_Name}\", Server: \"${mach}\"\n";
					}
					return -1;
				}
				
				##-- Storing each command output in separate arrays and variables
				my @util_data = @mydata2[0..$count-1];
				my @cfg_data = @mydata2[$count..$count+$lpar_no-1];
				my @hw_data = @mydata2[$count+$lpar_no..$count+$lpar_no+$lpar_no-1];
				my $cycles_per_sec = $mydata2[$count+$lpar_no+$lpar_no];
				my $mach_serial_num = $mydata2[$count+$lpar_no+$lpar_no+1];
				
				chomp($cycles_per_sec);
				chomp($mach_serial_num);
				
				##-- Loop for n number of lpars in machine, analyse data for same lpar with output for two different interval
				for( my $i= 0; $i < $lpar_no; $i++ )
				{
					my $parnam = $pars[$i];
					chomp($parnam);
					##-- Grep for individual lpar data from each array
					my @lpar_util_data = grep (/,$parnam,/, @util_data);
					my @lpar_cfg_data = grep (/^$parnam,/, @cfg_data);
					my @lpar_hw_data = grep (/^$parnam,/, @hw_data);
					
					my $lpar_data_count = @lpar_util_data;
					my $lpar_cfg_count = @lpar_cfg_data;
					my $lpar_hw_count = @lpar_hw_data;
					
					##-- Call analyse data function for each lpar with array of utilization, config, hardware, cycles_per_sec, machine interval, and machine serial number
					analyse_data ( \@lpar_util_data, $lpar_cfg_data[0], $lpar_hw_data[0], $cycles_per_sec, $mach_intv, $mach_serial_num);
				}
			}
		}
		return 1;
	}
	
	##-- Call Main
	
	##-- Set initial value of child process status
	$inchild = 0;
	
	##-- Update the tmpfile with child status value
	`/usr/bin/sed \"s/child:.*/child:${inchild}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
	`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
	
	##-- Get current time
	my $curtime = time();
	
	##-- Set maxtime limit to 900 seconds
	my $maxtime = $curtime + 900;
	$toloop = 0;
	
	##-- Create Child process
	my $pid1 = fork();
	sleep 1;
	if (not defined $pid1) {
		##-- If child process failed to create, exit
		WriteLog "Not enough resourse for child process for Main!\n";
		Grace_Exit 1;
	} elsif ($pid1 == 0) {
		##-- If child process is created, call Main function for Cross Lpar 
		$inchild = Main;
		
		##-- Update the child process status in tmpfile
		`/usr/bin/sed \"s/child:.*/child:${inchild}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
		
		##-- Exiting the child process
		exit(0);
	} else {
		##-- Parent process: loop until child process finishes or if it exceeds maxtime limit
		while( !$toloop ) {
			##-- Get child process status from tmpfile
			$inchild=`/usr/bin/cat ${tmpfile} | /usr/bin/grep child | /usr/bin/cut -d \":\" -f 2 2>/dev/null`;
			chomp($inchild);
			
			##-- Get current time
			$curtime = time();
			if( $inchild ) {
				##-- If child process exited, set loop variable to finish while loop
				$toloop = 1;
			} elsif ( $maxtime < $curtime || $inchild == -1 ) {
				##-- If maxtime limit exceeds, kill the child process and exit with error
				$toloop = 1;
				kill 1, $pid1;
				
				##-- If child process has exceeded time limit, update log file
				if( $maxtime < $curtime ) {
					`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Timedout -" > ${tmpfile1} 2>/dev/null`;
					`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
					WriteLog "HMC Timedout - Time out in collecting performance data from HMC ${HMC_Name}\n";
				}
				Grace_Exit 1;
			}
		}
	}

	Grace_Exit 0;
