#!/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 "#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\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=</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;