| #!/bin/sh | |
| # | |
| # | |
| # Dummy OCF RA. Does nothing but wait a few seconds, can be | |
| # configured to fail occassionally. | |
| # | |
| # Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Brée | |
| # 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=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} | |
| . ${OCF_FUNCTIONS} | |
| : ${__OCF_ACTION=$1} | |
| ####################################################################### | |
| meta_data() { | |
| cat <<END | |
| <?xml version="1.0"?> | |
| <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> | |
| <resource-agent name="Dummy" version="1.0"> | |
| <version>1.0</version> | |
| <longdesc lang="en"> | |
| This is a Dummy Resource Agent. It does absolutely nothing except | |
| keep track of whether its running or not. | |
| Its purpose in life is for testing and to serve as a template for RA writers. | |
| NB: Please pay attention to the timeouts specified in the actions | |
| section below. They should be meaningful for the kind of resource | |
| the agent manages. They should be the minimum advised timeouts, | |
| but they shouldn't/cannot cover _all_ possible resource | |
| instances. So, try to be neither overly generous nor too stingy, | |
| but moderate. The minimum timeouts should never be below 10 seconds. | |
| </longdesc> | |
| <shortdesc lang="en">Example stateless resource agent</shortdesc> | |
| <parameters> | |
| <parameter name="state" unique="1"> | |
| <longdesc lang="en"> | |
| Location to store the resource state in. | |
| </longdesc> | |
| <shortdesc lang="en">State file</shortdesc> | |
| <content type="string" default="${HA_VARRUN%%/}/Dummy-${OCF_RESOURCE_INSTANCE}.state" /> | |
| </parameter> | |
| <parameter name="passwd" unique="1"> | |
| <longdesc lang="en"> | |
| Fake password field | |
| </longdesc> | |
| <shortdesc lang="en">Password</shortdesc> | |
| <content type="string" default="" /> | |
| </parameter> | |
| <parameter name="fake" unique="0"> | |
| <longdesc lang="en"> | |
| Fake attribute that can be changed to cause a reload | |
| </longdesc> | |
| <shortdesc lang="en">Fake attribute that can be changed to cause a reload</shortdesc> | |
| <content type="string" default="dummy" /> | |
| </parameter> | |
| <parameter name="op_sleep" unique="1"> | |
| <longdesc lang="en"> | |
| Number of seconds to sleep during operations. This can be used to test how | |
| the cluster reacts to operation timeouts. | |
| </longdesc> | |
| <shortdesc lang="en">Operation sleep duration in seconds.</shortdesc> | |
| <content type="string" default="0" /> | |
| </parameter> | |
| <parameter name="fail_start_on" unique="0"> | |
| <longdesc lang="en"> | |
| Start actions will return failure if running on the host specified here, but | |
| the resource will start successfully anyway (future monitor calls will find it | |
| running). This can be used to test on-fail=ignore. | |
| </longdesc> | |
| <shortdesc lang="en">Report bogus start failure on specified host</shortdesc> | |
| <content type="string" default="" /> | |
| </parameter> | |
| <parameter name="envfile" unique="1"> | |
| <longdesc lang="en"> | |
| If this is set, the environment will be dumped to this file for every call. | |
| </longdesc> | |
| <shortdesc lang="en">Environment dump file</shortdesc> | |
| <content type="string" default="" /> | |
| </parameter> | |
| </parameters> | |
| <actions> | |
| <action name="start" timeout="20" /> | |
| <action name="stop" timeout="20" /> | |
| <action name="monitor" timeout="20" interval="10" depth="0"/> | |
| <action name="reload" timeout="20" /> | |
| <action name="migrate_to" timeout="20" /> | |
| <action name="migrate_from" timeout="20" /> | |
| <action name="validate-all" timeout="20" /> | |
| <action name="meta-data" timeout="5" /> | |
| </actions> | |
| </resource-agent> | |
| END | |
| } | |
| ####################################################################### | |
| # don't exit on TERM, to test that lrmd makes sure that we do exit | |
| trap sigterm_handler TERM | |
| sigterm_handler() { | |
| ocf_log info "They use TERM to bring us down. No such luck." | |
| return | |
| } | |
| dummy_usage() { | |
| cat <<END | |
| usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data} | |
| Expects to have a fully populated OCF RA-compliant environment set. | |
| END | |
| } | |
| dump_env() { | |
| if [ "${OCF_RESKEY_envfile}" != "" ]; then | |
| echo "### ${__OCF_ACTION} @ $(date) ### | |
| $(env | sort) | |
| ###" >> "${OCF_RESKEY_envfile}" | |
| fi | |
| } | |
| dummy_start() { | |
| local RETVAL | |
| dummy_monitor | |
| RETVAL=$? | |
| if [ $RETVAL -eq $OCF_SUCCESS ]; then | |
| if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then | |
| RETVAL=$OCF_ERR_GENERIC | |
| fi | |
| return $RETVAL | |
| fi | |
| touch "${OCF_RESKEY_state}" | |
| RETVAL=$? | |
| if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then | |
| RETVAL=$OCF_ERR_GENERIC | |
| fi | |
| return $RETVAL | |
| } | |
| dummy_stop() { | |
| dummy_monitor --force | |
| if [ $? -eq $OCF_SUCCESS ]; then | |
| rm ${OCF_RESKEY_state} | |
| fi | |
| rm -f "${VERIFY_SERIALIZED_FILE}" | |
| return $OCF_SUCCESS | |
| } | |
| dummy_monitor() { | |
| # Monitor _MUST!_ differentiate correctly between running | |
| # (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING). | |
| # That is THREE states, not just yes/no. | |
| if [ $OCF_RESKEY_op_sleep -ne 0 ]; then | |
| if [ "$1" = "" -a -f "${VERIFY_SERIALIZED_FILE}" ]; then | |
| # two monitor ops have occurred at the same time. | |
| # this is to verify a condition in the lrmd regression tests. | |
| ocf_log err "$VERIFY_SERIALIZED_FILE exists already" | |
| return $OCF_ERR_GENERIC | |
| fi | |
| touch "${VERIFY_SERIALIZED_FILE}" | |
| sleep ${OCF_RESKEY_op_sleep} | |
| rm "${VERIFY_SERIALIZED_FILE}" | |
| fi | |
| if [ -f "${OCF_RESKEY_state}" ]; then | |
| # Multiple monitor levels are defined to support various tests | |
| case "$OCF_CHECK_LEVEL" in | |
| 10) | |
| # monitor level with delay, useful for testing timeouts | |
| sleep 30 | |
| ;; | |
| 20) | |
| # monitor level that fails intermittently | |
| n=$(expr $(dd if=/dev/urandom bs=1 count=1 2>/dev/null | od | head -1 | cut -f2 -d' ') % 5) | |
| if [ $n -eq 1 ]; then | |
| ocf_exit_reason "smoke detected near CPU fan" | |
| return $OCF_ERR_GENERIC | |
| fi | |
| ;; | |
| 30) | |
| # monitor level that always fails | |
| ocf_exit_reason "hyperdrive quota reached" | |
| return $OCF_ERR_GENERIC | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| return $OCF_SUCCESS | |
| fi | |
| return $OCF_NOT_RUNNING | |
| } | |
| dummy_validate() { | |
| # Is the state directory writable? | |
| state_dir=`dirname "$OCF_RESKEY_state"` | |
| touch "$state_dir/$$" | |
| if [ $? -ne 0 ]; then | |
| return $OCF_ERR_ARGS | |
| fi | |
| rm "$state_dir/$$" | |
| return $OCF_SUCCESS | |
| } | |
| : ${OCF_RESKEY_fake=dummy} | |
| : ${OCF_RESKEY_op_sleep=0} | |
| : ${OCF_RESKEY_CRM_meta_interval=0} | |
| : ${OCF_RESKEY_CRM_meta_globally_unique:="false"} | |
| if [ -z "$OCF_RESKEY_state" ]; then | |
| OCF_RESKEY_state="${HA_VARRUN%%/}/Dummy-${OCF_RESOURCE_INSTANCE}.state" | |
| if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then | |
| # Strip off the trailing clone marker (note + is not portable in sed) | |
| OCF_RESKEY_state=`echo $OCF_RESKEY_state | sed s/:[0-9][0-9]*\.state/.state/` | |
| fi | |
| fi | |
| VERIFY_SERIALIZED_FILE="${OCF_RESKEY_state}.serialized" | |
| dump_env | |
| case $__OCF_ACTION in | |
| meta-data) meta_data | |
| exit $OCF_SUCCESS | |
| ;; | |
| start) dummy_start;; | |
| stop) dummy_stop;; | |
| monitor) dummy_monitor;; | |
| migrate_to) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}." | |
| dummy_stop | |
| ;; | |
| migrate_from) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}." | |
| dummy_start | |
| ;; | |
| reload) ocf_log err "Reloading..." | |
| dummy_start | |
| ;; | |
| validate-all) dummy_validate;; | |
| usage|help) dummy_usage | |
| exit $OCF_SUCCESS | |
| ;; | |
| *) dummy_usage | |
| exit $OCF_ERR_UNIMPLEMENTED | |
| ;; | |
| esac | |
| rc=$? | |
| ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" | |
| exit $rc |