The purpose of the script library (scriptlib) is to simplify the FailSafe application interface so that users can use scripts and need not be aware of input and output file format.
The /var/cluster/ha/common_scripts/scriptlib file contains the library of environment variables (beginning with uppercase HA_) and functions (beginning with lowercase ha_) available for use in your action scripts.
![]() | Note: Do not change the contents of the scriptlib file. |
This chapter describes functions that perform the following tasks, using samples from the scriptlib file:
Set global definitions
Check arguments
Read an input file
Execute a command
Write status for a resource
Get the value for a field
Get resource information
Print exclusivity check messages
There are three file formats:
Input file, which contains the list of resources that must be acted on by the executable; each resource must be specified on a separate line in the file.
(Optional) Output file, in which the executable writes the return the status of each resource on a separate line, using the following format:
resource_name resource_status |
There are corresponding lines for each line in the input file. The resource_name and resource_status fields are separated by whitespace. The resource status may be one of the following:
HA_SUCCESS
HA_RUNNING
HA_NOT_RUNNING
HA_INVAL_ARGS
HA_CMD_FAILED
HA_NOTSUPPORTED
HA_NOCFGINFO (no configuration information)
If information about a resource is not present in the output file, SRMD assumes that the action on the resource has timed out. A nonzero value for the resource_status field is considered an error.
If the executable requires more information to perform the action on the resource, the information must be stored in the cluster database (CDB) in the local machine. The executables can use cluster database commands to extract information about the resource.
Input parameter file, which contains the cluster name in the following format:
ClusterName clustername |
The ha_set_global_defs() function sets the global definitions for the environment variables shown in the following subsections.
The HA_INFILE and HA_OUTFILE variables set the input and output files for a script. These variables do not have global definitions, and are not set by the ha_set_global_defs() function.
Determine the current logging level for scripts.
Default:
`${HA_PRIVCMDSPATH}/loggroupQuery _NUM_LOG_GROUPS=1 \ _LOG_GROUP_0=ha_script`
Successful execution of the script. This variable is used by the start, stop, restart, and monitor scripts.
Default: 0
A command called by the script has failed. This variable is used by the start, stop, restart , and monitor, scripts.
Default: 2
An action script can have an input file ($1 HA_INFILE), an output file ($2HA_OUTFILE), and a parameter file ($3 HA_PARAMFILE). The parameter file is optional.
The ha_check_args() function checks the arguments specified for a script and sets the $HA_INFILE and $HA_OUTFILE variables accordingly.
If a parameter file exists, the ha_check_args() function reads the list of parameters from the file and sets the $HA_CLUSTERNAME variable.
In the following, long lines use the continuation character ( \) for readability.
ha_check_args() { ${HA_DBGLOG} "$HA_SCRIPTNAME called with $1, $2 and $3" if ! [ $# -eq 2 -o $# -eq 3 ]; then ${HA_LOG} "Incorrect number of arguments" return 1; fi if [ ! -r $1 ]; then ${HA_LOG} "file $1 is not readable or does not exist" return 1; fi if [ ! -s $1 ]; then ${HA_LOG} "file $1 is empty" return 1; fi if [ $# -eq 3 ]; then HA_PARAMFILE=$3 if [ ! -r $3 ]; then ${HA_LOG} "file $3 is not readable or does not exist" return 1; fi HA_CLUSTERNAME=`/usr/bin/awk '{ if ( $1 == "ClusterName" ) \ print $2 }' ${HA_PARAMFILE}` fi HA_INFILE=$1 HA_OUTFILE=$2 return 0; } |
The ha_read_infile() function reads the $HA_INFILE input file into the $HA_RES_NAMES variable, which specifies the list of resource names.
ha_read_infile() { HA_RES_NAMES=""; for HA_RESOURCE in `cat ${HA_INFILE}` do HA_TMP="${HA_RES_NAMES} ${HA_RESOURCE}"; HA_RES_NAMES=${HA_TMP}; done } |
The ha_execute_cmd() function executes the command specified by $HA_CMD, which is set in the action script. $1 is the string to be logged. The function returns 1 on error and 0 on success. On errors, the standard output and standard error of the command is redirected to the log file.
ha_execute_cmd() { OUTFILE=${HA_SCRIPTTMPDIR}/script.$$ ${HA_DBGLOG} $1 eval ${HA_CMD} > ${OUTFILE} 2>&1; ha_exit_code=$?; if [ $ha_exit_code -ne 0 ]; then ${HA_DBGLOG} `cat ${HA_SCRIPTTMPDIR}/script.$$` fi ${HA_DBGLOG} "${HA_CMD} exited with status $ha_exit_code"; /sbin/rm ${OUTFILE} return $ha_exit_code; } |
The ha_execute_cmd_ret() function is similar to ha_execute_cmd, except that it places the command output in the location specified by $HA_CMD_OUTPUT.
ha_execute_cmd_ret() { ${HA_DBGLOG} $1 # REVISIT: Is it possible to redirect the output to a log HA_CMD_OUTPUT=`${HA_CMD}`; ha_exit_code=$?; ${HA_DBGLOG} "${HA_CMD} exited with status $ha_exit_code"; return $ha_exit_code; } |
The ha_write_status_for_resource() function writes the status for a resource to the $HA_OUTFILE output file. $1 is the resource name, and $2 is the resource status.
ha_write_status_for_resource() { echo $1 $2 >> $HA_OUTFILE; } |
Similarly, the ha_write_status_for_all_resources() function writes the status for all resources. $HA_RES_NAMES is the list of resource names.
ha_write_status_for_all_resources() { for HA_RES in $HA_RES_NAMES do echo $HA_RES $1 >> $HA_OUTFILE; done } |
The ha_get_field() function obtains the field value from a string, where $1 is the string and $2 is the field name. The string format is as follows:
ha_get_field() { HA_STR=$1 HA_FIELD_NAME=$2 ha_found=0; ha_field=1; for ha_i in $HA_STR do if [ $ha_field -eq 1 ]; then ha_field=0; if [ $ha_i = $HA_FIELD_NAME ]; then ha_found=1; fi else ha_field=1; if [ $ha_found -eq 1 ]; then HA_FIELD_VALUE=$ha_i return 0; fi fi done return 1; } |
The ha_get_multi_fields() function obtains the field values from a string, where $1 is the string and $2 is the field name. The string format is a series of name-value field pairs, where a name field is followed by the value of the name, separated by whitespace.
This function is typically used to extract dependency information. There may be multiple fields with the same name, so the string returned in HA_FIELD_VALUE may contain multiple values separated by white space. This appears as follows:
ha_get_multi_fields() { HA_STR=$1 HA_FIELD_NAME=$2 ha_found=0; ha_field=1; for ha_i in $HA_STR do if [ $ha_field -eq 1 ]; then ha_field=0; if [ $ha_i = $HA_FIELD_NAME ]; then ha_found=1; fi else ha_field=1; if [ $ha_found -eq 1 ]; then if [ -z "$HA_FIELD_VALUE" ]; then HA_FIELD_VALUE=$ha_i; else HA_FIELD_VALUE="$HA_FIELD_VALUE $ha_i"; fi; ha_found=0; fi fi done if [ -z "$HA_FIELD_VALUE" ]; then return 1; else return 0; fi } |
The ha_get_info() and ha_get_info_debug()functions read resource information. $1 is the resource type, $2 is the resource name, and $3 is an optional parameter of any value that specifies a request for resource dependency information. Resource information is stored in the HA_STRING variable. If the resourceQuery command fails, the HA_STRING is set to an invalid string, and future calls to ha_get_info() or ha_get_info_debug() return errors.
You can use ha_get_info_debug() while developing scripts.
ha_get_info() { if [ -f /var/cluster/ha/resourceQuery.debug ]; then ha_get_info_debug $1 $2 $3 return; fi if [ -n "$3" ]; then ha_doall="_ALL=true" else ha_doall="" fi # Retry resourceQuery command $HA_RETRY_CMD_MAX times if $HA_RETRY_CMD_ERR # is returned. ha_retry_count=1 while [ $ha_retry_count -le $HA_RETRY_CMD_MAX ]; do if [ -n "${HA_CLUSTERNAME}" ]; then HA_STRING=`${HA_PRIVCMDSPATH}/${HA_RESOURCEQUERYCMD} \ _CDB_DB=$HA_CDB _RESOURCE=$2 _RESOURCE_TYPE=$1 \ $ha_doall _NO_LOGGING=true _CLUSTER=${HA_CLUSTERNAME}` else HA_STRING=`${HA_PRIVCMDSPATH}/${HA_RESOURCEQUERYCMD} \ _CDB_DB=$HA_CDB _RESOURCE=$2 _RESOURCE_TYPE=$1 \ $ha_doall _NO_LOGGING=true` fi ha_exit_code=$? if [ $ha_exit_code -ne 0 ]; then ${HA_LOG} "${HA_RESOURCEQUERYCMD}: resource name $2 resource type $1" ${HA_LOG} "Failed with error: ${HA_STRING}"; fi if [ $ha_exit_code -ne $HA_RETRY_CMD_ERR ]; then break; fi ha_retry_count=`expr $ha_retry_count + 1` done if [ -n "$ha_doall" ]; then echo $HA_STRING \ | grep "No resource dependencies" > /dev/null 2>&1 if [ $? -eq 0 ]; then HA_STRING= else HA_STRING=`echo $HA_STRING | /bin/sed -e "s/^.*Resource dependencies //"` fi fi return ${ha_exit_code}; } |
The ha_get_info is a faster version of ha_get_info_debug().
ha_get_info_debug() { if [ -n "$3" ]; then ha_doall="_ALL=true" else ha_doall="" fi if [ -n "${HA_CLUSTERNAME}" ]; then HA_STRING=`${HA_PRIVCMDSPATH}/${HA_RESOURCEQUERYCMD} \ _CDB_DB=$HA_CDB _RESOURCE=$2 _RESOURCE_TYPE=$1 \ $ha_doall _CLUSTER=${HA_CLUSTERNAME}` else HA_STRING=`${HA_PRIVCMDSPATH}/${HA_RESOURCEQUERYCMD} \ _CDB_DB=$HA_CDB _RESOURCE=$2 _RESOURCE_TYPE=$1 $ha_doall` fi ha_exit_code=$? if [ $? -ne 0 ]; then ${HA_LOG} "${HA_RESOURCEQUERYCMD}: resource name $2 resource type $1" ${HA_LOG} "Failed with error: ${HA_STRING}"; fi if [ -n "$ha_doall" ]; then echo $HA_STRING \ | grep "No resource dependencies" > /dev/null 2>&1 if [ $? -eq 0 ]; then HA_STRING= else HA_STRING=`echo $HA_STRING | /bin/sed -e "s/^.*Resource dependencies //"` fi fi return ${ha_exit_code}; } |
The ha_print_exclusive_status() function prints exclusivity check messages to the log file. $1 is the resource name and $2 is the exit status.
ha_print_exclusive_status() { if [ $? -eq $HA_NOT_RUNNING ]; then ${HA_LOG} "resource $1 exclusive status: NOT RUNNING" else ${HA_LOG} "resource $1 exclusive status: RUNNING" fi } |
The ha_print_exclusive_status_all_resources() function is similar, but it prints exclusivity check messages for all resources. $HA_RES_NAMES is the list of resource names.
ha_print_exclusive_status_all_resources() { for HA_RES in $HA_RES_NAMES do ha_print_exclusive_status ${HA_RES} $1 done } |