# @(#) 71c643f 43haes/usr/sbin/cluster/sa/maxdb/sbin/DBUtilities.sh, 726, 2147A_aha726, May 26 2021 10:50 PM # ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2017,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # #This file will be sourced in other files. No executable code in this file. # Load the common clmgr/clvt functions library . /usr/es/lib/ksh93/func_include #--------------------------------------------------------------------------- # Global Definitions #--------------------------------------------------------------------------- . /usr/es/sbin/cluster/sa/maxdb/sbin/DBGlobals #--------------------------------------------------------------------------- # Function: # setDBEnvs # # Purpose: # Sets variables relating to an instance that all other can functions use. # # Arguments: # (1) path: MaxDB Program Path # Optional (2) Application id: MaxDB Instance Application id to retreive version information # # Returns: # Exit with 1 for any problem #--------------------------------------------------------------------------- function setDBEnvs { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x #Use the argument supplied, if not find the path where MaxDB software is installed. if [[ ! -z $1 ]]; then KLIB_SA_logmsg TRACE 30 1 maxdbsa.cat "\"%1\$s\" : Using an already avaialble MAXDB_PROGRAM_PATH" $PROGRAM MAXDB_PROGRAM_PATH=$1 else MAXDB_PROGRAM_PATH=$(findMaxDBProgramPath) KLIB_SA_logmsg TRACE 30 2 maxdbsa.cat "\"%1\$s\" : setting MAXDB_PROGRAM_PATH to \"%2\$s\"" $PROGRAM $MAXDB_PROGRAM_PATH fi #Find out the MaxDB version for specific instance if [[ -n $2 ]] then APP_ID=$2 instanceName=$(clquerysaapp -a $APP_ID 2>/dev/null | awk -F"=" '$1 == "INSTANCE" {print $2}') MAXDB_VERSION=$(${MAXDB_PROGRAM_PATH}/bin/sdbregview | grep -w "$instanceName" | awk '{print $3}') fi #Set the path to dbmcli (Database command line utility) DBMCLI_COMMAND=$MAXDB_PROGRAM_PATH/bin/dbmcli [[ -n $DBMCLI_COMMAND && -x $DBMCLI_COMMAND ]] && { KLIB_SA_logmsg INFO 30 3 maxdbsa.cat "dbmcli command is available at : \"%1\$s\"" $DBMCLI_COMMAND } || { KLIB_SA_logmsg ERROR 30 4 maxdbsa.cat "Unable to locate dbmcli command or dbmcli is not executable" exit 1 } #Export the variables PATH=$MAXDB_PROGRAM_PATH/bin:$PATH myUsr=$(whoami) HOME=$(lsuser -a home ${myUsr} | cut -d= -f2) export HOME PATH MAXDB_PROGRAM_PATH DBMCLI_COMMAND if [[ -n $MAXDB_VERSION ]] then KLIB_SA_logmsg TRACE 30 5 maxdbsa.cat "MaxDB Version is \"%1\$s\"" $MAXDB_VERSION export MAXDB_VERSION fi } #--------------------------------------------------------------------------- # Function: # setHSDBEnvs # # Purpose: # Sets variables relating to a Hot Standby instance that all other can functions use. # # Arguments: # (1) Instance Role : PRIMARY or AUXILIARY # (2) Instance Name : SID of the instance # # Returns: # Exit with 1 for any problem #--------------------------------------------------------------------------- setHSDBEnvs (){ [[ "$VERBOSE_LOGGING" == "high" ]] && set -x MAXDB_PROGRAM_PATH=$(findMaxDBProgramPath) typeset instanceName=$2 dspmsg -s 30 maxdbsa.cat 2 "\"%1\$s\" : setting MAXDB_PROGRAM_PATH to \"%2\$s\" \n" $PROGRAM $MAXDB_PROGRAM_PATH [[ $1 = "PRIMARY" ]] && { APPLICATION_ID="liveCache_Primary_"$instanceName; } || { APPLICATION_ID="liveCache_Standby_"$instanceName; } MASTER_APP_ID="liveCache_Primary_"$instanceName; #Set the path to dbmcli (Database command line utility) DBMCLI_COMMAND=$MAXDB_PROGRAM_PATH/bin/dbmcli [[ -n $DBMCLI_COMMAND && -x $DBMCLI_COMMAND ]] && { dspmsg -s 30 maxdbsa.cat 3 "dbmcli command is available at : \"%1\$s\" \n" $DBMCLI_COMMAND } || { dspmsg -s 30 maxdbsa.cat 4 "Unable to locate dbmcli command or dbmcli is not executable" exit 1 } #Ensure that we are running MaxDB 7.7 #version=$(LC_ALL=C $MAXDB_PROGRAM_PATH/bin/sdbregview -l | grep "Database Kernel" | tr -s " " | cut -d" " -f4) #[[ $version == 7\.7\.* ]] && { # dspmsg -s 30 maxdbsa.cat 5 "MaxDB Version is \"%1\$s\" \n" $version #} || { # KLIB_SA_logmsg WARN 30 6 maxdbsa.cat "MaxDB version \"%1\$s\" is found. Only MaxDB version 7.7.x.x is supported" $version #} # Get Lock Directory from ODM LOCKFILE_DIR=$(getMetadata $APPLICATION_ID LC_LOCK_DIR) master="as_primary_"$instanceName standby="as_standby_"$instanceName APPMON_MASTER="$master $standby" ### Sleep and retry parameters for timeout function. typeset -A TIMEOUT=( [lc_monitor_startup]="30 10" [sap_lc_move_wait_for_clusterstate_stable]="30 10" [lc_wait_long_in_startup_of_master]="10" [lc_wait_short_in_startup_of_master]="2" [lc_wait_med_in_stop_of_master]="5" ) export OK=0 export TIME_LOG=1 export ERROR=1 export WARNING=2 export ONLINE=0 export OFFLINE=2 export DEV_NULL="/dev/null" LCADM=$(findMaxDBOwnerUID) NODES=$(getNodes $APPLICATION_ID) LCSERVER=`print $NODES | awk '{ print $1}'` TAKEOVER=`print $NODES | awk ' { print $2}'` LCSERVER_IP=$(getResource $MASTER_APP_ID SERVICE_LABEL) LCSERVER_DB_IP=$LCSERVER STANDBY_DB_IP=$TAKEOVER set +x CONTROL_LOGIN="-U $(getMetadata $APPLICATION_ID INSTANCE_DBM_USERID)" #above the -U is added to encapsulate th echange to have a fallback strategy done in a single place. set -x LOCKFILE_DIR=$(getMetadata $APPLICATION_ID LC_LOCK_DIR) LC_MONITOR="SERVICE" #Export the variables PATH=$MAXDB_PROGRAM_PATH/bin:$PATH myUsr=$(whoami) HOME=$(lsuser -a home ${myUsr} | cut -d= -f2) export HOME PATH MAXDB_PROGRAM_PATH DBMCLI_COMMAND LCADM CONTROL_LOGIN export LCSERVER TAKEOVER LCSERVER_IP LCSERVER_DB_IP STANDBY_DB_IP LOCKFILE_DIR LC_MONITOR export RC_FOR_FAILED_MASTER_db_online=0 #desired RC if startscript of Master does not bring the db online default is 0 --> nt sure. export LCBIN=$MAXDB_PROGRAM_PATH/bin } #---------------------------------------------------------------------------- # 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 set +x odmget -q "application_id=$appid and name=$name" HACMPsa_metadata | grep value | awk -F= '{ print $2 }' | sed 's/^[ \t]*//;s/"//g' set -x } #--------------------------------------------------------------------------- # Function: # findMaxDBProgramPath # # Purpose: # Discover and set MAXDB_PROGRAM_PATH # # Arguments: # none # # Returns: # Exit with 1 for any problem #--------------------------------------------------------------------------- function findMaxDBProgramPath { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x [[ ! -f /etc/opt/sdb ]] && { KLIB_SA_logmsg ERROR 30 7 "No MaxDB installation found on this node. Can't proceed" exit 1 } # Parse /etc/opt/sdb file to know where the MaxDB Software is installed. This file is created # by the MaxDB installation process and need to be available for it to run. MAXDB_PROGRAM_PATH=$(grep IndepPrograms /etc/opt/sdb | cut -d "=" -f2) [[ -z $MAXDB_PROGRAM_PATH ]] && { KLIB_SA_logmsg ERROR 30 8 maxdbsa.cat "Unable to read IndepPrograms value from /etc/opt/sdb. Can't proceed" exit 1 } echo $MAXDB_PROGRAM_PATH } #--------------------------------------------------------------------------- # Function: # findDBInstances # # Purpose: # Discovers all the running MaxDB instances. Assumes environment is setup. # # Arguments: # none # # Returns: # none #--------------------------------------------------------------------------- function findDBInstances { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset -n instances=$1 if [ -z $DBMCLI_COMMAND ]; then KLIB_SA_logmsg DEBUG 30 9 maxdbsa.cat "DBMCLI_COMMAND is not set. Unable to find any database instances" else list=$(LC_ALL=C $DBMCLI_COMMAND db_enum | awk '$4 == "fast" && $5 == "running" {print $1}' | uniq 2>/dev/null) typeset f i i=0 if [[ -n $XUSER ]] then for f in $list; do result=$(LC_ALL=C $DBMCLI_COMMAND -U $XUSER -c -d $f hss_getnodes) if [[ $? -eq 0 ]] then output=`echo "$result" | /usr/bin/awk '!/OK/ {print $1}' ` [[ ! -z $output ]] && { instances[$i]=$f (( ret=$ret+1 )) (( i=$i+1 )); } fi done else for f in $list; do instances[$i]=$f (( ret=$ret+1 )) (( i=$i+1 )) done fi fi } #--------------------------------------------------------------------------- # Function: # findServiceIP # # Purpose: # Discovers service IP for the MaxDB installation. # # Arguments: # none # # Returns: # none #--------------------------------------------------------------------------- function findServiceIP { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset serviceIP MAXDB_PROGRAM_PATH=$1 setDBEnvs $MAXDB_PROGRAM_PATH serviceIP=$(LC_ALL=C $MAXDB_PROGRAM_PATH/bin/sdbinfo 2>/dev/null | awk '/System name/ {getline;print}') echo $serviceIP } #--------------------------------------------------------------------------- # Function: # findHotStandbyServiceIP # # Purpose: # Discovers service IP of the liveCache Hot Standby instance # # Arguments: # none # # Returns: # none #--------------------------------------------------------------------------- function findHotStandbyServiceIP { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset serviceIP MAXDB_PROGRAM_PATH=$1 setDBEnvs $MAXDB_PROGRAM_PATH serviceIP=$($DBMCLI_COMMAND -U $XUSER -c -d $instanceName param_getvalue OfficialNodeName | /usr/bin/awk '!/OK/ {print $1}' | tr "[A-Z]" "[a-z]") echo $serviceIP } #--------------------------------------------------------------------------- # Function: # findVolumeGroups # # Purpose: # Discovers all the shared vgs used for the passed Instance # # Arguments: # instanceName # # Returns: # none #--------------------------------------------------------------------------- function findVolumeGroups { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset vgName typeset instance=$1 typeset -A configDirs typeset -A configVGs typeset pvid shared_vgs maxdb_ver [[ -z $instance ]] && { KLIB_SA_logmsg DEBUG 30 10 "Instance name is not specified for discovering Volume Gorups" echo "" return } setDBEnvs $MAXDB_PROGRAM_PATH #Perform cluster wide volume group discovery.\n" KLIB_SA_logmsg INFO 30 11 maxdbsa.cat "Performing cluster wide volume group discovery.\n" #Retrieve all the maxdb directories using maxdb command xinstinfo maxdbDirs=$($MAXDB_PROGRAM_PATH/bin/xinstinfo $instance | awk '{print $1}' | grep -v "Kernel") for loc in $maxdbDirs do configDirs[$loc]=$(LC_ALL=C $MAXDB_PROGRAM_PATH/bin/xinstinfo $instance | tr -s " " | grep $loc | cut -d":" -f2) configVGs[$loc]=$(KLIB_AIX_get_vg_by_path "${configDirs[$loc]}") if [[ -n ${configVGs[$loc]} ]] then KLIB_SA_logmsg INFO 30 12 maxdbsa.cat "MaxDB config location \"%1\$s\" is on \"%2\$s\" Volume Group" $loc ${configVGs[$loc]} pvid=$(KLIB_AIX_get_pvids_by_vgs "${configVGs[$loc]}") KLIB_HACMP_are_pvids_shared "$pvid" [[ $? == 0 ]] && { shared_vgs="$shared_vgs ${configVGs[$loc]}" } fi done echo $shared_vgs } #--------------------------------------------------------------------------- # Function: # findDataVolumeGroups # # Purpose: # Discovers data volumes vgs used of the passed Instance # # Arguments: # instanceName # # Returns: # none #--------------------------------------------------------------------------- function findDataVolumeGroups { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset instance=$1 [[ -z $instance ]] && { KLIB_SA_logmsg DEBUG 30 10 "Instance name is not specified for discovering Volume Gorups" echo "" return } setDBEnvs $MAXDB_PROGRAM_PATH datalv=`$DBMCLI_COMMAND -U $XUSER -c -d $instanceName param_getvalue DataVolumeName0001 | /usr/bin/awk -F "/dev/r" '{print $2}'` datavg=`/usr/es/sbin/cluster/utilities/clgetvg -l $datalv` echo $datavg } #--------------------------------------------------------------------------- # Function: # findLogVolumeGroups # # Purpose: # Discovers log volumes vgs used of the passed Instance # # Arguments: # instanceName # # Returns: # none #--------------------------------------------------------------------------- function findLogVolumeGroups { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset instance=$1 [[ -z $instance ]] && { KLIB_SA_logmsg DEBUG 30 10 "Instance name is not specified for discovering Volume Gorups" echo "" return } setDBEnvs $MAXDB_PROGRAM_PATH loglv=`$DBMCLI_COMMAND -U $XUSER -c -d $instanceName param_getvalue LogVolumeName001 | /usr/bin/awk -F "/dev/r" '{print $2}'` logvg=`/usr/es/sbin/cluster/utilities/clgetvg -l $loglv` echo $logvg } #--------------------------------------------------------------------------- # Function: # findMaxDBOwnerUID # # Purpose: # Discovers all the user ID of the MaxDB Software # # Arguments: # none # # Returns: # 1 on error #--------------------------------------------------------------------------- function findMaxDBOwnerUID { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x KLIB_OUTPUT_CONSOLE=false typeset userID setDBEnvs $MAXDB_PROGRAM_PATH userID=$(grep SdbOwner /etc/opt/sdb 2>/dev/null | cut -d "=" -f2) [[ -z $userID ]] && { KLIB_SA_logmsg ERROR 30 13 maxdbsa.cat "Unable to read SdbOwner value from /etc/opt/sdb. Can't proceed" return 1 } echo $userID } #--------------------------------------------------------------------------- # Function: # findMaxDBOwnerGID # # Purpose: # Discovers all the group ID of the MaxDB Software # # Arguments: # none # # Returns: # 1 on error #--------------------------------------------------------------------------- function findMaxDBOwnerGID { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x KLIB_OUTPUT_CONSOLE=false typeset groupID setDBEnvs $MAXDB_PROGRAM_PATH groupID=$(grep SdbGroup /etc/opt/sdb 2>/dev/null | cut -d "=" -f2) [[ -z $groupID ]] && { KLIB_SA_logmsg ERROR 30 14 maxdbsa.cat "Unable to read SdbGroup value from /etc/opt/sdb. Can't proceed" return 1 } echo $groupID } #---------------------------------------------------------------------------- # Function: # getResourceGroups # # Purpose: # Get a list of PowerHA SystemMirror resource groups for the specified application name # # Arguments: # (1) Application Name # # Output: # List of PowerHA SystemMirror resource groups # # Returns: # none #---------------------------------------------------------------------------- function getResourceGroups { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset appid=$1 typeset rgs="" rgs=$(clodmget -n -q "application_id=$appid and name=RESOURCE_GROUP" -f value HACMPsa_metadata) echo $rgs } #---------------------------------------------------------------------------- # 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: # none #--------------------------------------------------------------------------- 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 NODES=$(clodmget -n -q "group =$rg" -f nodes HACMPgroup) 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: # 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: # none #--------------------------------------------------------------------------- function getResource { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset appid=$1 typeset rName=$2 typeset res="" res=$(clodmget -n -q "application_id=$appid and name=$rName" -f value HACMPsa_metadata) echo $res } #---------------------------------------------------------------------------- # Function: # removeHAComponents # # Purpose: # Removes all the PowerHA SystemMirror Objects created for this instance # # Arguments: # (1) Application ID # (2) instanceName # # Output: # # Return: # none #--------------------------------------------------------------------------- function removeHAComponents { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x typeset appid=$1 typeset instanceName=$2 typeset -i MAXDB_APP_COUNT=0 typeset -i ERR=0 for app in $(getResource $appid APPLICATION_CONTROLLER); do MONITORS=$(clmgr query application $app 2>/dev/null | grep MONITORS | awk -F= '{ print $2 }' | sed -e "s/\"//g") for monitor in $MONITORS; do KLIB_SA_logmsg INFO 30 16 maxdbsa.cat "Deleting Application Monitor : \"%1\$s\"" $monitor clmgr delete application_monitor $monitor >/dev/null 2>&1 (( $? != 0 )) && { KLIB_SA_logmsg ERROR 30 15 maxdbsa.cat "Unable to delete Application Monitror : \"%1\$s\"" $monitor ERR=1 } done KLIB_SA_logmsg INFO 30 24 maxdbsa.cat "Deleting Application Server : \"%1\$s\"" $app clmgr delete application $app > /dev/null 2>&1 (( $? != 0 )) && { KLIB_SA_logmsg ERROR 30 17 maxdbsa.cat "Unable to delete Application Server : \"%1\$s\"" $app KLIB_SA_logmsg INFO 30 18 maxdbsa.cat "Please do a verify and sync from another node in the cluster to restore previous configuration." ERR=1 } #Deleting the serviceIP of the application as modified service-ip will be added to application while recreating the instance. typeset serviceIP=$(clquerysaapp -a $appid 2>/dev/null | awk -F"=" '$1 == "SERVICE_LABEL" {print $2}') clmgr delete service_ip $serviceIP >/dev/null 2>&1 (( $? != 0 )) && { KLIB_SA_logmsg ERROR 30 25 maxdbsa.cat "Unable to delete service IP label : \"%1\$s\"" $serviceIP KLIB_SA_logmsg INFO 30 18 maxdbsa.cat "Please do a verify and sync from another node in the cluster to restore previous configuration." ERR=1 } done for rg in $(getResourceGroups $appid); do MAXDB_APP_COUNT=$(clodmget -n -q "group=$rg and name=APPLICATIONS" -f value HACMPresource | wc -l) #As one RG can have mulitple applications, RG should be deleted only when no applications are associated with it. if (( $MAXDB_APP_COUNT == 0 ));then KLIB_SA_logmsg INFO 30 19 maxdbsa.cat "Deleting Resource Group : \"%1\$s\"" $rg clmgr delete resource_group $rg >/dev/null 2>&1 (( $? != 0 )) && { KLIB_SA_logmsg ERROR 30 20 maxdbsa.cat "Unable to delete Resource Group : \"%1\$s\"" $rg KLIB_SA_logmsg INFO 30 18 maxdbsa.cat "Please do a verify and sync from another node in the cluster to restore previous configuration." ERR=1 } fi done #Remove File collection for Instance related files fileCollectionName=$instanceName"_instFiles" clmgr query file_collection $fileCollectionName >/dev/null 2>&1 (( $? == 0 )) && { KLIB_SA_logmsg INFO 30 21 maxdbsa.cat "Deleting File Collection : \"%1\$s\"" $fileCollectionName clmgr delete file_collection $fileCollectionName >/dev/null 2>&1 } #Remove File collection for verification related file fileCollectionName=$instanceName"_verifyFiles" clmgr query file_collection $fileCollectionName >/dev/null 2>&1 (( $? == 0 )) && { KLIB_SA_logmsg INFO 30 21 maxdbsa.cat "Deleting File Collection : \"%1\$s\"" $fileCollectionName clmgr delete file_collection $fileCollectionName >/dev/null 2>&1 } # Remove the application (SA) references for this instance KLIB_SA_logmsg INFO 30 22 maxdbsa.cat "Unregistering the application id : \"%1\$s\" from Smart Assist Framework" $appid clrmsaapp -a $appid (( $? != 0 )) && { KLIB_SA_logmsg ERROR 30 23 maxdbsa.cat "Unable to unregister application with Smart Assist framework" KLIB_SA_logmsg INFO 30 18 maxdbsa.cat "Please do a verify and sync from another node in the cluster to restore previous configuration." ERR=1 } if (( $ERR == 1 ));then exit 1 fi return 0 }