The demote action is optional. It must only be supported by
stateful resource agents, which means agents that discern between
two distict roles: Master and Slave. Slave is functionally
identical to the Started state in a stateless resource agent. Thus,
while a regular (stateless) resource agent only needs to implement
start and stop, a stateful resource agent must also support the
demote action to be able to make a transition between the Master
and Started (Slave) roles.
foobar_demote() {
local rc
# exit immediately if configuration is not valid
foobar_validate_all || exit $?
# test the resource's current state
foobar_monitor
rc=$?
case "$rc" in
"$OCF_RUNNING_MASTER")
# Running as master. Normal, expected behavior.
ocf_log debug "Resource is currently running as Master"
;;
"$OCF_SUCCESS")
# Alread running as slave. Nothing to do.
ocf_log debug "Resource is currently running as Slave"
return $OCF_SUCCESS
;;
"$OCF_NOT_RUNNING")
# Currently not running. Getting a demote action
# in this state is unexpected. Exit with an error
# and let the cluster manager recover.
ocf_log err "Resource is currently not running"
exit $OCF_ERR_GENERIC
;;
*)
# Failed resource. Let the cluster manager recover.
ocf_log err "Unexpected error, cannot demote"
exit $rc
;;
esac
# actually demote the resource here (make sure to immediately
# exit with an $OCF_ERR_ error code if anything goes seriously
# wrong)
ocf_run frobnicate --unset-master-mode || exit $OCF_ERR_GENERIC
# After the resource has been demoted, check whether the
# demotion worked. If the resource demotion is asynchronous, the
# agent may spin on the monitor function here -- if the resource
# does not assume the Slave role within the defined timeout, the
# cluster manager will consider the demote action failed.
while true; do
foobar_monitor
if [ $? -eq $OCF_RUNNING_MASTER ]; then
ocf_log debug "Resource still awaiting promotion"
sleep 1
else
ocf_log debug "Resource demoted"
break
fi
done
# only return $OCF_SUCCESS if _everything_ succeeded as expected
return $OCF_SUCCESS
}