# ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2018,2020,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # 61haes_r721 src/43haes/usr/sbin/cluster/sa/sap/sbin/SAPUtilities.sh 1.26 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 2008,2016 # 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 # # @(#) 7d4c34b 43haes/usr/sbin/cluster/sa/sap/sbin/SAPUtilities.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM . /usr/es/lib/ksh93/func_include version='1.26' #--------------------------------------------------------------------------- # Global Definitions #--------------------------------------------------------------------------- . /usr/es/sbin/cluster/sa/sap/sbin/IO . /usr/es/lib/ksh93/func_include . /usr/es/sbin/cluster/sa/sap/etc/SAPGlobals typeset -i exe_check=1 typeset -i valid_version=0 typeset SID typeset SAPMNTDIR #--------------------------------------------------------------------------- #---------------------------------------------------------------------------- # Function: # setSAPGlobalEnv # # Purpose: # Sets SAP Gloabl Environment variables by finding SAPSYSTEMNAME. # # Arguments: # < SAPSYSTEMNAME > : If SAPSYSTEMNAME is passed as argument then it will be set directly # <-i Instance Name>: Search for SAPSYSTEMNAME from the profile for that instance # < > : If no Argument is passed then SAPSYSTEMNAME is greped from the first profile. # # Returns: # 0 -> for Sucess # 1 -> for Failure # #--------------------------------------------------------------------------- function setSAPGlobalEnv { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset startupProfiles typeset sapsystem typeset instance_name typeset Profile if [[ $1 == "-i" ]] then instance_name=$2 elif [[ -n $1 ]] then SAPSYSTEMNAME=$1 fi if [[ -z $SAPSYSTEMNAME ]]; then if [[ -f $SAPSERVICESFILE ]]; then getAllSAPInstanceStartupProfiles startupProfiles if (( ${#startupProfiles[*]} <= 0 )); then log_msg "No startup profiles found in $SAPSERVICESFILE" return 1 fi if [[ ! -z $instance_name ]]; then for Profile in ${startupProfiles[*]} ; do if echo "$Profile" 2>/dev/null | grep -q $instance_name then SAPSYSTEMNAME=$(echo "$Profile" 2>/dev/null | \ awk -F"/" '{print $4}' 2>/dev/null) break fi done else #Try finding the SAP System name from the first profile found. SAPSYSTEMNAME=$( echo ${startupProfiles[0]} | awk -F"/" '{print $4}') fi else echo "$SAPSERVICESFILE doesn't exist. It's not a SAP Netweaver 2004s SR2 Installation." return 1 fi fi SID=$SAPSYSTEMNAME SAPMNTDIR=/sapmnt/$SAPSYSTEMNAME SAPEXEDIR=/usr/sap/$SID/SYS/exe/run SAPPROFILEDIR=$SAPMNTDIR/profile SAPADMNUSR=$(echo $SAPSYSTEMNAME | tr '[:upper:]' '[:lower:]')adm SAPDBADMN=db2$(echo $SAPSYSTEMNAME | tr '[:upper:]' '[:lower:]') return 0; } #---------------------------------------------------------------------------- # Function: # getAllSAPInstanceStartupProfiles # # Purpose: # Gets All Instance profiles by reading /usr/sap/sapservices file. It expects # /usr/sap/sapservices file exists. # # Arguments: # (1) startupProfiles : A nameref for an array where startup profiles are # pushed into. # # Returns: # No. of Profiles #---------------------------------------------------------------------------- function getAllSAPInstanceStartupProfiles { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset -n profiles=$1 typeset ret=0 typeset tempProfiles tempProfiles=$(awk -F";" '/pf=/ {print $3}' $SAPSERVICESFILE | \ awk '{print $2}' - | awk -F"=" '{print $2}' 2>/dev/null) i=0 for p in $tempProfiles; do profiles[$i]=$p (( ret=$ret+1 )) (( i=$i+1 )) done return $ret } #---------------------------------------------------------------------------- # Function: # getInstanceNameFromProfile # # Purpose: # Gets the instancename for a given path to a profile. It needs to be called # after SAP env is setup by calling setSAPGlobalEnv # # Arguments: # (1) profile path. # # Returns: # Instance Name #---------------------------------------------------------------------------- function getInstanceNameFromProfile { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset profilePath=$1 typeset instanceName instanceName=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profilePath INSTANCE_NAME" 2>/dev/null) echo $instanceName return 0 } #---------------------------------------------------------------------------- # Function: # getAllRunningASInstances # # Purpose: # Gets the All the SAP instances of Application Instance type. # It needs to be called after SAP env is setup by calling setSAPGlobalEnv # # Arguments: # (1) A nameref for an array where instance names are pushed into. # # Returns: # All Valid Application Instances names are found from /usr/sap/sapservices file #---------------------------------------------------------------------------- function getAllRunningASInstances { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset -n allInstances=$1 typeset allProfiles typeset INSTANCE ret getAllSAPInstanceStartupProfiles allProfiles i=0 for p in "${!allProfiles[@]}"; do INSTANCE=$(getInstanceNameFromProfile ${allProfiles[$p]}) if [[ $INSTANCE == D* || $INSTANCE == J* ]]; then #Just to do some inspections of the found instance. if [ -f ${allProfiles[$p]} ]; then checkIsASInstanceRunningLocally ${allProfiles[$p]} ret=$? (( ret == 0 )) && allInstances[$i]=$INSTANCE (( i=$i+1 )) fi fi done } #---------------------------------------------------------------------------- # Function: # getAllRunningSCSInstances # # Purpose: # Gets the All the SAP instances of Central Services Instance type. # It needs to be called after SAP env is setup by calling setSAPGlobalEnv # # Arguments: # (1) A nameref for an array where instance names are pushed into. # # Returns: # All Valid SCS Instances names are found from /usr/sap/sapservices file #---------------------------------------------------------------------------- function getAllRunningSCSInstances { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset -n allInstances=$1 typeset allProfiles typeset INSTANCE ret getAllSAPInstanceStartupProfiles allProfiles i=0 for p in "${!allProfiles[@]}"; do INSTANCE=$(getInstanceNameFromProfile ${allProfiles[$p]}) if [[ $INSTANCE == ASCS* || $INSTANCE == SCS* ]]; then #Just to do some inspections of the found instance. if [ -f ${allProfiles[$p]} ]; then checkIsSCSInstanceRunningLocally ${allProfiles[$p]} ret=$? (( ret == 0 )) && allInstances[$i]=$INSTANCE (( i=$i+1 )) fi fi done } #---------------------------------------------------------------------------- # Function: # getAllRunningERSInstances # # Purpose: # Gets the All the SAP instances of Enqueue Replication Server Instance type. # It needs to be called after SAP env is setup by calling setSAPGlobalEnv # # Arguments: # (1) A nameref for an array where instance names are pushed into. # # Returns: # All Valid ERS Instances names are found from /usr/sap/sapservices file #---------------------------------------------------------------------------- function getAllRunningERSInstances { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset -n allInstances=$1 typeset allProfiles typeset INSTANCE getAllSAPInstanceStartupProfiles allProfiles i=0 for p in "${!allProfiles[@]}"; do INSTANCE=$(getInstanceNameFromProfile ${allProfiles[$p]}) if [[ $INSTANCE == ERS* ]]; then #Just to do some inspections of the found instance. if [ -f ${allProfiles[$p]} ]; then checkIsERSInstanceRunningLocally ${allProfiles[$p]} ret=$? (( ret == 0 )) && allInstances[$i]=$INSTANCE (( i++ )) fi fi done } #---------------------------------------------------------------------------- # Function: # checkIsSAPVersionOK # # Purpose: # Checks if we running SAP Netweaver version 2004s (aka SAP NW 7.0) or greater. # It needs to be called after SAP env is setup by calling setSAPGlobalEnv # # Arguments: # None. # # Returns: # 0 -> For yes # 1 -> For No #---------------------------------------------------------------------------- function checkIsSAPVersionOK { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset version if [[ -f $SAPEXEDIR/disp+work ]]; then exe_check=0 version=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/disp+work -version"|awk '/kernel release/ { print $3 }') if (( $version < 720 )); then valid_version=1 log_msg "Will exit Version for $SID is less than 720 which is not supported" return 1 fi return 0 else return 1 fi } #---------------------------------------------------------------------------- # Function: # checkIsASInstanceRunningLocally # # Purpose: # Checks if passed SAP Application instance is running locally or not. # # # Arguments: # 1. path to profile # # Returns: # 0 -> For yes # 1 -> For No #---------------------------------------------------------------------------- function checkIsASInstanceRunningLocally { [[ $VERBOSE_LOGGING == "high" ]] && set -x # Check first, if we have a running sapstartsrv process for this instance. # If not, we can't use sapcontrol to know the status. typeset profile=$1 typeset host instanceNo ret processDisplayStatus pids pid tempvar typeset -i count typeset -A allRunningProcess typeset tempOut TMPFILE=/tmp/env.$$ checkForRunningSapstartsrv $profile ret=$? if (( $ret != 0 )); then instanceNo=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPSYSTEM" 2>/dev/null) [[ -z $instanceNo ]] && return 1 tempvar=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ sapcontrol -nr $instanceNo -function GetVersionInfo" 2>/dev/null) ret=$? if (( $ret != 0 )); then return 1 else return 0 fi else host=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPLOCALHOST" 2>/dev/null) [[ -z $host ]] && return 1 instanceNo=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPSYSTEM" 2>/dev/null) [[ -z $instanceNo ]] && return 1 /usr/bin/su - $SAPADMNUSR -c "env LANG=C \ sapcontrol -host $host -nr $instanceNo -function GetProcessList \ -format script" > $TMPFILE 2>/dev/null pids=$(cat $TMPFILE | grep "[0-9] "|awk -F":" '/pid:/ {print $2}') rm -f $TMPFILE #To create a associate array tempOut=$(echo "(";ps -aeo pid,user | \ awk '{printf "[";printf $1;printf "]=";printf $2;printf " "}';echo ")") allRunningProcess=$(echo $tempOut) #check if any one of the process from sapcontrol is running here and #owned by SAPADMNUSR pid=0 for pid in "${!pids[@]}" do [[ ${allRunningProcess[${pids[$pid]}]} != $SAPADMNUSR ]] && return 0 done fi return 1 } #---------------------------------------------------------------------------- # Function: # checkIsSCSInstanceRunningLocally # # Purpose: # Checks if passed SAP SCS instance is running locally or not. # # Arguments: # None. # # Returns: # 0 -> For yes # 1 -> For No #---------------------------------------------------------------------------- function checkIsSCSInstanceRunningLocally { [[ $VERBOSE_LOGGING == "high" ]] && set -x # Check first, if we have a running sapstartsrv process for this instance. # If not, we can't use sapcontrol to know the status. typeset profile=$1 typeset host instanceNo ret processDisplayStatus pids pid tempvar typeset -i count typeset -A allRunningProcess typeset tempOut TMPFILE=/tmp/env.$$ checkForRunningSapstartsrv $profile ret=$? if (( $ret != 0 )); then instanceNo=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPSYSTEM" 2>/dev/null) [[ -z $instanceNo ]] && return 1 tempvar=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ sapcontrol -nr $instanceNo -function GetVersionInfo" 2>/dev/null) ret=$? if (( $ret != 0 )); then return 1 else return 0 fi else host=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPLOCALHOST" 2>/dev/null) [[ -z $host ]] && return 1 instanceNo=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPSYSTEM" 2>/dev/null) [[ -z $instanceNo ]] && return 1 /usr/bin/su - $SAPADMNUSR -c "env LANG=C \ sapcontrol -host $host -nr $instanceNo \ -function GetProcessList -format script" > $TMPFILE 2>/dev/null pids=$(cat $TMPFILE | grep "[0-9] "|awk -F":" '/pid:/ {print $2}') rm -f $TMPFILE #To create a associate array tempOut=$(echo "(";ps -aeo pid,user | \ awk '{printf "[";printf $1;printf "]=";printf $2;printf " "}';echo ")") allRunningProcess=$(echo $tempOut) #check if any one of the process from sapcontrol is running here and #owned by SAPADMNUSR pid=0 for pid in "${!pids[@]}" do [[ ${allRunningProcess[${pids[$pid]}]} != $SAPADMNUSR ]] && return 0 done fi return 1 } #---------------------------------------------------------------------------- # Function: # checkIsERSInstanceRunningLocally # # Purpose: # Checks if passed SAP ERS instance is running locally or not. # # Arguments: # None. # # Returns: # 0 -> For yes # 1 -> For No #---------------------------------------------------------------------------- function checkIsERSInstanceRunningLocally { [[ $VERBOSE_LOGGING == "high" ]] && set -x # Check first, if we have a running sapstartsrv process for this instance. # If not, we can't use sapcontrol to know the status. typeset profile=$1 typeset host instanceNo ret processDisplayStatus pids pid tempvar typeset -i count typeset -A allRunningProcess typeset tempOut TMPFILE=/tmp/env.$$ checkForRunningSapstartsrv $profile ret=$? if (( $ret != 0 )); then instanceNo=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPSYSTEM" 2>/dev/null) [[ -z $instanceNo ]] && return 1 tempvar=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ sapcontrol -nr $instanceNo -function GetVersionInfo" 2>/dev/null) ret=$? if (( $ret != 0 )); then return 1 else return 0 fi else host=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C \ $SAPEXEDIR/sappfpar pf=$profile SAPLOCALHOST" 2>/dev/null) [[ -z $host ]] && return 1 instanceNo=$(/usr/bin/su - $SAPADMNUSR -c "env LANG=C $SAPEXEDIR/sappfpar pf=$profile SAPSYSTEM" 2>/dev/null) [[ -z $instanceNo ]] && return 1 /usr/bin/su - $SAPADMNUSR -c "env LANG=C \ sapcontrol -host $host -nr $instanceNo \ -function GetProcessList -format script" > $TMPFILE 2>/dev/null pids=$(cat $TMPFILE | grep "[0-9] "|awk -F":" '/pid:/ {print $2}') rm -f $TMPFILE #To create a associate array tempOut=$(echo "(";ps -aeo pid,user | \ awk '{printf "[";printf $1;printf "]=";printf $2;printf " "}';echo ")") allRunningProcess=$(echo $tempOut) #check if any one of the process from sapcontrol is running here and #owned by SAPADMNUSR pid=0 for pid in "${!pids[@]}" do [[ ${allRunningProcess[${pids[$pid]}]} != $SAPADMNUSR ]] && return 0 done fi return 1 } #---------------------------------------------------------------------------- # Function: # checkForRunningSapstartsrv # # Purpose: # Checks if we have a sapstartsrv process running with a given profile # # Arguments: # None. # # Returns: # 0 -> For yes # 1 -> For No #---------------------------------------------------------------------------- function checkForRunningSapstartsrv { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset profile=$1 typeset ret profile=${profile//\//\\/} ps -aef | grep sapstartsrv | grep -q $profile > /dev/null ret=$? return $ret } #---------------------------------------------------------------------------- # Function: # isInTheList # # Purpose: # function to check if the value is in the list # # Arguments: # 1. Array by ref # 2. Value to be searched in the list # # Returns: # 0 -> For yes # 1 -> For No #---------------------------------------------------------------------------- function isInTheList { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset -n array=$1 value=$2 for element in ${array[@]}; do [[ "$element" == "$value" ]] && return 0 done return 1 } #---------------------------------------------------------------------------- # Function: # getResource # # Purpose: # Get the value of a particular resource type given the application name # # Arguments: # (1) Application Name # (2) Resource type (i.e. SERVICE_LABEL) # # Output: # List of resources defined to HACMP of the specified type # # Return: # 0 on success # 1 on failure #---------------------------------------------------------------------------- function getResource { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset appid=$1 typeset rName=$2 typeset RGS=$(getResourceGroups $appid) for rg in $RGS; do clmgr query resource_group $rg | grep $rName | \ awk -F= '{ print $2 }' | sed -e "s/\"//g" done } #---------------------------------------------------------------------------- # Function: # getResourceGroups # # Purpose: # Get a list of HACMP resource groups for the specified application name # # Arguments: # (1) Application Name # # Output: # List of HACMP resource groups # # Returns: # 0 on success # 1 on failure #---------------------------------------------------------------------------- function getResourceGroups { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset appid=$1 typeset name value odmget -q "sa_key=$appid" HACMPgroup | while IFS='=' read name value do name=$(echo $name) [[ "$name" == "group" ]] && { value=${value//\"/} echo $(echo $value) } done } #---------------------------------------------------------------------------- # Function: # getMetadata # # Purpose: # Get HACMPsa_metadata for a particular HACMP application, name name/value # pair. # # Arguments: # (1) Application Name # (2) Name of the name/value pair # # Output: # Value(s) of the name/value pair # # Return: # 0 on success # 1 on failure #---------------------------------------------------------------------------- function getMetadata { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset appid=$1 typeset name=$2 clquerysaapp -a $appid | grep $name | awk -F= '{ print $2 }' } #---------------------------------------------------------------------------- # Function: # getNodes # # Purpose: # Get a list of nodes from resource groups that belong to the application # # Arguments: # (1) Application Name # # Output: # List of nodes, list of nodes is ordered based on appearance in # participating node list. # # Returns: # 0 on success # 1 on failure #---------------------------------------------------------------------------- function getNodes { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset appid=$1 typeset arrNodes typeset RGS=$(getResourceGroups $appid) # # Get a list of nodes for the application, need to preserve the order # in which the nodes are presented in the resource group list(s) # for rg in $RGS; do set -a eval $(clmgr query resource_group $rg | grep NODES) set +a for nodeA in $NODES; do found=0 for nodeB in $arrNodes; do [[ "$nodeA" == "$nodeB" ]] && found=1 done (( $found == 0 )) && arrNodes="$arrNodes $nodeA" done done echo $arrNodes } #---------------------------------------------------------------------------- # Function: # stopsapstartsrv # # Purpose: # Stops sapstartsrv process running with a given profile # # Arguments: # None. # # Returns: # 0 -> for success # non zero -> for failure #---------------------------------------------------------------------------- function stopsapstartsrv { [[ $VERBOSE_LOGGING == "high" ]] && set -x typeset profile=$1 typeset ret pid profile=${profile//\//\\/} pid=$(ps -aef | grep sapstartsrv | grep $profile | awk '{print $2}') kill -9 $pid return $? } #---------------------------------------------------------------------------- # Function: # check_sapservices # # Purpose: # Verfies whether all the cluster nodes contain /usr/sap/sapservices # file and if contains checks if it is same on all nodes # # Arguments: # None. # # Returns: # None #---------------------------------------------------------------------------- function check_sapservices { typeset nodes=$(clmgr q nodes) typeset localnode=$(/usr/es/sbin/cluster/utilities/get_local_nodename 2>/dev/null) for node in $nodes do typeset sapservices_output sapservices_output=$(/usr/es/sbin/cluster/utilities/cl_rsh -n $node "ls -l /usr/sap/sapservices") if [[ -z $sapservices_output ]];then KLIB_SAP_SA_logmsg ERROR 120 27 sapsa.cat "/usr/sap/sapservices is not present in %s " $node exit 1 else if [[ $node == $localnode ]];then continue else /usr/es/sbin/cluster/utilities/cl_rcp $node:/usr/sap/sapservices /tmp/sapservices.$node if ! /usr/bin/diff /usr/sap/sapservices /tmp/sapservices.$node >/dev/null 2>&1 then KLIB_SAP_SA_logmsg ERROR 120 28 sapsa.cat "/usr/sap/sapservices is not same on nodes %1$s and %2$s \n" $localnode $node exit 1 fi fi fi done }