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