#!/usr/bin/perl 
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# perf720 src/perf/pmaix/usr/bin/pmcfg/amsinfo 1.7 
#  
# 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);
		}
	}
	
	my $SSHCMD = "/usr/bin/ssh -o 'PreferredAuthentications=publickey' -o 'StrictHostKeyChecking=no' ";
	
	##-- 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];
	open OUTFILE, ">$OUTFILE";
	
	##-- Store config file pmconf path in PMCONF variable
	$PMCONF = "/var/perf/pm/config/pmconf";
	chomp($PMCONF);
	
	##-- 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";
	
	##-- 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);
	
	##-- Clearing the amsinfo logs from pmcfg.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} ) {
			`/usr/bin/rm -f ${tmpfile} 2>/dev/null`;
			if( $? ) {
				WriteLog "Unable to delete temporary file ${tmpfile}!\n";
			}
		}
		
		##-- If tmpfile1 exist, remove tmpfile1
		if( -e ${tmpfile1} ) {
			`/usr/bin/rm -f ${tmpfile1} 2>/dev/null`;
			if( $? ) {
				WriteLog "Unable to delete temporary file ${tmpfile1}!\n";
			}
		}
		
		##-- If normal exit
		if( $exitcode == 0 ) {
			print TMPOUTFILE "</shrmem>\n";
			
			##-- Copy the output stored in temp output file to actual output file
			`/usr/bin/cp $TMPOUTFILE $OUTFILE 2>/dev/null`;
			if( $? ) {
				WriteLog "Unable to write to output file $OUTFILE\n";
			}
		}
		
		##-- Close LOGFILE and TEMPOUTFILE
		close LOGFILE;
		close TMPOUTFILE;

                ##-- Remove temporary output file
                `/usr/bin/rm -f ${TMPOUTFILE}`;
                if( $? ) {
                      WriteLog "Unable to delete temp output file $TMPOUTFILE\n";
                }
		
		##-- 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}`;
	
	##-- 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 )
	{
		`/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";
		Grace_Exit 1;
	}
	
	##-- Get the name of the lpar
	$curr_lpar = `/usr/bin/lparstat -i | /usr/bin/grep "Partition Name" | /usr/bin/awk '{print \$4}' 2>/dev/null`;
	chomp ($curr_lpar);

	##-- To check if lpar is managed by HMC and get the HMC name
	`/usr/bin/lsrsrc -l "IBM.MCP" 2>/dev/null | /usr/bin/grep MNName 2>/dev/null`;
	if( $? != 0 )
	{
		##-- If lpar is stand alone and not managed by HMC, quit with error msg
		`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: HMC Managed -" > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
		WriteLog "HMC Managed - This Lpar ${curr_lpar} is Either not configured for RMC or is not managed by HMC!\n";
	}

	##-- Check if PM is enabled, if not enabled, exit the script
	`/usr/bin/grep "# Enabled" /var/perf/pm/config/pmconf 2>/dev/null`;
	if( $? != 0 )
	{
		##-- If PM Data Transmission is not enabled, quit execution
		`/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;
	}

	##-- To check if lpar of shared or dedicated memory mode 
	sub get_mem_mode
	{
		##-- Get the memory mode (Dedicated or Shared) of lpar from lparstat command output
		$mem_mode=`/usr/bin/lparstat -i | /usr/bin/grep "Memory Mode" | /usr/bin/cut -d ':' -f 2 2>/dev/null`;
		chomp($mem_mode);
			
		##-- If lpar is of Dedicated, return to calling function with error code -1
		if( $mem_mode =~ /Dedicated/ ) {
			`/usr/bin/cat $LOGFILE | /usr/bin/grep -v "$ScriptName: Memory Mode -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "Memory Mode - This Partition is of $mem_mode memory mode. The Shared Memory Pool data can be collected only for Partitions with Shared memory mode\n";
			return -1;
		}
		return 0;
	}



	##-- Check if Password-less ssh is setup from LPar to HMC
	sub check_lpar_ssh_to_hmc
	{
		##-- Check password-less ssh connection to HMC
		`${SSHCMD} -l ${HMC_User} ${HMC_Name} echo 2>/dev/null`;
		
		##-- If password-less ssh connection fails, return to calling function with code 1
		if( $? != 0)
		{
			`/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 to HMC ${HMC_Name}. Password-Less SSH to HMC not setup!\n";
			return -1;
		}
		
		##-- If ssh connection passes, get HMC version
		$HmcVer = `${SSHCMD} -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 = `${SSHCMD} -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 = `${SSHCMD} -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
		$Machine_Name = `${SSHCMD} -l $HMC_User $HMC_Name 'lssyscfg -r sys -F name,serial_num | grep -w  \"$Serial_Num\" | cut -d \",\" -f 1' 2>/dev/null`;
		chomp ( $Machine_Name);
		
		##-- If machine name is not found, return to calling function with error code -1
		if( $Machine_Name 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:${Machine_Name}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
		
		##-- Check if Allow Performance Collection is enabled for the partition
		$AllowPerf = `${SSHCMD} -l $HMC_User $HMC_Name 'lssyscfg -r lpar -m \"${Machine_Name}\" -F name,allow_perf_collection | grep -iw ${curr_lpar} | 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;
	}

	##-- Check if HMC user name and HMC user id is updated in the pmconf file
	sub get_hmc_info
	{
		##-- Call function get_mem_mode to get the memory mode 
		$retval = get_mem_mode;
		
		##-- If return value of function get_mem_mode is not 0, return to calling function with error code -1
		if( $retval != 0 ) {
			return -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);
		
		##-- 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 Invalid -" > ${tmpfile1} 2>/dev/null`;
			`/usr/bin/cp ${tmpfile1} $LOGFILE 2>/dev/null`;
			WriteLog "HMC Info Invalid - Hmc info is not valid. Please update ${PMCONF} with $hmc_msg\n";
			return -1;
		}
		
		##-- Check the ssh connection from partition to HMC
		$retval = check_lpar_ssh_to_hmc;
		
		##-- If connection to HMC fails, return to calling function with code -1
		if( $retval != 1 ) {
			return -1;
		}
		return 0;
	}
	
	
	##-- Convert the date format into seconds
	sub date_to_sec
	{
		my $date_time = shift;
		
		##-- Split date and time
		my @tmp1 = split( / /, $date_time );
		
		##-- Split date and time again
		my @tmp = (split(/\//,$tmp1[0]), split(/:/,$tmp1[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 = `${SSHCMD} -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;
		}
		
	}

	##-- Get the HMC Information
	$retval = get_hmc_info;
	
	##-- If HMC Info function returns with error, grace exit
	if( $retval == -1 ) {
		Grace_Exit 1;
	}
	
	##-- 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`;

	$curtime = time();
	$maxtime = $curtime + 30;
	$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_lpar_ssh_to_hmc;
		
		##-- 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`;
		
		##-- Set child exit status to 0 for new function call
		$inchild = 0;
		
		##-- Update the tmpfile common to both child and parent process
		`/usr/bin/sed \"s/child:.*/child:${inchild}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
		`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
		$inchild = time_difference;
		
		##-- 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;
			}
		}
	}

	##-- Function to get HMC data
	sub GetData
	{	
		
		my $var = "/usr/bin/date +'%Y/%m/%d %T'";
		
		my $localdat = `$var 2>/dev/null`;
		chomp($localdat);
		my @tmp1 = split( / /, $localdat );
		my @tmp = (split(/\//,$tmp1[0]), split(/:/,$tmp1[1]));
		
		my $year = $tmp[0];
		my $mon = $tmp[1];
		my $day = $tmp[2];
		my $prev_day = $day - 1;

		##-- Get HMC name from tmpfile which is stored by the child process
		$Machine_Name=`/usr/bin/cat ${tmpfile} | /usr/bin/grep Machine: | /usr/bin/cut -d \":\" -f 2 2>/dev/null`;
		chomp ( $Machine_Name );
		
		##-- Get HMC sample rate interval
		my $Interval = `${SSHCMD} -l $HMC_User $HMC_Name 'lslparutil -r config -m \"${Machine_Name}\" -F sample_rate' 2>/dev/null`;
		chomp ( $Interval );
		
		my $is_valid=1;
		my $msg = "";
		if( $Interval =~ /^\d+\z/  ) {
			##-- If interval is 0, HMC is not enabled to record server utilization statistics,
			if( $Interval == 0 ) {
				$is_valid = 0;
				$msg .= "Sampling Rate for the machine \"${Machine_Name}\" Interval is set to Disabled, Please enable the sampling rate in HMC going to Machine > Operations > Utilization Data > Change Sampling Rate -- ";
			}
		} else {
			##-- Else if no interval set to record HMC utilization 
			$is_valid = 0;
			if( $msg ne "" ) {
			$msg .= " and";
			}
			$msg .= " HMC recording Interval is not set or not valid. HMC error msg: $Interval";
		}
		
		##-- If HMC is not enabled to record data utilization, exit return 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 memory mode is shared then collect data
		if( $mem_mode =~ /Shared/ ) {
			
			my $mempoolid=`lparstat -i | grep -iw "Memory Pool ID" | cut -d':' -f2 | sed 's/ //g' 2>/dev/null`;
			chomp($mempoolid);
		
		##-- mydata1 contains the data that will be printed in the output file only once in a day		
			my $mydata1 = `${SSHCMD} -l $HMC_User $HMC_Name 'lslparutil -m ${Machine_Name} -r mempool -F curr_pool_mem,lpar_curr_io_entitled_mem,sys_firmware_pool_mem' 2>/dev/null`;
			if ($?) {
                        WriteLog "SSH failed while collecting data from HMC\n";
                        return -1;
                        }
			chomp($mydata1);
	
		##-- fulcmd has two commands; lslparutil will be called with two different flags -mempool and -lpar to collect the shared memory pool data particular to memory pool and lpar		
			$fulcmd=<<EOF;
			'lslparutil -m \"${Machine_Name}\" -r mempool -d 0 --filter \"event_types=sample\" -F time,lpar_mapped_io_entitled_mem,page_faults,lpar_run_mem,page_in_delay;
			lslparutil -r lpar -m ${Machine_Name} --filter \"lpar_names=$curr_lpar\" -d 0 -F time,mem_mode,curr_mem,curr_io_entitled_mem,mapped_io_entitled_mem,phys_run_mem,run_mem_weight,mem_overage_cooperation;'
EOF
		
		##-- fulldatacmd will contain lslparutil outputs time, lpar_name,mem_mode and physical run memory; The intention is to get the physical run memory of all the lpars and sum it up to get the pool utilization	
			$fulldatacmd=<<EOF;
			'lslparutil -r lpar -m ${Machine_Name} -d 0 -F time,lpar_name,mem_mode,phys_run_mem | grep shared;'
EOF
	
		##-- The array mydata2 stores the output of fulcmd; the size of the array is stored in cnt and half its size is stored in count variable
			my @mydata2 = `${SSHCMD} -l $HMC_User $HMC_Name $fulcmd 2>/dev/null`;
			if ($?) {
                        WriteLog "SSH failed while collecting data from HMC\n";
                        return -1;
                        }
			my $cnt = scalar (@mydata2);
			chomp($cnt);
			my $count = $cnt/2;
			chomp($count);

		##-- Fuldata array contains the output of lslparutil, stored in fulldatacmd variable 	
			my @fuldata = `${SSHCMD} -l $HMC_User $HMC_Name $fulldatacmd 2>/dev/null`;
		##-- Timestamp_data array greps the data pertainingto only one lpar from the complete data; This step is carried on to collect the timestamps. 
			my @timestamp_data = grep /$curr_lpar/, @fuldata;
			my @time_stamp,@sum_pool_mem;

		##-- Time_stamp array contains the time_stamps for current lpar; the time_stamps are grepped from timestamp_data array;	
			foreach my $t(@timestamp_data) {
				my $ts = `echo "$t" | cut -d "," -f 1`;
				chomp($ts);	
				push(@time_stamp,$ts);		
			}

			foreach my $s(@time_stamp){
				chomp($s);
				my $pool_phys_run_mem = 0;
		##-- Pool_util_data array contains the data for all lpar for a particular time stamp;
				my @pool_util_data = grep /$s/, @fuldata;
		##-- For every entry in pool_util_data array, get the physical_run_memory of each lpar in the variable lpar_phys_run_mem and sum it up; The sum is held in pool_phys_run_mem variable;  
				foreach my $p(@pool_util_data)	{
					my $lpar_phys_run_mem = `echo "$p" | cut -d "," -f 4`;
					chomp($lpar_phys_run_mem);
					$pool_phys_run_mem += $lpar_phys_run_mem;
					chomp($pool_phys_run_mem);
				}
		##-- pool_phys_run_mem contains the sum of lpar utilizations for each inerval; For every interval the sum is pushed to array sum_pool_mem;		
				push (@sum_pool_mem,"$s".",$pool_phys_run_mem");
			}


		##-- The arrays cmd1_data and cmd2_data are taken so as to seggregate the outputs of two commands of fulcmd
			my @cmd1_data;
			my @cmd2_data;
	 		@cmd1_data = @mydata2[0..$count-1];
			@cmd2_data = @mydata2[$count..$cnt-1];  
	
	
		##-- The page_in_delay field of cmd1_data will be in terms of microseconds; the below loop converts the data to milliseconds;	
			use integer;
			foreach my $field (@cmd1_data)
			{
	 			my $page_in_delay_microsec = `echo "$field" | cut -d ',' -f5`;
	 			chomp ($page_in_delay_microsec);
	 			my $page_in_delay_ms = $page_in_delay_microsec / 1000;
	 			chomp($page_in_delay_ms);
	 			my $pos = rindex( $field, ',' , length($field) );
	 			chomp($pos);
	 			my $new_field = substr( $field, 0, $pos+1 );
	 			chomp($new_field);
	 			$field = "$new_field"."$page_in_delay_ms\n";
			}
			
		##-- The array currtime takes the date_time field from cmd1_data	
			my @currtime;
			$n =0;
			foreach my $i(@cmd1_data)
			{
		 		my @tmp = split(/,/, $i);
		 		chomp($tmp[0]);
		 		$currtime[$n] = $tmp[0];
		 		$n++;
			} 
	
		##-- The date_time field of cmd1_data is grepped in cmd2_data; The grepped date_time field of cmd2_data is removed and the string is concatenated with cmd1_data; The output is stored in the array mydata3 
			my @cmd_data;
			my @mydata3;
			for(my $i=0; $i<=$count; $i++)
			{
				my $time = $currtime[$i];
		 		chomp($time);
				if ( $cmd1_data[$i] != "" )
				{
			 		@cmd_data = grep /$time/, @cmd2_data;
			 		$cmd_data[0] =~ s/$time,//;
			 		chomp($cmd1_data[$i]);
			 		chomp($cmd_data[0]);

					if ( $cmd_data[0] ne "" ) {
			 			$mydata3[$i] = "$cmd1_data[$i]".",$cmd_data[0]";
			 			chomp($mydata3[$i]);
					}
			 		
			 		my @mydate = split(/ /,$mydata3[$i]); 
			 		chomp ($mydate[0]);
			 		chomp ($mydate[1]);
			 	
				##-- The below block converts date to YY-MM-DD format	
					my @mydate1 = split("/",$mydate[0]);
					chomp($mydate1[0]);
			 		chomp($mydate1[1]);
			 		chomp($mydate1[2]);
			 		my @mydate2;
			 		$mydate2[0] = $mydate1[2];
			 		chomp($mydate2[0]);
			 		$mydate2[1] = $mydate1[0];
			 		chomp($mydate2[1]);
			 		$mydate2[2] = $mydate1[1];
			 		chomp($mydate2[2]);
			 		
			 		$mydate[0] = join("-", @mydate2);
			 		chomp($mydate[0]);
		
                    @total_pool_mem = grep /$time/, @sum_pool_mem;
                    $tot_pool_mem = `echo $total_pool_mem[0] | cut -d ',' -f 2`;
                    chomp($tot_pool_mem);
		
				##-- mydata3 array contains the overall output; It is the concatenation of parsed data along with memory pool utilization;		
			 		$mydata3[$i] = "$mydate[0]".",$mydate[1]".",$tot_pool_mem";
			 		chomp($mydata3[$i]);
				}  
			}

		##-- The output will be printed in to the output file
			print TMPOUTFILE  "<shrmem>\n";
			##-- print TMPOUTFILE  "<datacols>mem_pool_id, curr_pool_mem, Lpar_curr_io_entitled_mem, Sys_firmware_pool_mem</datacols>\n$mempoolid,$mydata1\n";
	 		
			print TMPOUTFILE "$mempoolid,$mydata1\n";
		##--print TMPOUTFILE "<datacols>date,time,lpar_mapped_io_entitled_mem,page_faults,lpar_run_mem,page_in_delay,mem_mode,curr_mem,curr_io_entitled_mem,mapped_io_entitled_mem,phys_run_mem,run_mem_weight,mem_overage_cooperation,phy_pool_run_mem</datacols>\n";
			
			for( my $i=0; $i <= $count; $i++ )
	   		{
				if ( $mydata3[$i] != "" ){
					print TMPOUTFILE "$mydata3[$i]\n";
	  			}
			}
			print OUTFILE "</shrmem>";
		}
	}

	##-- Set child initial status to 0
	$inchild = 0;
	
	##-- Update the tmpfile with child initial status
	`/usr/bin/sed \"s/child:.*/child:${inchild}/\" ${tmpfile} > ${tmpfile1} 2>/dev/null`;
	`/usr/bin/cp ${tmpfile1} ${tmpfile} 2>/dev/null`;
	
	my $curtime = time();
	
	##-- Set the maximum time as 900 seconds limit for the child process to execute to get HMC data for shared processor pool utilization
	my $maxtime = $curtime + 900;
	$toloop = 0;
	
	##-- Create child process
	my $pid1 = fork();
	sleep 1;
	
	##-- If child process fails to create, exit with error
	if (not defined $pid1) {
		`/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 for Main!\n";
		Grace_Exit 1;
	} elsif ($pid1 == 0) {
		##-- Else if child process is created, call GetData function in child process
		$inchild = GetData;
		
		##-- Update the child process return code in tmpfile to use it by parent process
		`/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 {
		##-- In Parent process: loop until the child process exit or the maxtime limit
		while( !$toloop ) {
			##-- Check child process status
			$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 child process has exited, set the loop variable to finish while loop
			if( $inchild ) {
				$toloop = 1;
			} elsif ( $maxtime < $curtime || $inchild == -1 ) {
				##-- If child process is still running and maxtime is more than the limit, kill 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;
