#!/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 "\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=</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 "\n"; ##-- print TMPOUTFILE "mem_pool_id, curr_pool_mem, Lpar_curr_io_entitled_mem, Sys_firmware_pool_mem\n$mempoolid,$mydata1\n"; print TMPOUTFILE "$mempoolid,$mydata1\n"; ##--print TMPOUTFILE "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\n"; for( my $i=0; $i <= $count; $i++ ) { if ( $mydata3[$i] != "" ){ print TMPOUTFILE "$mydata3[$i]\n"; } } print OUTFILE ""; } } ##-- 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;