diff --git a/heartbeat/ClusterMon b/heartbeat/ClusterMon index 1d45ff47e..2bbf87da4 100755 --- a/heartbeat/ClusterMon +++ b/heartbeat/ClusterMon @@ -1,271 +1,271 @@ #!/bin/sh # # # ClusterMon OCF RA. # Starts crm_mon in background which logs cluster status as # html to the specified file. # # Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Bree # All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # # OCF instance parameters: # OCF_RESKEY_user # OCF_RESKEY_pidfile # OCF_RESKEY_update # OCF_RESKEY_extra_options # OCF_RESKEY_htmlfile ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs # Parameter defaults OCF_RESKEY_user_default="root" OCF_RESKEY_update_default="15000" OCF_RESKEY_extra_options_default="" -OCF_RESKEY_pidfile_default="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid" -OCF_RESKEY_htmlfile_default="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html" +OCF_RESKEY_pidfile_default="${HA_RSCTMP}/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid" +OCF_RESKEY_htmlfile_default="${HA_RSCTMP}/ClusterMon_${OCF_RESOURCE_INSTANCE}.html" : ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} : ${OCF_RESKEY_update=${OCF_RESKEY_update_default}} : ${OCF_RESKEY_extra_options=${OCF_RESKEY_extra_options_default}} : ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}} : ${OCF_RESKEY_htmlfile=${OCF_RESKEY_htmlfile_default}} ####################################################################### meta_data() { cat < 1.0 This is a ClusterMon Resource Agent. It outputs current cluster status to the html. Runs crm_mon in the background, recording the cluster status to an HTML file The user we want to run crm_mon as The user we want to run crm_mon as How frequently should we update the cluster status Update interval Additional options to pass to crm_mon. Eg. -n -r Extra options PID file location to ensure only one instance is running PID file Location to write HTML output to. HTML output END } ####################################################################### ClusterMon_usage() { cat </dev/null if [ $? -eq 0 ]; then : Yes, user exists. We can further check his permission on crm_mon if necessary else ocf_log err "The user $OCF_RESKEY_user does not exist!" exit $OCF_ERR_ARGS fi fi # Pidfile better be an absolute path case $OCF_RESKEY_pidfile in /*) ;; *) ocf_log warn "You should have pidfile($OCF_RESKEY_pidfile) of absolute path!" ;; esac # Check the update interval if ocf_is_decimal "$OCF_RESKEY_update" && [ $OCF_RESKEY_update -gt 0 ]; then : else ocf_log err "Invalid update interval $OCF_RESKEY_update. It should be positive integer!" exit $OCF_ERR_ARGS fi if CheckOptions $OCF_RESKEY_extra_options; then : else ocf_log err "Invalid options $OCF_RESKEY_extra_options!" exit $OCF_ERR_ARGS fi # Htmlfile better be an absolute path case $OCF_RESKEY_htmlfile in /*) ;; *) ocf_log warn "You should have htmlfile($OCF_RESKEY_htmlfile) of absolute path!" ;; esac echo "Validate OK" return $OCF_SUCCESS } if [ $# -ne 1 ]; then ClusterMon_usage exit $OCF_ERR_ARGS fi OCF_RESKEY_update=`expr $OCF_RESKEY_update / 1000` case $__OCF_ACTION in meta-data) meta_data exit $OCF_SUCCESS ;; start) ClusterMon_start ;; stop) ClusterMon_stop ;; monitor) ClusterMon_monitor ;; validate-all) ClusterMon_validate ;; usage|help) ClusterMon_usage exit $OCF_SUCCESS ;; *) ClusterMon_usage exit $OCF_ERR_UNIMPLEMENTED ;; esac exit $? diff --git a/heartbeat/openstack-cinder-volume b/heartbeat/openstack-cinder-volume index f47570b8b..d8e12c92f 100755 --- a/heartbeat/openstack-cinder-volume +++ b/heartbeat/openstack-cinder-volume @@ -1,378 +1,378 @@ #!/bin/sh # # # OCF resource agent to attach a cinder volume to an instance. # # Copyright (c) 2018 Mathieu GRZYBEK # Based on code of Markus Guertler # All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs # Defaults OCF_RESKEY_openstackcli_default="/usr/bin/openstack" -OCF_RESKEY_node_id_cache_file_default="/tmp/node_id" +OCF_RESKEY_node_id_cache_file_default="${HA_RSCTMP}/node_id" OCF_RESKEY_volume_local_check_default="true" export attached_server_id="" : ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}} : ${OCF_RESKEY_node_id_cache_file=${OCF_RESKEY_node_id_cache_file_default}} : ${OCF_RESKEY_volume_local_check=${OCF_RESKEY_volume_local_check_default}} ####################################################################### USAGE="usage: $0 {start|stop|status|meta-data}"; ############################################################################### ############################################################################### # # Functions # ############################################################################### metadata() { cat < 2.0 Resource Agent to attach a cinder volume to an instance. It relies on attributes given by openstack-info resource agent (openstack_id attribute). Attach a cinder volume Path to command line tools for openstack. Path to Openstack CLI tool Path to Node ID cache file, used to avoid Openstack API calls: 1. Is the local file written? 2. Is openstack_id available as a node attribute? 3. Can we get it from the API? Path to Node ID cache file This option allows the cluster to monitor the cinder volume presence without calling the API. Monitor cinder volume locally Valid Openstack credentials as openrc file from api_access/openrc. openrc file Cinder volume identifier to use to attach the bloc storage. Volume ID END } # # This is used to get the node ID from different sources: # 1. Is the local file written? # 2. Is openstack_id available as a node attribute? # 3. Can we get it from the API? # # When the ID is retrieved, the local cache file is written. # This prevents the agent to call the API each time the agent is used. # _get_node_id() { local crm_node local node local node_id local result crm_node=$(crm_node -n) # # Use local cache # if [ -f $OCF_RESKEY_node_id_cache_file ] ; then node_id=$(cat $OCF_RESKEY_node_id_cache_file) if [ ! -z "$node_id" ] ; then echo $node_id return fi fi # # Query the attributes database # node_id=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_id -N $crm_node \ | tr ' ' '\n' \ | awk -F= '/value=/ {gsub("\"","");print $NF}') if [ ! -z "$node_id" ] ; then echo $node_id | awk '{print $1}' echo $node_id | awk '{print $1}' > $OCF_RESKEY_node_id_cache_file return fi # # Use the API # node=$(crm_node -n | awk -F. '{print $1}') result=$($OCF_RESKEY_openstackcli server list \ --format value --column ID --column Name \ | grep $node) if [ $? -eq 0 ] ; then echo $result | awk '{print $1}' echo $result | awk '{print $1}' > $OCF_RESKEY_node_id_cache_file return fi ocf_exit_reason "openstack_id attribute must be set for node $crm_node" return $OCF_ERR_CONFIGURED } osvol_validate() { local node_id check_binary "$OCF_RESKEY_openstackcli" check_binary "awk" check_binary "tr" . $OCF_RESKEY_openrc node_id=$(_get_node_id) if [ -z "$node_id" ] ; then ocf_exit_reason "openstack_id attribute must be set for node $crm_node" return $OCF_ERR_CONFIGURED fi if [ -z "$OCF_RESKEY_openrc" ]; then ocf_exit_reason "openrc parameter not set" return $OCF_ERR_CONFIGURED fi if [ ! -f "$OCF_RESKEY_openrc" ] ; then ocf_exit_reason "openrc file not found" return $OCF_ERR_CONFIGURED fi return $OCF_SUCCESS } osvol_monitor() { local result local node_id local short_volume_id local fdisk_command if ocf_is_true $OCF_RESKEY_volume_local_check ; then # # Is the volue attached? # We check the local devices # short_volume_id=$(echo $OCF_RESKEY_volume_id | awk '{print substr($0, 0, 20)}') if uname | grep -q Linux ; then fdisk_command="fdisk -l" else fdisk_command="fdisk" fi $fdisk_command /dev/disk/by-id/virtio-$short_volume_id 1>/dev/null 2>&1 if [ $? -eq 0 ] ; then return $OCF_SUCCESS else ocf_log warn "$OCF_RESKEY_volume_id is not attached to instance $(_get_node_id)" return $OCF_NOT_RUNNING fi else # # Is the volue attached? # We use the API # result=$($OCF_RESKEY_openstackcli volume show \ --column status \ --column attachments \ --format value \ $OCF_RESKEY_volume_id) if echo "$result" | grep -q available ; then ocf_log warn "$OCF_RESKEY_volume_id is not attached to any instance" return $OCF_NOT_RUNNING else export attached_server_id=$(echo $result|head -n1|awk -F "'" '{print $4}') ocf_log info "$OCF_RESKEY_volume_id is attached to instance $attached_server_id" # Compare node_id and the id of the node the volume is attached to node_id=$(_get_node_id) if [ "$node_id" != "$attached_server_id" ] ; then return $OCF_NOT_RUNNING fi fi fi return $OCF_SUCCESS } osvol_stop() { local node_id # # Is the volume already attached? # osvol_monitor if [ $? = $OCF_NOT_RUNNING ]; then ocf_log info "Volume $OCF_RESKEY_volume_id already available" return $OCF_SUCCESS fi node_id=$(_get_node_id) # # Unmout the volume # if ! $OCF_RESKEY_openstackcli server remove volume $node_id $OCF_RESKEY_volume_id ; then ocf_log error "Couldn't remove volume $OCF_RESKEY_volume_id from instance $node_id" return $OCF_ERR_GENERIC fi ocf_log info "Successfully removed $OCF_RESKEY_volume_id from instance $node_id" return $OCF_SUCCESS } osvol_start() { local node_id # # Is the volume already attached? # osvol_monitor if [ $? = $OCF_SUCCESS ]; then ocf_log info "$OCF_RESKEY_volume_id already attached" return $OCF_SUCCESS fi # # Unmout it from another node # TODO: make it optional in case multi-attachment is allowed by Cinder # if [ ! -z $attached_server_id ] ; then if ! $OCF_RESKEY_openstackcli server remove volume $attached_server_id $OCF_RESKEY_volume_id ; then ocf_log error "Couldn't remove volume $OCF_RESKEY_volume_id from instance $attached_server_id" return $OCF_ERR_GENERIC fi fi export attached_server_id="" node_id=$(_get_node_id) # # Attach the volume # $OCF_RESKEY_openstackcli server add volume $node_id $OCF_RESKEY_volume_id if [ $? != $OCF_SUCCESS ]; then ocf_log error "Couldn't add volume $OCF_RESKEY_volume_id to instance $node_id" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } ############################################################################### # # MAIN # ############################################################################### case $__OCF_ACTION in meta-data) metadata exit $OCF_SUCCESS ;; usage|help) echo $USAGE exit $OCF_SUCCESS ;; esac if ! ocf_is_root; then ocf_log err "You must be root for $__OCF_ACTION operation." exit $OCF_ERR_PERM fi osvol_validate case $__OCF_ACTION in start) osvol_start;; stop) osvol_stop;; monitor|status) osvol_monitor;; validate-all) exit $?;; *) echo $USAGE exit $OCF_ERR_UNIMPLEMENTED ;; esac diff --git a/heartbeat/sapdb-nosha.sh b/heartbeat/sapdb-nosha.sh index 06aa65c4b..31b52e7fe 100644 --- a/heartbeat/sapdb-nosha.sh +++ b/heartbeat/sapdb-nosha.sh @@ -1,744 +1,744 @@ # # sapdatabase-nosha - for systems not having SAPHostAgent installed # (sourced by SAPDatabase) # # Description: this code is separated from the SAPDatabase agent to # be downward compatible and support systems which do # not have SAPHostAgent installed. # It will be removed in a later release completely. # # Author: Alexander Krauth, October 2006 # Support: linux@sap.com # License: GNU General Public License (GPL) # Copyright: (c) 2006, 2007 Alexander Krauth # trap_handler() { rm -f $TEMPFILE exit $OCF_ERR_GENERIC } # # listener_start: Start the given listener # listener_start() { local orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`" local lrc=$OCF_SUCCESS local output output=`echo "lsnrctl start $NETSERVICENAME" | su - $orasid 2>&1` if [ $? -eq 0 ] then ocf_log info "Oracle Listener $NETSERVICENAME started: $output" lrc=$OCF_SUCCESS else ocf_log err "Oracle Listener $NETSERVICENAME start failed: $output" lrc=$OCF_ERR_GENERIC fi return $lrc } # # listener_stop: Stop the given listener # listener_stop() { local orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`" local lrc=$OCF_SUCCESS if listener_status then : listener is running, trying to stop it later... else return $OCF_SUCCESS fi local output output=`echo "lsnrctl stop $NETSERVICENAME" | su - $orasid 2>&1` if [ $? -eq 0 ] then ocf_log info "Oracle Listener $NETSERVICENAME stopped: $output" else ocf_log err "Oracle Listener $NETSERVICENAME stop failed: $output" lrc=$OCF_ERR_GENERIC fi return $lrc } # # listener_status: is the given listener running? # listener_status() { local lrc=$OCF_SUCCESS local orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`" # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here # as the output might be to long. local cnt=`ps efo args --user $orasid | grep $NETSERVICENAME | grep -c tnslsnr` if [ $cnt -eq 1 ] then lrc=$OCF_SUCCESS else ocf_log info "listener process not running for $NETSERVICENAME for $SID" lrc=$OCF_ERR_GENERIC fi return $lrc } # # x_server_start: Start the given x_server # x_server_start() { local rc=$OCF_SUCCESS local output output=`echo "x_server start" | su - $sidadm 2>&1` if [ $? -eq 0 ] then ocf_log info "MaxDB x_server start: $output" lrc=$OCF_SUCCESS else ocf_log err "MaxDB x_server start failed: $output" lrc=$OCF_ERR_GENERIC fi return $lrc } # # x_server_stop: Stop the x_server # x_server_stop() { local lrc=$OCF_SUCCESS local output output=`echo "x_server stop" | su - $sidadm 2>&1` if [ $? -eq 0 ] then ocf_log info "MaxDB x_server stop: $output" else ocf_log err "MaxDB x_server stop failed: $output" lrc=$OCF_ERR_GENERIC fi return $lrc } # # x_server_status: is the x_server running? # x_server_status() { local lrc=$OCF_SUCCESS local sdbuser=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'` # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here # as the output might be to long. local cnt=`ps efo args --user $sdbuser | grep -c vserver` if [ $cnt -ge 1 ] then lrc=$OCF_SUCCESS else ocf_log info "x_server process not running" lrc=$OCF_ERR_GENERIC fi return $lrc } # # oracle_stop: Stop the Oracle database without any condition # oracle_stop() { echo '#!/bin/sh LOG=$HOME/stopdb.log date > $LOG if [ -x "${ORACLE_HOME}/bin/sqlplus" ] then SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus" else echo "Can not find executable sqlplus" >> $LOG exit 1 fi $SRVMGRDBA_EXE /NOLOG >> $LOG << ! connect / as sysdba shutdown immediate exit ! rc=$? cat $LOG exit $rc' > $TEMPFILE chmod 700 $TEMPFILE chown $sidadm $TEMPFILE su - $sidadm -c $TEMPFILE retcode=$? rm -f $TEMPFILE if [ $retcode -eq 0 ]; then sapdatabase_status if [ $? -ne $OCF_NOT_RUNNING ]; then retcode=1 fi fi return $retcode } # # maxdb_stop: Stop the MaxDB database without any condition # maxdb_stop() { # x_Server must be running to stop database x_server_status if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi if [ $DBJ2EE_ONLY -eq 1 ]; then userkey=c_J2EE else userkey=c fi echo "#!/bin/sh LOG=\$HOME/stopdb.log date > \$LOG echo \"Stop database with xuserkey >$userkey<\" >> \$LOG dbmcli -U ${userkey} db_offline >> \$LOG 2>&1 exit \$?" > $TEMPFILE chmod 700 $TEMPFILE chown $sidadm $TEMPFILE su - $sidadm -c $TEMPFILE retcode=$? rm -f $TEMPFILE if [ $retcode -eq 0 ]; then sapdatabase_status if [ $? -ne $OCF_NOT_RUNNING ]; then retcode=1 fi fi return $retcode } # # db6udb_stop: Stop the DB2/UDB database without any condition # db6udb_stop() { echo '#!/bin/sh LOG=$HOME/stopdb.log date > $LOG echo "Shut down the database" >> $LOG $INSTHOME/sqllib/bin/db2 deactivate database $DB2DBDFT |tee -a $LOG 2>&1 $INSTHOME/sqllib/adm/db2stop force |tee -a $LOG 2>&1 exit $?' > $TEMPFILE chmod 700 $TEMPFILE chown $sidadm $TEMPFILE su - $sidadm -c $TEMPFILE retcode=$? rm -f $TEMPFILE if [ $retcode -eq 0 ]; then sapdatabase_status if [ $? -ne $OCF_NOT_RUNNING ]; then retcode=1 fi fi return $retcode } # # oracle_recover: try to clean up oracle after a crash # oracle_recover() { echo '#!/bin/sh LOG=$HOME/recover.log date > $LOG echo "Logfile written by heartbeat SAPDatabase resource agent" >> $LOG if [ -x "${ORACLE_HOME}/bin/sqlplus" ] then SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus" else echo "Can not find executable sqlplus" >> $LOG exit 1 fi $SRVMGRDBA_EXE /NOLOG >> $LOG << ! connect / as sysdba shutdown abort startup mount alter database end backup; alter database open; exit ! rc=$? cat $LOG exit $rc' > $TEMPFILE chmod 700 $TEMPFILE chown $sidadm $TEMPFILE su - $sidadm -c $TEMPFILE retcode=$? rm -f $TEMPFILE return $retcode } # # maxdb_recover: try to clean up MaxDB after a crash # maxdb_recover() { # x_Server must be running to stop database x_server_status if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi if [ $DBJ2EE_ONLY -eq 1 ]; then userkey=c_J2EE else userkey=c fi echo "#!/bin/sh LOG=\$HOME/recover.log date > \$LOG echo \"Logfile written by heartbeat SAPDatabase resource agent\" >> \$LOG echo \"Cleanup database with xuserkey >$userkey<\" >> \$LOG echo \"db_stop\" >> \$LOG 2>&1 dbmcli -U ${userkey} db_stop >> \$LOG 2>&1 echo \"db_clear\" >> \$LOG 2>&1 dbmcli -U ${userkey} db_clear >> \$LOG 2>&1 echo \"db_online\" >> \$LOG 2>&1 dbmcli -U ${userkey} db_online >> \$LOG 2>&1 rc=\$? cat \$LOG exit \$rc" > $TEMPFILE chmod 700 $TEMPFILE chown $sidadm $TEMPFILE su - $sidadm -c $TEMPFILE retcode=$? rm -f $TEMPFILE return $retcode } # # db6udb_recover: try to recover DB/2 after a crash # db6udb_recover() { db2sid="db2`echo $SID | tr '[:upper:]' '[:lower:]'`" echo '#!/bin/sh LOG=$HOME/recover.log date > $LOG echo "Logfile written by heartbeat SAPDatabase resource agent" >> $LOG $INSTHOME/sqllib/bin/db2_kill >> $LOG 2>&1 $INSTHOME/sqllib/adm/db2start >> $LOG 2>&1 $INSTHOME/sqllib/bin/db2 activate database $DB2DBDFT >> $LOG 2>&1 rc=$? cat $LOG exit $rc' > $TEMPFILE chmod 700 $TEMPFILE chown $db2sid $TEMPFILE su - $db2sid -c $TEMPFILE retcode=$? rm -f $TEMPFILE return $retcode } # # sapdatabase_start : Start the SAP database # sapdatabase_start() { sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT" case $DBTYPE in ADA) x_server_start ;; ORA) listener_start ;; esac output=`su - $sidadm -c $SAPSTARTDB` rc=$? if [ $DBJ2EE_ONLY -eq 1 ] then sapdatabase_monitor 1 rc=$? fi if [ $rc -ne 0 -a $OCF_RESKEY_AUTOMATIC_RECOVER -eq 1 ] then ocf_log warn "SAP database $SID start failed: $output" ocf_log warn "Try to recover database $SID" output='' sapdatabase_recover rc=$? fi if [ $rc -eq 0 ] then ocf_log info "SAP database $SID started: $output" rc=$OCF_SUCCESS sapuserexit POST_START_USEREXIT "$OCF_RESKEY_POST_START_USEREXIT" else ocf_log err "SAP database $SID start failed: $output" rc=$OCF_ERR_GENERIC fi return $rc } # # sapdatabase_stop: Stop the SAP database # sapdatabase_stop() { sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT" # use of the stopdb kernel script is not possible, because there are to may checks in that # script. We want to stop the database regardless of anything. #output=`su - $sidadm -c $SAPSTOPDB` case $DBTYPE in ORA) output=`oracle_stop` ;; ADA) output=`maxdb_stop` ;; DB6) output=`db6udb_stop` ;; esac if [ $? -eq 0 ] then ocf_log info "SAP database $SID stopped: $output" rc=$OCF_SUCCESS else ocf_log err "SAP database $SID stop failed: $output" rc=$OCF_ERR_GENERIC fi case $DBTYPE in ORA) listener_stop ;; ADA) x_server_stop ;; esac sapuserexit POST_STOP_USEREXIT "$OCF_RESKEY_POST_STOP_USEREXIT" return $rc } # # sapdatabase_monitor: Can the given database instance do anything useful? # sapdatabase_monitor() { strict=$1 sapdatabase_status rc=$? if [ $rc -ne $OCF_SUCCESS ]; then return $rc fi case $DBTYPE in ADA) x_server_status if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi ;; ORA) listener_status if [ $? -ne $OCF_SUCCESS ]; then listener_start; fi ;; esac if [ $strict -eq 0 ] then return $rc else if [ $DBJ2EE_ONLY -eq 0 ] then output=`echo "$SAPDBCONNECT -d -w /dev/null" | su $sidadm 2>&1` if [ $? -le 4 ] then rc=$OCF_SUCCESS else rc=$OCF_NOT_RUNNING fi else MYCP="" EXECMD="" # WebAS Java 6.40+7.00 IAIK_JCE="$SECSTORE"/iaik_jce.jar IAIK_JCE_EXPORT="$SECSTORE"/iaik_jce_export.jar EXCEPTION="$BOOTSTRAP"/exception.jar LOGGING="$BOOTSTRAP"/logging.jar OPENSQLSTA="$BOOTSTRAP"/opensqlsta.jar TC_SEC_SECSTOREFS="$BOOTSTRAP"/tc_sec_secstorefs.jar JDDI="$BOOTSTRAP"/../server0/bin/ext/jdbdictionary/jddi.jar ANTLR="$BOOTSTRAP"/../server0/bin/ext/antlr/antlr.jar FRAME="$BOOTSTRAP"/../server0/bin/system/frame.jar # only start jdbcconnect when all jars available if [ -f "$EXCEPTION" -a -f "$LOGGING" -a -f "$OPENSQLSTA" -a -f "$TC_SEC_SECSTOREFS" -a -f "$JDDI" -a -f "$ANTLR" -a -f "$FRAME" -a -f "$SAPDBCONNECT" ] then MYCP=".:$FRAME:$ANTLR:$JDDI:$IAIK_JCE_EXPORT:$IAIK_JCE:$EXCEPTION:$LOGGING:$OPENSQLSTA:$TC_SEC_SECSTOREFS:$DB_JARS:$SAPDBCONNECT" EXECMD="com.sap.inst.jdbc.connect.JdbcCon -sec $SID:$SID" else # WebAS Java 7.10 LAUNCHER=${BOOTSTRAP}/sap.com~tc~bl~offline_launcher~impl.jar if [ -f "$DB_JARS" -a -f "$SAPDBCONNECT" -a -f "$LAUNCHER" ] then MYCP="$LAUNCHER" EXECMD="com.sap.engine.offline.OfflineToolStart com.sap.inst.jdbc.connect.JdbcCon ${SAPDBCONNECT}:${SECSTORE}:${DB_JARS}:${BOOTSTRAP} -sec $SID:$SID" fi fi if [ -n "$EXECMD" ] then output=`${JAVA_HOME}/bin/java -cp $MYCP $EXECMD 2> /dev/null` if [ $? -le 0 ] then rc=$OCF_SUCCESS else rc=$OCF_NOT_RUNNING fi else output="Cannot find all jar files needed for database monitoring." rc=$OCF_ERR_GENERIC fi fi fi if [ $rc -ne $OCF_SUCCESS ] then ocf_log err "The SAP database $SID is not running: $output" fi return $rc } # # sapdatabase_status: Are there any database processes on this host ? # sapdatabase_status() { case $DBTYPE in ADA) SEARCH="$SID/db/pgm/kernel" SUSER=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'` SNUM=2 ;; ORA) SEARCH="ora_[a-z][a-z][a-z][a-z]_" SUSER="ora`echo $SID | tr '[:upper:]' '[:lower:]'`" SNUM=4 ;; DB6) SEARCH="db2[a-z][a-z][a-z]" SUSER="db2`echo $SID | tr '[:upper:]' '[:lower:]'`" SNUM=2 ;; esac # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here # as the output might be to long. cnt=`ps efo args --user $SUSER 2> /dev/null | grep -c "$SEARCH"` if [ $cnt -ge $SNUM ] then rc=$OCF_SUCCESS else # ocf_log info "Database Instance $SID is not running on `hostname`" rc=$OCF_NOT_RUNNING fi return $rc } # # sapdatabase_recover: # sapdatabase_recover() { case $DBTYPE in ORA) recoutput=`oracle_recover` ;; ADA) recoutput=`maxdb_recover` ;; DB6) recoutput=`db6udb_recover` ;; esac sapdatabase_monitor 1 retcode=$? if [ $retcode -eq $OCF_SUCCESS ] then ocf_log info "Recover of SAP database $SID was successful: $recoutput" else ocf_log err "Recover of SAP database $SID failed: $recoutput" fi return $retcode } # # sapdatabase_validate: Check the symantic of the input parameters # sapdatabase_validate() { rc=$OCF_SUCCESS if [ `echo "$SID" | grep -c '^[A-Z][A-Z0-9][A-Z0-9]$'` -ne 1 ] then ocf_log err "Parsing parameter SID: '$SID' is not a valid system ID!" rc=$OCF_ERR_ARGS fi case "$DBTYPE" in ORA|ADA|DB6) ;; *) ocf_log err "Parsing parameter DBTYPE: '$DBTYPE' is not a supported database type!" rc=$OCF_ERR_ARGS ;; esac return $rc } # # sapdatabase_init: initialize global variables at the beginning # sapdatabase_init() { ocf_log warn "Usage of SAPDatabase resource agent without SAPHostAgent is deprecated. Please read documentation of SAPDatabase resource agent and follow SAP note 1031096 for the installation of SAPHostAgent." # optional OCF parameters, we try to guess which directories are correct EXESTARTDB="startdb" EXESTOPDB="stopdb" EXEDBCONNECT="R3trans" if [ -z "$OCF_RESKEY_DBJ2EE_ONLY" ]; then DBJ2EE_ONLY=0 else case "$OCF_RESKEY_DBJ2EE_ONLY" in 1|true|TRUE|yes|YES) DBJ2EE_ONLY=1 EXESTARTDB="startj2eedb" EXESTOPDB="stopj2eedb" EXEDBCONNECT="jdbcconnect.jar" ;; 0|false|FALSE|no|NO) DBJ2EE_ONLY=0;; *) ocf_log err "Parsing parameter DBJ2EE_ONLY: '$DBJ2EE_ONLY' is not a boolean value!" exit $OCF_ERR_ARGS ;; esac fi if [ -z "$OCF_RESKEY_NETSERVICENAME" ]; then case "$DBTYPE" in ORA|ora) NETSERVICENAME="LISTENER";; *) NETSERVICENAME="";; esac else NETSERVICENAME="$OCF_RESKEY_NETSERVICENAME" fi if [ -z "$OCF_RESKEY_STRICT_MONITORING" ]; then OCF_RESKEY_STRICT_MONITORING=0 else case "$OCF_RESKEY_STRICT_MONITORING" in 1|true|TRUE|yes|YES) OCF_RESKEY_STRICT_MONITORING=1;; 0|false|FALSE|no|NO) OCF_RESKEY_STRICT_MONITORING=0;; *) ocf_log err "Parsing parameter STRICT_MONITORING: '$OCF_RESKEY_STRICT_MONITORING' is not a boolean value!" exit $OCF_ERR_ARGS ;; esac fi PATHLIST=" $OCF_RESKEY_DIR_EXECUTABLE /usr/sap/$SID/*/exe /usr/sap/$SID/SYS/exe/run /sapmnt/$SID/exe " DIR_EXECUTABLE="" for EXEPATH in $PATHLIST do if [ -x $EXEPATH/$EXESTARTDB -a -x $EXEPATH/$EXESTOPDB -a -x $EXEPATH/$EXEDBCONNECT ] then DIR_EXECUTABLE=$EXEPATH SAPSTARTDB=$EXEPATH/$EXESTARTDB SAPSTOPDB=$EXEPATH/$EXESTOPDB SAPDBCONNECT=$EXEPATH/$EXEDBCONNECT break fi done if [ -z "$DIR_EXECUTABLE" ] then ocf_log warn "Cannot find $EXESTARTDB,$EXESTOPDB and $EXEDBCONNECT executable, please set DIR_EXECUTABLE parameter!" exit $OCF_NOT_RUNNING fi if [ $DBJ2EE_ONLY -eq 1 ] then if [ -n "$OCF_RESKEY_DIR_BOOTSTRAP" ] then BOOTSTRAP="$OCF_RESKEY_DIR_BOOTSTRAP" else BOOTSTRAP=`ls -1d /usr/sap/$SID/*/j2ee/cluster/bootstrap | head -1` fi if [ -n "$OCF_RESKEY_DIR_SECSTORE" ] then SECSTORE="$OCF_RESKEY_DIR_SECSTORE" else SECSTORE=/usr/sap/$SID/SYS/global/security/lib/tools fi if [ -n "$OCF_RESKEY_JAVA_HOME" ] then JAVA_HOME="$OCF_RESKEY_JAVA_HOME" PATH=$JAVA_HOME/bin:$PATH else if [ -n "$JAVA_HOME" ] then PATH=$JAVA_HOME/bin:$PATH else ocf_log err "Cannot find JAVA_HOME directory, please set JAVA_HOME parameter!" exit $OCF_NOT_RUNNING fi fi if [ -n "$OCF_RESKEY_DB_JARS" ] then DB_JARS=$OCF_RESKEY_DB_JARS else if [ -f "$BOOTSTRAP"/bootstrap.properties ]; then DB_JARS=`cat $BOOTSTRAP/bootstrap.properties | grep -i rdbms.driverLocation | sed -e 's/\\\:/:/g' | awk -F= '{print $2}'` fi fi fi if [ -z "$OCF_RESKEY_AUTOMATIC_RECOVER" ] then OCF_RESKEY_AUTOMATIC_RECOVER=0 else case "$OCF_RESKEY_AUTOMATIC_RECOVER" in 1|true|TRUE|yes|YES) OCF_RESKEY_AUTOMATIC_RECOVER=1;; 0|false|FALSE|no|NO) OCF_RESKEY_AUTOMATIC_RECOVER=0;; esac fi # as root user we need the library path to the SAP kernel to be able to call executables if [ `echo $LD_LIBRARY_PATH | grep -c "^$DIR_EXECUTABLE\>"` -eq 0 ]; then LD_LIBRARY_PATH=$DIR_EXECUTABLE${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH export LD_LIBRARY_PATH fi sidadm="`echo $SID | tr '[:upper:]' '[:lower:]'`adm" } # Set a tempfile and make sure to clean it up again -TEMPFILE="/tmp/SAPDatabase.$$.tmp" -trap trap_handler INT TERM \ No newline at end of file +TEMPFILE="${HA_RSCTMP}/SAPDatabase.$$.tmp" +trap trap_handler INT TERM diff --git a/rgmanager/src/resources/oradg.sh.in b/rgmanager/src/resources/oradg.sh.in index 4674fe1b2..955f93e18 100644 --- a/rgmanager/src/resources/oradg.sh.in +++ b/rgmanager/src/resources/oradg.sh.in @@ -1,660 +1,660 @@ #!@BASH_SHELL@ # # Copyright 2003-2004, 2006-2013 Red Hat, Inc. # # Author(s): # Hardy Merrill # Lon Hohberger # Michael Moon # Ryan McCabe # # This program is Open Source software. You may modify and/or redistribute # it persuant to the terms of the Open Software License version 2.1, which # is available from the following URL and is included herein by reference: # # http://opensource.org/licenses/osl-2.1.php # # NOTES: # # (1) You can comment out the LOCKFILE declaration below. This will prevent # the need for this script to access anything outside of the ORACLE_HOME # path. # # (2) You MUST customize ORACLE_USER, ORACLE_HOME, ORACLE_SID, and # ORACLE_HOSTNAME to match your installation if not running from within # rgmanager. # # (3) Do NOT place this script in shared storage; place it in ORACLE_USER's # home directory in non-clustered environments and /usr/share/cluster # in rgmanager/Red Hat cluster environments. # # Oracle is a registered trademark of Oracle Corporation. # Oracle9i is a trademark of Oracle Corporation. # Oracle10g is a trademark of Oracle Corporation. # Oracle11g is a trademark of Oracle Corporation. # All other trademarks are property of their respective owners. # # # $Id: oradg.sh 127 2009-08-21 09:17:52Z hevirtan $ # # Original version is distributed with RHCS. The modifications include # the following minor changes: # - Meta-data moved to a dedicated file # - Support for multiple listeners # - Disabled EM # - SysV init support removed. Only usable with rgmanager # # Grab the global RHCS helper functions . $(dirname $0)/ocf-shellfuncs . $(dirname $0)/utils/config-utils.sh . $(dirname $0)/utils/messages.sh . $(dirname $0)/utils/ra-skelet.sh . /etc/init.d/functions declare SCRIPT="`basename $0`" declare SCRIPTDIR="`dirname $0`" # Required parameters from rgmanager ORACLE_USER=$OCF_RESKEY_user ORACLE_HOME=$OCF_RESKEY_home ORACLE_SID=$OCF_RESKEY_name [ -n "$OCF_RESKEY_tns_admin" ] && export TNS_ADMIN=$OCF_RESKEY_tns_admin # Optional parameters with default values LISTENERS=$OCF_RESKEY_listeners LOCKFILE="$ORACLE_HOME/.orainstance-${ORACLE_SID}.lock" [ -n "$OCF_RESKEY_vhost" ] && ORACLE_HOSTNAME=$OCF_RESKEY_vhost [ -n "$OCF_RESKEY_lockfile" ] && LOCKFILE=$OCF_RESKEY_lockfile export LISTENERS ORACLE_USER ORACLE_HOME ORACLE_SID LOCKFILE ORACLE_HOSTNAME export LD_LIBRARY_PATH=$ORACLE_HOME/lib export PATH=$ORACLE_HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin #declare -i RESTART_RETRIES=3 declare -i RESTART_RETRIES=0 declare -r DB_PROCNAMES="pmon" declare -r LSNR_PROCNAME="tnslsnr" # clulog will not log messages when run by the oracle user. # This is a hack to work around that. if [ "`id -u`" = "`id -u $ORACLE_USER`" ]; then ocf_log() { prio=$1 shift logger -i -p daemon."$prio" -- "$*" } fi # # Start Oracle (database portion) # start_db() { declare -i rv declare startup_cmd declare startup_stdout ocf_log info "Starting Oracle DB $ORACLE_SID" # Set up our sqlplus script. Basically, we're trying to # capture output in the hopes that it's useful in the case # that something doesn't work properly. startup_stdout=$(sqlplus "/ as sysdba" << EOF set serveroutput on startup mount; declare rol varchar(20); begin select database_role into rol from v\$database; dbms_output.put_line('Database role is ' || rol); if (rol = 'PHYSICAL STANDBY') then return; end if; execute immediate 'alter database open'; end; / select database_role, open_mode from v\$database; set heading off; set serveroutput off; -spool /tmp/dgstatus.${ORACLE_SID}; +spool ${HA_RSCTMP}/dgstatus.${ORACLE_SID}; select open_mode from v\$database; spool off; EOF ) rv=$? # Data Guard Modification 2 - Remove deprecated parameter error from startup_stdout startup_stdout=$(echo $startup_stdout | sed 's/ORA-32004//g') # Dump output to syslog for debugging ocf_log debug "[$ORACLE_SID] [$rv] sent $startup_cmd" ocf_log debug "[$ORACLE_SID] [$rv] got $startup_stdout" if [ $rv -ne 0 ]; then ocf_log error "Starting Oracle DB $ORACLE_SID failed, sqlplus returned $rv" return 1 fi # If we see: # ORA-.....: failure, we failed # Troubleshooting: # ORA-00845 - Try rm -f /dev/shm/ora_* # ORA-01081 - Try echo -e 'shutdown abort;\nquit;'|sqlplus "/ as sysdba" if [[ "$startup_stdout" =~ "ORA-" ]] || [[ "$startup_stdout" =~ "failure" ]]; then ocf_log error "Starting Oracle DB $ORACLE_SID failed, found errors in stdout" return 1 fi ocf_log info "Started Oracle DB $ORACLE_SID successfully" return 0 } # # Stop Oracle (database portion) # stop_db() { declare stop_cmd declare stop_stdout declare -i rv declare how_shutdown="$1" if [ -z "$1" ]; then how_shutdown="immediate" fi ocf_log info "Stopping Oracle DB $ORACLE_SID $how_shutdown" ora_procname="ora_${DB_PROCNAMES}_${ORACLE_SID}" status $ora_procname if [ $? -ne 0 ]; then ocf_log debug "no pmon process -- DB $ORACLE_SID already stopped" # No pmon process found, db already down return 0 fi # Setup for Stop ... stop_cmd="set heading off;\nshutdown $how_shutdown;\nquit;\n" stop_stdout=$(echo -e "$stop_cmd" | sqlplus -S "/ as sysdba") rv=$? # Log stdout of the stop command ocf_log debug "[$ORACLE_SID] sent stop command $stop_cmd" ocf_log debug "[$ORACLE_SID] got $stop_stdout" # sqlplus returned failure. We'll return failed to rhcs if [ $rv -ne 0 ]; then ocf_log error "Stopping Oracle DB $ORACLE_SID failed, sqlplus returned $rv" return 1 fi # If we see 'ORA-' or 'failure' in stdout, we're done. if [[ "$startup_stdout" =~ "ORA-" ]] || [[ "$startup_stdout" =~ "failure" ]]; then ocf_log error "Stopping Oracle DB $ORACLE_SID failed, errors in stdout" return 1 fi ocf_log info "Stopped Oracle DB $ORACLE_SID successfully" return 0 } # # Destroy any remaining processes with refs to $ORACLE_SID # force_cleanup() { declare pids declare pid ocf_log error "Not all Oracle processes for $ORACLE_SID exited cleanly, killing" pids=`ps ax | grep "ora_.*_${ORACLE_SID}$" | grep -v grep | awk '{print $1}'` for pid in $pids; do kill -9 $pid rv=$? if [ $rv -eq 0 ]; then ocf_log info "Cleanup $ORACLE_SID Killed PID $pid" else ocf_log error "Cleanup $ORACLE_SID Kill PID $pid failed: $rv" fi done return 0 } # # Wait for oracle processes to exit. Time out after 60 seconds # exit_idle() { declare -i n=0 ocf_log debug "Waiting for Oracle processes for $ORACLE_SID to terminate..." while ps ax | grep "ora_.*_${ORACLE_SID}$" | grep -v grep | grep -q -v $LSNR_PROCNAME; do if [ $n -ge 90 ]; then ocf_log debug "Timed out while waiting for Oracle processes for $ORACLE_SID to terminate" force_cleanup return 0 fi sleep 1 ((n++)) done ocf_log debug "All Oracle processes for $ORACLE_SID have terminated" return 0 } # # Get database background process status. Restart it if it failed and # we have seen the lock file. # get_db_status() { declare -i subsys_lock=$1 declare -i i=0 declare -i rv=0 declare ora_procname ocf_log debug "Checking status of DB $ORACLE_SID" for procname in $DB_PROCNAMES ; do ora_procname="ora_${procname}_${ORACLE_SID}" status $ora_procname if [ $? -eq 0 ] ; then # This one's okay; go to the next one. continue fi # We're not supposed to be running, and we are, # in fact, not running... if [ $subsys_lock -ne 0 ]; then ocf_log debug "DB $ORACLE_SID is already stopped" return 3 fi for (( i=$RESTART_RETRIES ; i; i-- )) ; do # this db process is down - stop and # (re)start all ora_XXXX_$ORACLE_SID processes ocf_log info "Restarting Oracle Database $ORACLE_SID" stop_db start_db if [ $? -eq 0 ] ; then # ora_XXXX_$ORACLE_SID processes started # successfully, so break out of the # stop/start # 'for' loop ocf_log info "Restarted Oracle DB $ORACLE_SID successfully" break fi done if [ $i -eq 0 ]; then # stop/start's failed - return 1 (failure) ocf_log error "Failed to restart Oracle DB $ORACLE_SID after $RESTART_RETRIES tries" return 1 fi done ocf_log debug "Checking status of DB $ORACLE_SID success" return 0 } # # Get the status of the Oracle listener process # get_lsnr_status() { declare -i subsys_lock=$1 declare -i rv declare -r LISTENER=$3 ocf_log debug "Checking status for listener $LISTENER" lsnrctl status "$LISTENER" >& /dev/null rv=$? if [ $rv -eq 0 ] ; then ocf_log debug "Listener $LISTENER is up" return 0 # Listener is running fine fi # We're not supposed to be running, and we are, # in fact, not running. Return 3 if [ $subsys_lock -ne 0 ]; then ocf_log debug "Listener $LISTENER is stopped as expected" return 3 fi # Listener is NOT running (but should be) - try to restart for (( i=$RESTART_RETRIES ; i; i-- )) ; do ocf_log info "Listener $LISTENER is down, attempting to restart" lsnrctl start "$LISTENER" >& /dev/null lsnrctl status "$LISTENER" >& /dev/null if [ $? -eq 0 ]; then ocf_log info "Listener $LISTENER was restarted successfully" break # Listener was (re)started and is running fine fi done if [ $i -eq 0 ]; then # stop/start's failed - return 1 (failure) ocf_log error "Failed to restart listener $LISTENER after $RESTART_RETRIES tries" return 1 fi lsnrctl_stdout=$(lsnrctl status "$LISTENER") rv=$? if [ $rv -ne 0 ] ; then ocf_log error "Starting listener $LISTENER failed: $rv output $lsnrctl_stdout" return 1 # Problem restarting the Listener fi ocf_log info "Listener $LISTENER started successfully" return 0 # Success restarting the Listener } # # Helps us keep a running status so we know what our ultimate return # code will be. Returns 1 if the $1 and $2 are not equivalent, otherwise # returns $1. The return code is meant to be the next $1 when this is # called, so, for example: # # update_status 0 <-- returns 0 # update_status $? 0 <-- returns 0 # update_status $? 3 <-- returns 1 (values different - error condition) # update_status $? 1 <-- returns 1 (same, but happen to be error state!) # # update_status 3 # update_status $? 3 <-- returns 3 # # (and so forth...) # update_status() { declare -i old_status=$1 declare -i new_status=$2 if [ -z "$2" ]; then return $old_status fi if [ $old_status -ne $new_status ]; then ocf_log error "Error: $old_status vs $new_status for $ORACLE_SID - returning 1" return 1 fi return $old_status } # # Print an error message to the user and exit. # oops() { ocf_log error "$ORACLE_SID: Fatal: $1 failed validation checks" exit 1 } # # Do some validation on the user-configurable stuff at the beginning of the # script. # validation_checks() { ocf_log debug "Validating configuration for $ORACLE_SID" # If the oracle user doesn't exist, we're done. [ -n "$ORACLE_USER" ] || oops "ORACLE_USER" id -u $ORACLE_USER > /dev/null || oops "ORACLE_USER" id -g $ORACLE_USER > /dev/null || oops "ORACLE_GROUP" # If the oracle home isn't a directory, we're done [ -n "$ORACLE_HOME" ] || oops "ORACLE_HOME" # If the oracle SID is NULL, we're done [ -n "$ORACLE_SID" ] || oops "ORACLE_SID" # Super user? Automatically change UID and exec as oracle user. # Oracle needs to be run as the Oracle user, not root! if [ "`id -u`" = "0" ]; then su $ORACLE_USER -c "$0 $*" exit $? fi # If we're not root and not the Oracle user, we're done. [ "`id -u`" = "`id -u $ORACLE_USER`" ] || oops "not ORACLE_USER after su" [ "`id -g`" = "`id -g $ORACLE_USER`" ] || oops "not ORACLE_GROUP after su" # Go home. cd "$ORACLE_HOME" ocf_log debug "Validation checks for $ORACLE_SID succeeded" return 0 } # # Start Oracle # start_oracle() { ocf_log info "Starting service $ORACLE_SID" start_db rv=$? if [ $rv -ne 0 ]; then ocf_log error "Starting service $ORACLE_SID failed" return 1 fi for LISTENER in ${LISTENERS}; do ocf_log info "Starting listener $LISTENER" lsnrctl_stdout=$(lsnrctl start "$LISTENER") rv=$? if [ $rv -ne 0 ]; then ocf_log debug "[$ORACLE_SID] Listener $LISTENER start returned $rv output $lsnrctl_stdout" ocf_log error "Starting service $ORACLE_SID failed" return 1 fi done - if [ -n "$ORACLE_HOSTNAME" -a -s /tmp/dgstatus.${ORACLE_SID} ]; then + if [ -n "$ORACLE_HOSTNAME" -a -s ${HA_RSCTMP}/dgstatus.${ORACLE_SID} ]; then # Start DB Console if vhost defined and database_role is READ WRITE - if cat /tmp/dgstatus.${ORACLE_SID} 2>/dev/null | grep "READ WRITE"; then + if cat ${HA_RSCTMP}/dgstatus.${ORACLE_SID} 2>/dev/null | grep "READ WRITE"; then ocf_log info "Starting Oracle EM DB Console for $ORACLE_SID" emctl start dbconsole if [ $? -ne 0 ]; then ocf_log error "Oracle EM DB Console startup for $ORACLE_SID failed" ocf_log error "Starting service $ORACLE_SID failed" # Force good return status #return 1 return 0 else ocf_log info "Oracle EM DB Console startup for $ORACLE_SID succeeded" fi fi - rm -f /tmp/dgstatus.${ORACLE_SID} + rm -f ${HA_RSCTMP}/dgstatus.${ORACLE_SID} fi if [ -n "$LOCKFILE" ]; then touch "$LOCKFILE" fi ocf_log info "Starting service $ORACLE_SID completed successfully" return 0 } # # Stop Oracle # stop_oracle() { ocf_log info "Stopping service $ORACLE_SID" if ! [ -e "$ORACLE_HOME/bin/lsnrctl" ]; then ocf_log error "Oracle Listener Control is not available ($ORACLE_HOME not mounted?)" # XXX should this return 1? return 0 fi stop_db || stop_db abort if [ $? -ne 0 ]; then ocf_log error "Unable to stop DB for $ORACLE_SID" return 1 fi for LISTENER in ${LISTENERS}; do ocf_log info "Stopping listener $LISTENER for $ORACLE_SID" lsnrctl_stdout=$(lsnrctl stop "$LISTENER") rv=$? if [ $rv -ne 0 ]; then ocf_log error "Listener $LISTENER stop failed for $ORACLE_SID: $rv output $lsnrctl_stdout" pid=`ps ax | grep "tnslsnr $LISTENER " | grep -v grep | awk '{print $1}'` kill -9 $pid rv=$? if [ $rv -eq 0 ]; then ocf_log info "Cleanup $LISTENER Killed PID $pid" else ocf_log error "Cleanup $LISTENER Kill PID $pid failed: $rv" fi fi done if [ -n "$ORACLE_HOSTNAME" ]; then # Stop DB Console if vhost defined ocf_log info "Stopping Oracle EM DB Console for $ORACLE_SID" emctl stop dbconsole if [ $? -ne 0 ]; then ocf_log error "Stopping Oracle EM DB Console for $ORACLE_SID failed" ocf_log error "Stopping service $ORACLE_SID failed" # Force good return status #return 1 return 0 else ocf_log info "Stopping Oracle EM DB Console for $ORACLE_SID succeeded" fi fi exit_idle if [ $? -ne 0 ]; then ocf_log error "WARNING: Not all Oracle processes exited cleanly for $ORACLE_SID" # XXX - failure? fi if [ -n "$LOCKFILE" ]; then rm -f "$LOCKFILE" fi ocf_log info "Stopping service $ORACLE_SID succeeded" return 0 } # # Find and display the status of iAS infrastructure. # # This has three parts: # (1) Oracle database itself # (2) Oracle listener process # (3) OPMN and OPMN-managed processes # # - If all are (cleanly) down, we return 3. In order for this to happen, # $LOCKFILE must not exist. In this case, we try and restart certain parts # of the service - as this may be running in a clustered environment. # # - If some but not all are running (and, if $LOCKFILE exists, we could not # restart the failed portions), we return 1 (ERROR) # # - If all are running, return 0. In the "all-running" case, we recreate # $LOCKFILE if it does not exist. # status_oracle() { declare -i subsys_lock=1 declare -i last declare -i depth=$1 ocf_log debug "Checking status for $ORACLE_SID depth $depth" # Check for lock file. Crude and rudimentary, but it works if [ -z "$LOCKFILE" ] || [ -f "$LOCKFILE" ]; then subsys_lock=0 fi # Check database status get_db_status $subsys_lock $depth update_status $? # Start last=$? # Check & report listener status for LISTENER in ${LISTENERS}; do get_lsnr_status $subsys_lock $depth "$LISTENER" update_status $? $last last=$? done # No status for DB Console (ORACLE_HOSTNAME) # No lock file, but everything's running. Put the lock # file back. XXX - this kosher? if [ $last -eq 0 ] && [ $subsys_lock -ne 0 ]; then touch "$LOCKFILE" fi ocf_log debug "Status returning $last for $ORACLE_SID" return $last } ######################## # Do some real work... # ######################## # Data Guard Modification 1 - Debug Logging case $1 in stop | start | status | restart | recover | monitor ) -[ $(id -u) = 0 ] && exec > "/tmp/oradg_${ORACLE_SID}_$1.log" 2>&1 +[ $(id -u) = 0 ] && exec > "${HA_RSCTMP}/oradg_${ORACLE_SID}_$1.log" 2>&1 set -x date echo $@ printenv esac case $1 in meta-data) cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'` exit 0 ;; start) validation_checks $* start_oracle exit $? ;; stop) validation_checks $* stop_oracle exit $? ;; status|monitor) validation_checks $* status_oracle $OCF_CHECK_LEVEL exit $? ;; restart) $0 stop || exit $? $0 start || exit $? exit 0 ;; *) echo "usage: $SCRIPT {start|stop|restart|status|monitor|meta-data}" exit 1 ;; esac exit 0 diff --git a/tools/ocft/caselib.in b/tools/ocft/caselib.in index 1857e6381..33ffa72dd 100644 --- a/tools/ocft/caselib.in +++ b/tools/ocft/caselib.in @@ -1,299 +1,299 @@ # # Copyright (c) 2010-2011 Novell Inc, John Shi # All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. quit() { local ret ret="$1" while [ $__OCFT__atexit_num -gt 0 ]; do atexit$__OCFT__atexit_num let __OCFT__atexit_num-- done rm -rf $__OCFT__fakebin exit $ret } agent_install() { local pkg if [ $# -eq 0 ]; then return 0 fi for pkg in "$@"; do if [ -e /etc/SuSE-release ]; then if ! zypper -q install -y "$pkg" >/dev/null 2>&1; then echo echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi elif [ -e /etc/debian_version ]; then if ! apt-get -y install "$pkg" >/dev/null 2>&1; then echo echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi elif [ -e /etc/redhat-release ]; then if ! yum -y install "$pkg" >/dev/null 2>&1; then echo echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi else echo "${__OCFT__showhost}ERROR: Cannot detect your OS type." quit 2 fi done } set_ocf_env() { export OCF_RA_VERSION_MAJOR=1 export OCF_RA_VERSION_MINOR=0 export OCF_RESOURCE_TYPE=$1 export OCF_RESOURCE_INSTANCE=${OCF_RESOURCE_INSTANCE:-"ocft"} } agent_run() { local agent cmd timeout pid i ret aroot agent="$1" cmd="$2" timeout="$3" set_ocf_env $agent export OCF_RESKEY_CRM_meta_timeout : ${OCF_RESKEY_CRM_meta_timeout:=$timeout} aroot=${__OCFT__MYROOT:-$__OCFT__AGENT_ROOT} - setsid $aroot/$agent $cmd >/tmp/.ocft_runlog 2>&1 & + setsid $aroot/$agent $cmd >${HA_RSCTMP}/.ocft_runlog 2>&1 & pid=$! i=0 while [ $i -lt $timeout ]; do if [ ! -e /proc/$pid ]; then break fi sleep 1 let i++ done if [ $i -ge $timeout ]; then kill -SIGTERM -$pid >/dev/null 2>&1 sleep 3 kill -SIGKILL -$pid >/dev/null 2>&1 echo -n "${__OCFT__showhost}ERROR: The agent was hanging, killed it, " echo "maybe you damaged the agent or system's environment, see details below:" - cat /tmp/.ocft_runlog + cat ${HA_RSCTMP}/.ocft_runlog echo quit 1 fi wait $pid } check_success() { local ret msg ret="$1" msg="$2" if [ $ret -ne 0 ]; then echo "${__OCFT__showhost}ERROR: '${msg}' failed, the return code is ${ret}." quit 1 fi } __maxfd() { (echo 0; ls -1 /proc/$$/fd) | sort -rn | head -1 } __getfd() { local host rw fd file host="$1" rw="$2" for fd in /proc/$$/fd/*; do file=$(basename "$(readlink $fd)") if [ "$file" = "${host}_$rw" ]; then basename $fd break fi done } backbash_start() { local host fd rfd wfd host="$1" if [ ! -d "$__OCFT__CASES_DIR" ]; then echo "${__OCFT__showhost}ERROR: Could not found Directory: ${__OCFT__CASES_DIR}." quit 1 fi if lsof $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then echo "${__OCFT__showhost}ERROR: Connection exist with $host." quit 1 fi if [ ! -p "$__OCFT__CASES_DIR/${host}_r" ] || [ ! -p "$__OCFT__CASES_DIR/${host}_w" ]; then rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w if ! mkfifo $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then echo "${__OCFT__showhost}ERROR: Could not create pipe file: $__OCFT__CASES_DIR/${host}_*." quit 1 fi fi ssh root@$host '@BASH_SHELL@ 2>&1 - sed "s/00/001/g" /tmp/.backbash-log + sed "s/00/001/g" ${HA_RSCTMP}/.backbash-log echo 000 echo 1' >$__OCFT__CASES_DIR/${host}_r <$__OCFT__CASES_DIR/${host}_w & fd=$(__maxfd) rfd=$(expr $fd + 1) wfd=$(expr $fd + 2) eval "exec ${rfd}<$__OCFT__CASES_DIR/${host}_r ${wfd}>$__OCFT__CASES_DIR/${host}_w" } backbash() { local host rfd wfd ret host="$1" rfd=$(__getfd $host r) wfd=$(__getfd $host w) if [ -z "$rfd" -o -z "$wfd" ]; then echo "${__OCFT__showhost}ERROR: Could not found connection with $host." fi cat >&$wfd <&$wfd cat >&$wfd <&/tmp/.backbash-log -sed 's/00/001/g' /tmp/.backbash-log +} >&${HA_RSCTMP}/.backbash-log +sed 's/00/001/g' ${HA_RSCTMP}/.backbash-log echo 000 echo 0 EOF if [ $? -ne 0 ]; then echo "${__OCFT__showhost}ERROR: Broken connection with $host." quit 1 fi awk -vlive=2 '{ if (sub(/000$/, "")) { if ($0 != "") { gsub("001", "00"); printf("%s", $0); } getline live; exit; } gsub("001", "00"); print; } END { exit(live); }' <&$rfd case $? in 1) quit 1 ;; 2) echo "${__OCFT__showhost}ERROR: Broken connection with $host." quit 1 ;; esac } backbash_stop() { local host rfd wfd host="$1" wfd=$(__getfd $host w) if [ -n "$wfd" ]; then cat >&$wfd <<<'quit 0' fi rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w } export OCF_ROOT=@OCF_ROOT_DIR@ export OCF_LIB=@OCF_LIB_DIR@/heartbeat __OCFT__AGENT_ROOT=@OCF_RA_DIR@/heartbeat __OCFT__CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases OCFT_DIR=@datadir@/@PACKAGE_NAME@/ocft . $OCFT_DIR/helpers.sh __OCFT__atexit_num=0 if [ $EUID -ne 0 ]; then echo "${__OCFT__showhost}ERROR: '$0' needs to be run by root." quit 3 fi __OCFT__fakebin=./fakebin mkdir -p $__OCFT__fakebin >/dev/null 2>&1 && ln -sf /bin/true $__OCFT__fakebin/crm_master >/dev/null 2>&1 && ln -sf /bin/true $__OCFT__fakebin/crm_mon >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "${__OCFT__showhost}ERROR: initialize 'fakebin' failed." quit 3 fi export HA_SBIN_DIR=$__OCFT__fakebin . $OCF_LIB/ocf-returncodes || { echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-returncodes not found." quit 3 } . $OCF_LIB/ocf-directories || { echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-directories not found." quit 3 } while read __OCFT__line; do if [ -n "$__OCFT__line" ]; then __OCFT__retn=${__OCFT__line%%=*} __OCFT__reti=$(eval echo \$$__OCFT__retn) __OCFT__retval[__OCFT__reti]=$__OCFT__retn fi done <<<"$(sed 's/#.*//' $OCF_LIB/ocf-returncodes)" # vim:ts=2:sw=2:et: