Thursday, September 7, 2023
#!/bin/bash
#
# GI callout script to catch INSTANCE up event from clusterware and relocate services to preferred instance
# Copy or symlink this script to $GRID_HOME/racg/usrco
# 2012 Ilmar Kerm
#
LOGFILE=/u02/app/oracle/grid_callout/log.txt
SCRIPTDIR=`dirname $0`
# Determine grid home
if [[ "${SCRIPTDIR:(-11)}" == "/racg/usrco" ]]; then
CRS_HOME="${SCRIPTDIR:0:$(( ${#SCRIPTDIR} - 11 ))}"
export CRS_HOME
fi
# Only execute script for INSTANCE events
if [ "$1" != "INSTANCE" ]; then
exit 0
fi
STATUS=""
DATABASE=""
INSTANCE=""
# Parse input arguments
args=("$@")
for arg in ${args[@]}; do
if [[ "$arg" == *=* ]]; then
KEY=${arg%=*}
VALUE=${arg#*=}
case "$KEY" in
status)
STATUS="$VALUE"
;;
database)
DATABASE="$VALUE"
;;
instance)
INSTANCE="$VALUE"
;;
esac
fi
done
# If database, status and instance values are not set, then exit
# status must be up
if [[ -z "$DATABASE" || -z "$INSTANCE" || "$STATUS" != "up" ]]; then
exit 0
fi
echo "`date`" >> "$LOGFILE"
echo "[$DATABASE][`hostname`] Instance $INSTANCE up" >> "$LOGFILE"
#
# Read database software home directory from clusterware
#
DBCONFIG=`$CRS_HOME/bin/crsctl status res ora.$DATABASE.db -f | grep "ORACLE_HOME="`
if [ -z "$DBCONFIG" ]; then
exit 0
fi
declare -r "$DBCONFIG"
echo "ORACLE_HOME=$ORACLE_HOME" >> "$LOGFILE"
# Array function
in_array() {
local hay needle=$1
shift
for hay; do
[[ $hay == $needle ]] && return 0
done
return 1
}
#
# Read information about services
#
for service in `$CRS_HOME/bin/crsctl status res | grep -E "ora\.$DATABASE\.(.+)\.svc" | sed -rne "s/NAME=ora\.$DATABASE\.(.+)\.svc/\1/gip"`; do
SERVICECONFIG=`$ORACLE_HOME/bin/srvctl config service -d $DATABASE -s $service`
echo "Service $service" >> "$LOGFILE"
if [[ "$SERVICECONFIG" == *"Service is enabled"* ]]; then
echo " enabled" >> "$LOGFILE"
PREFERRED=( `echo "$SERVICECONFIG" | grep "Preferred instances:" | sed -rne "s/.*\: ([a-zA-Z0-9]+)/\1/p" | tr "," "\n"` )
#
# Check if current instance is preferred for this service
#
if in_array "$INSTANCE" "${PREFERRED[@]}" ; then
echo " preferred" >> "$LOGFILE"
#
# Check if service is already running on current instance
#
SRVSTATUS=`$ORACLE_HOME/bin/srvctl status service -d $DATABASE -s $service`
if [[ "$SRVSTATUS" == *"is not running"* ]]; then
#
# if service is not running, then start it
#
echo " service stopped, starting" >> "$LOGFILE"
$ORACLE_HOME/bin/srvctl start service -d "$DATABASE" -s "$service" >> "$LOGFILE"
else
#
# Service is running, but is it running on preferred instance?
#
RUNNING=( `echo "$SRVSTATUS" | sed -rne "s/.* ([a-zA-Z0-9]+)/\1/p" | tr "," "\n"` )
# echo "${RUNNING[@]} = ${PREFERRED[@]}"
if ! in_array "$INSTANCE" "${RUNNING[@]}" ; then
echo " not running on preferred $INSTANCE" >> "$LOGFILE"
#
# Find the first non-preferred running instance
#
CURRENT=""
for inst in "${RUNNING[@]}"; do
if ! in_array "$inst" "${PREFERRED[@]}" ; then
CURRENT="$inst"
break
fi
done
#
# Relocate
#
if [[ -n "$CURRENT" ]]; then
echo " relocate $CURRENT -> $INSTANCE" >> "$LOGFILE"
$ORACLE_HOME/bin/srvctl relocate service -d "$DATABASE" -s "$service" -i "$CURRENT" -t "$INSTANCE" >> "$LOGFILE"
fi
else
#
# Service is already running on preferred instance, no need to do anything
#
echo " running on preferred $INSTANCE" >> "$LOGFILE"
fi
fi
fi
fi
done