diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am index 8699311a5..adfd97c68 100644 --- a/heartbeat/Makefile.am +++ b/heartbeat/Makefile.am @@ -1,129 +1,131 @@ # Makefile.am for OCF RAs # # Author: Sun Jing Dong # Copyright (C) 2004 IBM # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = $(ocf_SCRIPTS) $(ocfcommon_DATA) \ $(common_DATA) $(hb_DATA) $(dtd_DATA) \ README INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha ocfdir = $(OCF_RA_DIR_PREFIX)/heartbeat dtddir = $(datadir)/$(PACKAGE_NAME) dtd_DATA = ra-api-1.dtd if USE_IPV6ADDR ocf_PROGRAMS = IPv6addr else ocf_PROGRAMS = endif IPv6addr_SOURCES = IPv6addr.c IPv6addr_LDADD = -lplumb $(LIBNETLIBS) ocf_SCRIPTS = ClusterMon \ CTDB \ Dummy \ IPaddr \ IPaddr2 \ drbd \ anything \ AoEtarget \ apache \ asterisk \ nginx \ AudibleAlarm \ conntrackd \ db2 \ Delay \ eDir88 \ EvmsSCC \ Evmsd \ ethmonitor \ exportfs \ Filesystem \ fio \ ids \ iscsi \ ICP \ IPsrcaddr \ iSCSITarget \ iSCSILogicalUnit \ jboss \ LinuxSCSI \ LVM \ lxc \ MailTo \ ManageRAID \ ManageVE \ mysql \ mysql-proxy \ named \ nfsserver \ oracle \ oralsnr \ pingd \ portblock \ postfix \ pound \ pgsql \ proftpd \ Pure-FTPd \ Raid1 \ Route \ rsyncd \ rsyslog \ SAPDatabase \ SAPInstance \ SendArp \ ServeRAID \ slapd \ SphinxSearchDaemon \ Squid \ Stateful \ SysInfo \ scsi2reservation \ sfex \ symlink \ syslog-ng \ tomcat \ VIPArip \ VirtualDomain \ varnish \ vmware \ WAS \ WAS6 \ WinPopup \ Xen \ Xinetd ocfcommondir = $(OCF_LIB_DIR_PREFIX)/heartbeat ocfcommon_DATA = ocf-shellfuncs \ ocf-binaries \ ocf-directories \ ocf-returncodes \ apache-conf.sh \ - http-mon.sh + http-mon.sh \ + sapdb-nosha.sh \ + sapdb.sh # Legacy locations hbdir = $(sysconfdir)/ha.d hb_DATA = shellfuncs diff --git a/heartbeat/SAPDatabase b/heartbeat/SAPDatabase index 9a695bf46..7beb236a6 100755 --- a/heartbeat/SAPDatabase +++ b/heartbeat/SAPDatabase @@ -1,1008 +1,329 @@ #!/bin/sh # # SAPDatabase # # Description: Manages any type of SAP supported database instance # as a High-Availability OCF compliant resource. # # Author: Alexander Krauth, October 2006 # Support: linux@sap.com # License: GNU General Public License (GPL) -# Copyright: (c) 2006, 2007 Alexander Krauth +# Copyright: (c) 2006, 2007, 2010, 2012 Alexander Krauth # # An example usage: # See usage() function below for more details... # # OCF instance parameters: -# OCF_RESKEY_SID -# OCF_RESKEY_DIR_EXECUTABLE (optional, well known directories will be searched by default) -# OCF_RESKEY_DBTYPE -# OCF_RESKEY_NETSERVICENAME (optional, non standard name of Oracle Listener) -# OCF_RESKEY_DBJ2EE_ONLY (optional, default is false) -# OCF_RESKEY_JAVA_HOME (optional, only needed if DBJ2EE_ONLY is true and JAVA_HOME enviroment variable is not set) -# OCF_RESKEY_STRICT_MONITORING (optional, activate application level monitoring - with Oracle a failover will occur in case of an archiver stuck) -# OCF_RESKEY_AUTOMATIC_RECOVER (optional, automatic startup recovery, default is false) -# OCF_RESKEY_DIR_BOOTSTRAP (optional, if non standard J2EE server directory) -# OCF_RESKEY_DIR_SECSTORE (optional, if non standard J2EE secure store directory) -# OCF_RESKEY_DB_JARS (optional, if maintained in bootstrap.properties, mandatory for WebAS Java 7.10) -# OCF_RESKEY_PRE_START_USEREXIT (optional, lists a script which can be executed before the resource is started) -# OCF_RESKEY_POST_START_USEREXIT (optional, lists a script which can be executed after the resource is started) -# OCF_RESKEY_PRE_STOP_USEREXIT (optional, lists a script which can be executed before the resource is stopped) -# OCF_RESKEY_POST_STOP_USEREXIT (optional, lists a script which can be executed after the resource is stopped) -# -# ToDo: -# Remove all the database dependend stuff from the agent and use -# saphostcontrol daemon as soon as SAP will release it. +# OCF_RESKEY_SID +# OCF_RESKEY_DIR_EXECUTABLE (optional, well known directories will be searched by default) +# OCF_RESKEY_DBTYPE (mandatory, one of the following values: ORA,ADA,DB6,SYB,HDB) +# OCF_RESKEY_DBINSTANCE (optional, Database instance name, if not equal to SID) +# OCF_RESKEY_STRICT_MONITORING (optional, activate application level monitoring - with Oracle a failover will occur in case of an archiver stuck) +# OCF_RESKEY_AUTOMATIC_RECOVER (optional, automatic startup recovery, default is false) +# OCF_RESKEY_MONITOR_SERVICES (optional, default is to monitor all database services) +# OCF_RESKEY_PRE_START_USEREXIT (optional, lists a script which can be executed before the resource is started) +# OCF_RESKEY_POST_START_USEREXIT (optional, lists a script which can be executed after the resource is started) +# OCF_RESKEY_PRE_STOP_USEREXIT (optional, lists a script which can be executed before the resource is stopped) +# OCF_RESKEY_POST_STOP_USEREXIT (optional, lists a script which can be executed after the resource is stopped) +# Deprecated parameters: +# OCF_RESKEY_NETSERVICENAME +# OCF_RESKEY_DBJ2EE_ONLY +# OCF_RESKEY_JAVA_HOME +# OCF_RESKEY_DIR_BOOTSTRAP +# OCF_RESKEY_DIR_SECSTORE +# OCF_RESKEY_DB_JARS # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ####################################################################### SH=/bin/sh usage() { methods=`sapdatabase_methods` methods=`echo $methods | tr ' ' '|'` cat <<-! usage: $0 ($methods) $0 manages a SAP database of any type as an HA resource. - Currently Oracle, MaxDB and DB/2 UDB are supported. + Currently Oracle, MaxDB, DB/2 UDB, Sybase ASE and SAP HANA Database are supported. ABAP databases as well as JAVA only databases are supported. The 'start' operation starts the instance. The 'stop' operation stops the instance. The 'status' operation reports whether the instance is running The 'monitor' operation reports whether the instance seems to be working The 'recover' operation tries to recover the instance after a crash (instance will be stopped first!) The 'validate-all' operation reports whether the parameters are valid The 'methods' operation reports on the methods $0 supports ! } meta_data() { cat < -1.93 +2.06 +Manages a SAP database instance as an HA resource. Resource script for SAP databases. It manages a SAP database of any type as an HA resource. - -Manages any SAP database (based on Oracle, MaxDB, or DB2) +The purpose of the resource agent is to start, stop and monitor the database instance of a SAP system. Together with the RDBMS system it will also control the related network service for the database. Like the Oracle Listener and the xserver of MaxDB. +The resource agent expects a standard SAP installation of the database and therefore needs less parameters to configure. +The resource agent supports the following databases: +- Oracle 10.2 and 11.2 +- DB/2 UDB for Windows and Unix 9.x +- SAP-DB / MaxDB 7.x +- Sybase ASE 15.7 +- SAP HANA Database since 1.00 - with SAP node 1625203 (http://sdn.sap.com) + +In fact this resource agent does not run any database commands directly. It uses the SAP standard process SAPHostAgent to control the database. +The SAPHostAgent must be installed on each cluster node locally. It will not work, if you try to run the SAPHostAgent also as a HA resource. +Please follow SAP note 1031096 for the installation of SAPHostAgent. +The required minimum version of SAPHostAgent is: +Release: 7.20 +Patch Number: 90 +or compile time after: Dec 17 2011 + - The unique SAP system identifier. e.g. P01 - SAP system ID + The unique database system identifier. e.g. P01 + Database system ID - The full qualified path where to find sapstartsrv and sapcontrol. - path of sapstartsrv and sapcontrol - + The full qualified path where to find saphostexec and saphostctrl. +Usually you can leave this empty. Then the default: /usr/sap/hostctrl/exe is used. + + path of saphostexec and saphostctrl + - The name of the database vendor you use. Set either: ORA,DB6,ADA + The name of the database vendor you use. Set either: ADA, DB6, ORA, SYB, HDB database vendor + + Must be used for special database implementations, when database instance name is not equal to the SID (e.g. Oracle DataGuard) + Database instance name, if not equal to SID + + - The Oracle TNS listener name. - listener name + Deprecated - do not use anymore. This parameter will be deleted in one of the next releases. + deprecated - do not use anymore - If you do not have a ABAP stack installed in the SAP database, set this to TRUE - only JAVA stack installed - + Deprecated - do not use anymore. This parameter will be deleted in one of the next releases. + deprecated - do not use anymore + - This is only needed if the DBJ2EE_ONLY parameter is set to true. Enter the path to the Java SDK which is used by the SAP WebAS Java - Path to Java SDK + Deprecated - do not use anymore. This parameter will be deleted in one of the next releases. + deprecated - do not use anymore - This controls how the resource agent monitors the database. If set to true, it will use SAP tools to test the connect to the database. Do not use with Oracle, because it will result in unwanted failovers in case of an archiver stuck + This controls how the resource agent monitors the database. If set to true, it will use 'saphostctrl -function GetDatabaseStatus' to test the database state. If set to false, only operating system processes are monitored. Activates application level monitoring - The SAPDatabase resource agent tries to recover a failed start attempt automaticaly one time. This is done by running a forced abort of the RDBMS and/or executing recovery commands. + If you set this to true, 'saphostctrl -function StartDatabase' will always be called with the '-force' option. Enable or disable automatic startup recovery + + Defines which services are monitored by the SAPDatabase resource agent, if STRICT_MONITORING is set to true. Service names must correspond with the output of the 'saphostctrl -function GetDatabaseStatus' command. + Database services to monitor + + - The full qualified path where to find the J2EE instance bootstrap directory. e.g. /usr/sap/P01/J00/j2ee/cluster/bootstrap - path to j2ee bootstrap directory + Deprecated - do not use anymore. This parameter will be deleted in one of the next releases. + deprecated - do not use anymore - The full qualified path where to find the J2EE security store directory. e.g. /usr/sap/P01/SYS/global/security/lib/tools - path to j2ee secure store directory + Deprecated - do not use anymore. This parameter will be deleted in one of the next releases. + deprecated - do not use anymore - The full qualified filename of the jdbc driver for the database connection test. It will be automaticaly read from the bootstrap.properties file in Java engine 6.40 and 7.00. For Java engine 7.10 and higher the parameter is mandatory. - file name of the jdbc driver + Deprecated - do not use anymore. This parameter will be deleted in one of the next releases. + deprecated - do not use anymore The full qualified path where to find a script or program which should be executed before this resource gets started. path to a pre-start script The full qualified path where to find a script or program which should be executed after this resource got started. path to a post-start script The full qualified path where to find a script or program which should be executed before this resource gets stopped. path to a pre-start script The full qualified path where to find a script or program which should be executed after this resource got stopped. path to a post-start script END } -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 -} # # methods: What methods/operations do we support? # sapdatabase_methods() { cat <<-! start stop status monitor - recover + recover validate-all methods meta-data usage ! } # # sapuserexit : Many SAP customers need some additional processes/tools to run their SAP systems. # This specialties do not allow a totally generic SAP cluster resource agent. # Someone should write a resource agent for each additional process you need, if it # is required to monitor that process within the cluster manager. To enable # you to extent this resource agent without developing a new one, this user exit # was introduced. # sapuserexit() { NAME="$1" VALUE="$2" if [ -n "$VALUE" ] then - if [ -x "$VALUE" ] + if have_binary "$VALUE" then ocf_log info "Calling userexit ${NAME} with customer script file ${VALUE}" "$VALUE" >/dev/null 2>&1 ocf_log info "Exiting userexit ${NAME} with customer script file ${VALUE}, returncode: $?" else ocf_log warn "Attribute ${NAME} is set to ${VALUE}, but this file is not executable" fi fi - return 0 + return $OCF_SUCCESS } # -# sapdatabase_start : Start the SAP database +# saphostctrl_installed # -sapdatabase_start() { - sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT" +saphostctrl_installed() { + OCF_RESKEY_DIR_EXECUTABLE_default="/usr/sap/hostctrl/exe" + : ${OCF_RESKEY_DIR_EXECUTABLE=${OCF_RESKEY_DIR_EXECUTABLE_default}} + SAPHOSTCTRL="${OCF_RESKEY_DIR_EXECUTABLE}/saphostctrl" + SAPHOSTEXEC="${OCF_RESKEY_DIR_EXECUTABLE}/saphostexec" - 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 ist 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 + have_binary $SAPHOSTCTRL && have_binary $SAPHOSTEXEC } # # 'main' starts here... # if ( [ $# -ne 1 ] ) then usage exit $OCF_ERR_ARGS fi -# Set a tempfile and make sure to clean it up again -TEMPFILE="/tmp/SAPDatabase.$$.tmp" -trap trap_handler INT TERM - # These operations don't require OCF instance parameters to be set case "$1" in meta-data) meta_data exit $OCF_SUCCESS;; usage) usage exit $OCF_SUCCESS;; methods) sapdatabase_methods exit $?;; *);; esac -US=`id -u -n` -US=`echo $US` -if - [ $US != root ] +if ! ocf_is_root then ocf_log err "$0 must be run as root" exit $OCF_ERR_PERM fi # mandatory parameter check if [ -z "$OCF_RESKEY_SID" ]; then ocf_log err "Please set OCF_RESKEY_SID to the SAP system id!" exit $OCF_ERR_ARGS fi SID=`echo "$OCF_RESKEY_SID"` if [ -z "$OCF_RESKEY_DBTYPE" ]; then - ocf_log err "Please set OCF_RESKEY_DBTYPE to the database vendor specific tag (ORA,ADA,DB6)!" + ocf_log err "Please set OCF_RESKEY_DBTYPE to the database vendor specific tag (ADA,DB6,ORA,SYB,HDB)!" exit $OCF_ERR_ARGS fi -DBTYPE=`echo "$OCF_RESKEY_DBTYPE" | tr "[a-z]" "[A-Z]"` - -# 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 +DBTYPE=`echo "$OCF_RESKEY_DBTYPE" | tr '[:lower:]' '[:upper:]'` -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 +# source functions and initialize global variables +if saphostctrl_installed; then + . ${OCF_FUNCTIONS_DIR}/sapdb.sh 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 + . ${OCF_FUNCTIONS_DIR}/sapdb-nosha.sh fi +sapdatabase_init -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 ] +# we always want to fall to the faster status method in case of a probe by the cluster +ACTION=$1 +if ocf_is_probe 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 + ACTION=status fi -sidadm="`echo $SID | tr '[:upper:]' '[:lower:]'`adm" # What kind of method was invoked? -case "$1" in - - start) sapdatabase_start - exit $?;; - - stop) sapdatabase_stop - exit $?;; - - monitor) - sapdatabase_monitor $OCF_RESKEY_STRICT_MONITORING - exit $?;; - - status) - sapdatabase_status - exit $?;; - - recover) sapdatabase_recover - exit $?;; - - validate-all) sapdatabase_validate - exit $?;; - - *) sapdatabase_methods - exit $OCF_ERR_UNIMPLEMENTED;; +case "$ACTION" in + + start|stop|status|recover) sapdatabase_$ACTION + exit $?;; + monitor) sapdatabase_monitor $OCF_RESKEY_STRICT_MONITORING + exit $?;; + validate-all) sapdatabase_validate + exit $?;; + *) sapdatabase_methods + exit $OCF_ERR_UNIMPLEMENTED;; esac diff --git a/heartbeat/SAPDatabase b/heartbeat/sapdb-nosha.sh old mode 100755 new mode 100644 similarity index 60% copy from heartbeat/SAPDatabase copy to heartbeat/sapdb-nosha.sh index 9a695bf46..c6599094f --- a/heartbeat/SAPDatabase +++ b/heartbeat/sapdb-nosha.sh @@ -1,1008 +1,744 @@ -#!/bin/sh # -# SAPDatabase +# sapdatabase-nosha - for systems not having SAPHostAgent installed +# (sourced by SAPDatabase) # -# Description: Manages any type of SAP supported database instance -# as a High-Availability OCF compliant resource. +# 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 # -# An example usage: -# See usage() function below for more details... -# -# OCF instance parameters: -# OCF_RESKEY_SID -# OCF_RESKEY_DIR_EXECUTABLE (optional, well known directories will be searched by default) -# OCF_RESKEY_DBTYPE -# OCF_RESKEY_NETSERVICENAME (optional, non standard name of Oracle Listener) -# OCF_RESKEY_DBJ2EE_ONLY (optional, default is false) -# OCF_RESKEY_JAVA_HOME (optional, only needed if DBJ2EE_ONLY is true and JAVA_HOME enviroment variable is not set) -# OCF_RESKEY_STRICT_MONITORING (optional, activate application level monitoring - with Oracle a failover will occur in case of an archiver stuck) -# OCF_RESKEY_AUTOMATIC_RECOVER (optional, automatic startup recovery, default is false) -# OCF_RESKEY_DIR_BOOTSTRAP (optional, if non standard J2EE server directory) -# OCF_RESKEY_DIR_SECSTORE (optional, if non standard J2EE secure store directory) -# OCF_RESKEY_DB_JARS (optional, if maintained in bootstrap.properties, mandatory for WebAS Java 7.10) -# OCF_RESKEY_PRE_START_USEREXIT (optional, lists a script which can be executed before the resource is started) -# OCF_RESKEY_POST_START_USEREXIT (optional, lists a script which can be executed after the resource is started) -# OCF_RESKEY_PRE_STOP_USEREXIT (optional, lists a script which can be executed before the resource is stopped) -# OCF_RESKEY_POST_STOP_USEREXIT (optional, lists a script which can be executed after the resource is stopped) -# -# ToDo: -# Remove all the database dependend stuff from the agent and use -# saphostcontrol daemon as soon as SAP will release it. -# -####################################################################### -# Initialization: - -: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} -. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs - -####################################################################### - -SH=/bin/sh - -usage() { - methods=`sapdatabase_methods` - methods=`echo $methods | tr ' ' '|'` - cat <<-! - usage: $0 ($methods) - - $0 manages a SAP database of any type as an HA resource. - Currently Oracle, MaxDB and DB/2 UDB are supported. - ABAP databases as well as JAVA only databases are supported. - - The 'start' operation starts the instance. - The 'stop' operation stops the instance. - The 'status' operation reports whether the instance is running - The 'monitor' operation reports whether the instance seems to be working - The 'recover' operation tries to recover the instance after a crash (instance will be stopped first!) - The 'validate-all' operation reports whether the parameters are valid - The 'methods' operation reports on the methods $0 supports - - ! -} -meta_data() { - cat < - - -1.93 - - -Resource script for SAP databases. It manages a SAP database of any type as an HA resource. - -Manages any SAP database (based on Oracle, MaxDB, or DB2) - - - - The unique SAP system identifier. e.g. P01 - SAP system ID - - - - The full qualified path where to find sapstartsrv and sapcontrol. - path of sapstartsrv and sapcontrol - - - - The name of the database vendor you use. Set either: ORA,DB6,ADA - database vendor - - - - The Oracle TNS listener name. - listener name - - - - If you do not have a ABAP stack installed in the SAP database, set this to TRUE - only JAVA stack installed - - - - This is only needed if the DBJ2EE_ONLY parameter is set to true. Enter the path to the Java SDK which is used by the SAP WebAS Java - Path to Java SDK - - - - This controls how the resource agent monitors the database. If set to true, it will use SAP tools to test the connect to the database. Do not use with Oracle, because it will result in unwanted failovers in case of an archiver stuck - Activates application level monitoring - - - - The SAPDatabase resource agent tries to recover a failed start attempt automaticaly one time. This is done by running a forced abort of the RDBMS and/or executing recovery commands. - Enable or disable automatic startup recovery - - - - The full qualified path where to find the J2EE instance bootstrap directory. e.g. /usr/sap/P01/J00/j2ee/cluster/bootstrap - path to j2ee bootstrap directory - - - - The full qualified path where to find the J2EE security store directory. e.g. /usr/sap/P01/SYS/global/security/lib/tools - path to j2ee secure store directory - - - - The full qualified filename of the jdbc driver for the database connection test. It will be automaticaly read from the bootstrap.properties file in Java engine 6.40 and 7.00. For Java engine 7.10 and higher the parameter is mandatory. - file name of the jdbc driver - - - - The full qualified path where to find a script or program which should be executed before this resource gets started. - path to a pre-start script - - - - The full qualified path where to find a script or program which should be executed after this resource got started. - path to a post-start script - - - - The full qualified path where to find a script or program which should be executed before this resource gets stopped. - path to a pre-start script - - - - The full qualified path where to find a script or program which should be executed after this resource got stopped. - path to a post-start script - - - - - - - - - - - - - - -END -} 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 } -# -# methods: What methods/operations do we support? -# -sapdatabase_methods() { - cat <<-! - start - stop - status - monitor - recover - validate-all - methods - meta-data - usage - ! -} - - -# -# sapuserexit : Many SAP customers need some additional processes/tools to run their SAP systems. -# This specialties do not allow a totally generic SAP cluster resource agent. -# Someone should write a resource agent for each additional process you need, if it -# is required to monitor that process within the cluster manager. To enable -# you to extent this resource agent without developing a new one, this user exit -# was introduced. -# -sapuserexit() { - NAME="$1" - VALUE="$2" - - if [ -n "$VALUE" ] - then - if [ -x "$VALUE" ] - then - ocf_log info "Calling userexit ${NAME} with customer script file ${VALUE}" - "$VALUE" >/dev/null 2>&1 - ocf_log info "Exiting userexit ${NAME} with customer script file ${VALUE}, returncode: $?" - else - ocf_log warn "Attribute ${NAME} is set to ${VALUE}, but this file is not executable" - fi - fi - return 0 -} - # # 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 ist 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 } # -# 'main' starts here... +# sapdatabase_init: initialize global variables at the beginning # +sapdatabase_init() { -if - ( [ $# -ne 1 ] ) -then - usage - exit $OCF_ERR_ARGS -fi - -# Set a tempfile and make sure to clean it up again -TEMPFILE="/tmp/SAPDatabase.$$.tmp" -trap trap_handler INT TERM - -# These operations don't require OCF instance parameters to be set -case "$1" in - meta-data) meta_data - exit $OCF_SUCCESS;; - - usage) usage - exit $OCF_SUCCESS;; - - methods) sapdatabase_methods - exit $?;; - - *);; -esac - -US=`id -u -n` -US=`echo $US` -if - [ $US != root ] -then - ocf_log err "$0 must be run as root" - exit $OCF_ERR_PERM -fi - -# mandatory parameter check -if [ -z "$OCF_RESKEY_SID" ]; then - ocf_log err "Please set OCF_RESKEY_SID to the SAP system id!" - exit $OCF_ERR_ARGS -fi -SID=`echo "$OCF_RESKEY_SID"` - -if [ -z "$OCF_RESKEY_DBTYPE" ]; then - ocf_log err "Please set OCF_RESKEY_DBTYPE to the database vendor specific tag (ORA,ADA,DB6)!" - exit $OCF_ERR_ARGS -fi -DBTYPE=`echo "$OCF_RESKEY_DBTYPE" | tr "[a-z]" "[A-Z]"` +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" +} -# What kind of method was invoked? -case "$1" in - - start) sapdatabase_start - exit $?;; - - stop) sapdatabase_stop - exit $?;; - - monitor) - sapdatabase_monitor $OCF_RESKEY_STRICT_MONITORING - exit $?;; - - status) - sapdatabase_status - exit $?;; - - recover) sapdatabase_recover - exit $?;; - - validate-all) sapdatabase_validate - exit $?;; - - *) sapdatabase_methods - exit $OCF_ERR_UNIMPLEMENTED;; -esac +# 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 diff --git a/heartbeat/sapdb.sh b/heartbeat/sapdb.sh new file mode 100644 index 000000000..d77d1eb0a --- /dev/null +++ b/heartbeat/sapdb.sh @@ -0,0 +1,282 @@ +# +# sapdb.sh - for systems having SAPHostAgent installed +# (sourced by SAPDatabase) +# +# Description: This code is separated from the SAPDatabase agent to +# introduce new functions for systems which having +# SAPHostAgent installed. +# Someday it might be merged back into SAPDatabase agein. +# +# Author: Alexander Krauth, September 2010 +# Support: linux@sap.com +# License: GNU General Public License (GPL) +# Copyright: (c) 2010, 2012 Alexander Krauth +# + + +# +# check_saphostexec : Before using saphostctrl we make sure that the saphostexec is running on the current node. +# +check_saphostexec() { + restart=0 + runninginst="" + chkrc=$OCF_SUCCESS + + output=`$SAPHOSTEXEC -status 2>&1` + if [ $? -ne 0 ] + then + ocf_log warn "saphostexec is not running on node `hostname`, it will be started now" + output=`$SAPHOSTEXEC -restart 2>&1` + + # now make sure the daemon has been started and is able to respond + srvrc=1 + while [ $srvrc -ne 0 -a `pgrep -f "$SAPHOSTEXEC" | wc -l` -gt 0 ] + do + sleep 1 + output=`$SAPHOSTEXEC -status 2>&1` + srvrc=$? + done + + if [ $srvrc -eq 0 ] + then + ocf_log info "saphostexec on node `hostname` was restarted !" + chkrc=$OCF_SUCCESS + else + ocf_log error "saphostexec on node `hostname` could not be started! - $output" + chkrc=$OCF_ERR_GENERIC + fi + fi + + return $chkrc +} + + +# +# sapdatabase_start : Start the SAP database +# +sapdatabase_start() { + + check_saphostexec + rc=$? + + if [ $rc -eq $OCF_SUCCESS ] + then + sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT" + + DBINST="" + if [ -n "$OCF_RESKEY_DBINSTANCE" ] + then + DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE " + fi + FORCE="" + if ocf_is_true $OCF_RESKEY_AUTOMATIC_RECOVER + then + FORCE="-force" + fi + output=`$SAPHOSTCTRL -function StartDatabase -dbname $SID -dbtype $DBTYPE $DBINST $FORCE -service` + + sapdatabase_monitor 1 + rc=$? + + 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 + fi + + return $rc +} + +# +# sapdatabase_stop: Stop the SAP database +# +sapdatabase_stop() { + + check_saphostexec + rc=$? + + if [ $rc -eq $OCF_SUCCESS ] + then + sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT" + + DBINST="" + if [ -n "$OCF_RESKEY_DBINSTANCE" ] + then + DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE " + fi + output=`$SAPHOSTCTRL -function StopDatabase -dbname $SID -dbtype $DBTYPE $DBINST -force -service` + + 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 + fi + + 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 + rc=$OCF_SUCCESS + + if ! ocf_is_true $strict + then + sapdatabase_status + rc=$? + else + check_saphostexec + rc=$? + + if [ $rc -eq $OCF_SUCCESS ] + then + count=0 + + DBINST="" + if [ -n "$OCF_RESKEY_DBINSTANCE" ] + then + DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE " + fi + output=`$SAPHOSTCTRL -function GetDatabaseStatus -dbname $SID -dbtype $DBTYPE $DBINST` + + # we have to parse the output, because the returncode doesn't tell anything about the instance status + for SERVICE in `echo "$output" | grep -i 'Component[ ]*Name *[:=] [A-Za-z][A-Za-z0-9_]* (' | sed 's/^.*Component[ ]*Name *[:=] *\([A-Za-z][A-Za-z0-9_]*\).*$/\1/i'` + do + COLOR=`echo "$output" | grep -i "Component[ ]*Name *[:=] *$SERVICE (" | sed 's/^.*Status *[:=] *\([A-Za-z][A-Za-z0-9_]*\).*$/\1/i'` + STATE=0 + + case $COLOR in + Running) STATE=$OCF_SUCCESS;; + *) STATE=$OCF_NOT_RUNNING;; + esac + + SEARCH=`echo "$OCF_RESKEY_MONITOR_SERVICES" | sed 's/\+/\\\+/g' | sed 's/\./\\\./g'` + if [ `echo "$SERVICE" | egrep -c "$SEARCH"` -eq 1 ] + then + if [ $STATE -eq $OCF_NOT_RUNNING ] + then + ocf_log err "SAP database service $SERVICE is not running with status $COLOR !" + rc=$STATE + fi + count=1 + fi + done + + if [ $count -eq 0 -a $rc -eq $OCF_SUCCESS ] + then + ocf_log err "The resource does not run any services which this RA could monitor!" + rc=$OCF_ERR_ARGS + fi + + if [ $rc -ne $OCF_SUCCESS ] + then + ocf_log err "The SAP database $SID ist not running: $output" + fi + fi + 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 + ;; + SYB) SEARCH="dataserver" + SUSER="syb`echo $SID | tr '[:upper:]' '[:lower:]'`" + SNUM=1 + ;; + HDB) SEARCH="hdb[a-z]*server" + SUSER="`echo $SID | tr '[:upper:]' '[:lower:]'`adm" + SNUM=1 + ;; + esac + + cnt=`ps -u $SUSER -o args 2> /dev/null | grep -c $SEARCH` + [ $cnt -ge $SNUM ] && return $OCF_SUCCESS + return $OCF_NOT_RUNNING +} + + +# +# sapdatabase_recover: +# +sapdatabase_recover() { + OCF_RESKEY_AUTOMATIC_RECOVER=1 + sapdatabase_stop + sapdatabase_start +} + + +# +# 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|SYB|HDB) ;; + *) 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_RESKEY_AUTOMATIC_RECOVER_default=0 +: ${OCF_RESKEY_AUTOMATIC_RECOVER=${OCF_RESKEY_AUTOMATIC_RECOVER_default}} + +if [ -z "$OCF_RESKEY_MONITOR_SERVICES" ] +then + case $DBTYPE in + ORA) export OCF_RESKEY_MONITOR_SERVICES="Instance|Database|Listener" + ;; + ADA) export OCF_RESKEY_MONITOR_SERVICES="Database" + ;; + DB6) db2sid="db2`echo $SID | tr '[:upper:]' '[:lower:]'`" + export OCF_RESKEY_MONITOR_SERVICES="${SID}|${db2sid}" + ;; + SYB) export OCF_RESKEY_MONITOR_SERVICES="Server|Database" + ;; + HDB) export OCF_RESKEY_MONITOR_SERVICES="hdbindexserver" + ;; + esac +fi +}