Page MenuHomeClusterLabs Projects

No OneTemporary

This document is not UTF8. It was detected as Shift JIS and converted to UTF8 for display.
diff --git a/extra/resources/ClusterMon.in b/extra/resources/ClusterMon.in
index f33cfd4cef..db397c2a42 100755
--- a/extra/resources/ClusterMon.in
+++ b/extra/resources/ClusterMon.in
@@ -1,274 +1,261 @@
#!@BASH_PATH@
#
+# ocf:pacemaker:ClusterMon resource agent
#
-# ClusterMon OCF RA.
-# Starts crm_mon in background which logs cluster status as
-# html to the specified file.
-#
-# Copyright 2004-2018 SUSE LINUX AG, Lars Marowsky-Br馥
-# 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.
+# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Br<E9>e
+# Later changes copyright 2008-2018 the Pacemaker project contributors
#
-# 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.
+# The version control history for this file may have further details.
#
-# 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.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
#
-# 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.
+
+# Starts crm_mon in background which logs cluster status as
+# html to the specified file.
#
# OCF instance parameters:
# OCF_RESKEY_user
# OCF_RESKEY_pidfile
# OCF_RESKEY_update
# OCF_RESKEY_extra_options
# OCF_RESKEY_htmlfile
#######################################################################
# 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="ClusterMon" version="1.0">
<version>1.0</version>
<longdesc lang="en">
This is a ClusterMon Resource Agent.
It outputs current cluster status to the html.
</longdesc>
<shortdesc lang="en">Runs crm_mon in the background, recording the cluster status to an HTML file</shortdesc>
<parameters>
<parameter name="user" unique="0">
<longdesc lang="en">
The user we want to run crm_mon as
</longdesc>
<shortdesc lang="en">The user we want to run crm_mon as</shortdesc>
<content type="string" default="root" />
</parameter>
<parameter name="update" unique="0">
<longdesc lang="en">
How frequently should we update the cluster status (in milliseconds).
For compatibility with old documentation, values less than 1000 will be treated
as seconds.
</longdesc>
<shortdesc lang="en">Update interval in milliseconds</shortdesc>
<content type="integer" default="15000" />
</parameter>
<parameter name="extra_options" unique="0">
<longdesc lang="en">
Additional options to pass to crm_mon. Eg. -n -r
</longdesc>
<shortdesc lang="en">Extra options</shortdesc>
<content type="string" default="" />
</parameter>
<parameter name="pidfile" unique="1">
<longdesc lang="en">
PID file location to ensure only one instance is running
</longdesc>
<shortdesc lang="en">PID file</shortdesc>
<content type="string" default="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid" />
</parameter>
<parameter name="htmlfile" unique="1" required="0">
<longdesc lang="en">
Location to write HTML output to.
</longdesc>
<shortdesc lang="en">HTML output</shortdesc>
<content type="string" default="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html" />
</parameter>
</parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" depth="0" timeout="20s" interval="10s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
}
#######################################################################
ClusterMon_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
ClusterMon_exit() {
if [ $1 != 0 ]; then
exit $OCF_ERR_GENERIC
else
exit $OCF_SUCCESS
fi
}
ClusterMon_start() {
if [ ! -z $OCF_RESKEY_user ]; then
su - $OCF_RESKEY_user -c "$CMON_CMD"
else
$CMON_CMD
fi
ClusterMon_exit $?
}
ClusterMon_stop() {
if [ -f $OCF_RESKEY_pidfile ]; then
pid=`cat $OCF_RESKEY_pidfile`
if [ ! -z $pid ]; then
kill -s 9 $pid
rm -f $OCF_RESKEY_pidfile
fi
fi
ClusterMon_exit 0
}
ClusterMon_monitor() {
if [ -f $OCF_RESKEY_pidfile ]; then
pid=`cat $OCF_RESKEY_pidfile`
if [ ! -z $pid ]; then
str=$(echo "su - $OCF_RESKEY_user -c \"$CMON_CMD\"" | tr 'crmon, \t' 'xxxxxxxx')
ps -o "args=${str}" -p $pid 2>/dev/null | \
grep -qE "[c]rm_mon.*${OCF_RESKEY_pidfile}"
rc=$?
case $rc in
0) exit $OCF_SUCCESS;;
1) exit $OCF_NOT_RUNNING;;
*) exit $OCF_ERR_GENERIC;;
esac
fi
fi
exit $OCF_NOT_RUNNING
}
CheckOptions() {
while getopts Vi:nrh:cdp: OPTION
do
case $OPTION in
V|n|r|c|d);;
i) ocf_log warn "You should not have specified the -i option, since OCF_RESKEY_update is set already!";;
h) ocf_log warn "You should not have specified the -h option, since OCF_RESKEY_htmlfile is set already!";;
p) ocf_log warn "You should not have specified the -p option, since OCF_RESKEY_pidfile is set already!";;
*) return $OCF_ERR_ARGS;;
esac
done
if [ $? -ne 0 ]; then
return $OCF_ERR_ARGS
fi
# We should have eaten all options at this stage
shift $(($OPTIND -1))
if [ $# -gt 0 ]; then
false
else
true
fi
}
ClusterMon_validate() {
# Existence of the user
if [ ! -z $OCF_RESKEY_user ]; then
getent passwd "$OCF_RESKEY_user" >/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:="15000"}
: ${OCF_RESKEY_pidfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid"}
: ${OCF_RESKEY_htmlfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html"}
if [ ${OCF_RESKEY_update} -ge 1000 ]; then
OCF_RESKEY_update=$(( $OCF_RESKEY_update / 1000 ))
fi
CMON_CMD="${HA_SBIN_DIR}/crm_mon -p $OCF_RESKEY_pidfile -d -i $OCF_RESKEY_update $OCF_RESKEY_extra_options -h $OCF_RESKEY_htmlfile"
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/extra/resources/Dummy b/extra/resources/Dummy
index 75e4cf5b23..950b631e00 100755
--- a/extra/resources/Dummy
+++ b/extra/resources/Dummy
@@ -1,274 +1,278 @@
#!/bin/sh
#
-# Dummy OCF RA. Does nothing but wait a few seconds, can be
-# configured to fail occassionally.
+# ocf:pacemaker:Dummy resource agent
#
-# Copyright 2004-2018 SUSE LINUX AG, Lars Marowsky-Br馥
-# All Rights Reserved.
+# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Br<E9>e
+# Later changes copyright 2008-2018 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# (GPLv2) WITHOUT ANY WARRANTY.
+
+#
+# Does nothing but wait a few seconds, can be configured to fail occassionally
#
#######################################################################
# 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="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" timeout="20s" interval="10s" depth="0"/>
<action name="reload" timeout="20s" />
<action name="migrate_to" timeout="20s" />
<action name="migrate_from" timeout="20s" />
<action name="validate-all" timeout="20s" />
<action name="meta-data" timeout="5s" />
</actions>
</resource-agent>
END
}
#######################################################################
# don't exit on TERM, to test that pacemaker-execd 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."
# Since we're likely going to get KILLed, clean up any monitor
# serialization in progress, so the next probe doesn't return an error.
rm -f "${VERIFY_SERIALIZED_FILE}"
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() {
dummy_monitor
DS_RETVAL=$?
if [ $DS_RETVAL -eq $OCF_SUCCESS ]; then
if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then
DS_RETVAL=$OCF_ERR_GENERIC
fi
return $DS_RETVAL
fi
touch "${OCF_RESKEY_state}"
DS_RETVAL=$?
if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then
DS_RETVAL=$OCF_ERR_GENERIC
fi
return $DS_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" = "" ] && [ -f "${VERIFY_SERIALIZED_FILE}" ]; then
# two monitor ops have occurred at the same time.
# This verifies a condition in pacemaker-execd regression tests.
ocf_log err "$VERIFY_SERIALIZED_FILE exists already"
ocf_exit_reason "alternate universe collision"
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
diff --git a/extra/resources/HealthCPU b/extra/resources/HealthCPU
index d860a718bb..82ba597e43 100755
--- a/extra/resources/HealthCPU
+++ b/extra/resources/HealthCPU
@@ -1,197 +1,200 @@
#!/bin/sh
#
-# HealthCPU OCF RA
-# Measures CPUs idling and writes #health-cpu status into the CIB
+# ocf:pacemaker:HealthCPU resource agent
#
# Copyright 2004-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# (GPLv2) WITHOUT ANY WARRANTY.
#
+
+#
+# Measures CPUs idling and writes #health-cpu status into the CIB
+#
################################
#
# TODO: Enter default values
# Error handling in getting uptime
#
##################################
#######################################################################
# 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="HealthCPU" version="0.1">
<version>1.0</version>
<longdesc lang="en">
Systhem health agent that measures the CPU idling and updates the #health-cpu attribute.
</longdesc>
<shortdesc lang="en">System health CPU usage</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%%/}/health-cpu-${OCF_RESOURCE_INSTANCE}.state" />
</parameter>
<parameter name="yellow_limit" unique="1">
<longdesc lang="en">
Lower (!) limit of idle percentage to switch the health attribute to yellow. I.e.
the #health-cpu will go yellow if the %idle of the CPU falls below 50%.
</longdesc>
<shortdesc lang="en">Lower limit for yellow health attribute</shortdesc>
<content type="string" default="50"/>
</parameter>
<parameter name="red_limit" unique="1">
<longdesc lang="en">
Lower (!) limit of idle percentage to switch the health attribute to red. I.e.
the #health-cpu will go red if the %idle of the CPU falls below 10%.
</longdesc>
<shortdesc lang="en">Lower limit for red health attribute</shortdesc>
<content type="string" default="10"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="10s" />
<action name="stop" timeout="10s" />
<action name="monitor" timeout="10s" interval="10s" start-delay="0s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="10s" />
</actions>
</resource-agent>
END
}
#######################################################################
dummy_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
dummy_start() {
dummy_monitor
if [ $? = $OCF_SUCCESS ]; then
return $OCF_SUCCESS
fi
touch ${OCF_RESKEY_state}
}
dummy_stop() {
dummy_monitor
if [ $? = $OCF_SUCCESS ]; then
rm ${OCF_RESKEY_state}
fi
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 [ -f ${OCF_RESKEY_state} ]; then
IDLE=`top -b -n2 | grep Cpu | tail -1 | awk -F",|.[0-9][ %]id" '{ print $4 }'`
# echo "System idle: " $IDLE
# echo "$OCF_RESKEY_red_limit"
# echo $OCF_RESKEY_yellow_limit
if [ $IDLE -lt ${OCF_RESKEY_red_limit} ] ; then
# echo "System state RED!"
attrd_updater -n "#health-cpu" -U "red" -d "30s"
return $OCF_SUCCESS
fi
if [ $IDLE -lt ${OCF_RESKEY_yellow_limit} ] ; then
# echo "System state yellow."
attrd_updater -n "#health-cpu" -U "yellow" -d "30s"
else
# echo "System state green."
attrd_updater -n "#health-cpu" -U "green" -d "30s"
fi
return $OCF_SUCCESS
fi
if false ; then
return $OCF_ERR_GENERIC
fi
return $OCF_NOT_RUNNING
}
dummy_validate() {
# Is the state directory writable?
state_dir=`dirname "$OCF_RESKEY_state"`
touch "$state_dir/$$"
if [ $? != 0 ]; then
return $OCF_ERR_ARGS
fi
rm "$state_dir/$$"
return $OCF_SUCCESS
}
: ${OCF_RESKEY_CRM_meta_interval=0}
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
if [ "x$OCF_RESKEY_state" = "x" ]; then
if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
state="${HA_VARRUN%%/}/Dummy-${OCF_RESOURCE_INSTANCE}.state"
# Strip off the trailing clone marker
OCF_RESKEY_state=`echo $state | sed s/:[0-9][0-9]*\.state/.state/`
else
OCF_RESKEY_state="${HA_VARRUN%%/}/Dummy-${OCF_RESOURCE_INSTANCE}.state"
fi
fi
if [ "x${OCF_RESKEY_red_limit}" = "x" ] ; then
OCF_RESKEY_red_limit=10
fi
if [ "x${OCF_RESKEY_yellow_limit}" = "x" ] ; then
OCF_RESKEY_yellow_limit=50
fi
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) dummy_start;;
stop) dummy_stop;;
monitor) dummy_monitor;;
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
diff --git a/extra/resources/HealthIOWait b/extra/resources/HealthIOWait
index e8630cbbca..6fadec2bce 100755
--- a/extra/resources/HealthIOWait
+++ b/extra/resources/HealthIOWait
@@ -1,173 +1,176 @@
#!/bin/sh
#
-# IOWait RA
-# Measures CPU iowait % via top and writes #health-iowait status into the CIB
+# ocf:pacemaker:HealthIOWait resource agent
#
# Copyright 2004-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# (GPLv2) WITHOUT ANY WARRANTY.
#
+
+#
+# Measures CPU iowait % via top and writes #health-iowait status into the CIB
+#
#######################################################################
# 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="HealthIOWait" version="1.0">
<version>1.0</version>
<longdesc lang="en">
Systhem health agent that measures the CPU iowait via top and updates the #health-iowait attribute.
</longdesc>
<shortdesc lang="en">System health based on CPU iowait measurement</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%%/}/health-iowait-${OCF_RESOURCE_INSTANCE}.state" />
</parameter>
<parameter name="yellow_limit" unique="0">
<longdesc lang="en">
Upper limit of iowait percentage to switch the health attribute to yellow. I.e.
the #health-iowait will go yellow if the %iowait of the CPU gets higher than 10%.
</longdesc>
<shortdesc lang="en">Upper limit for yellow health attribute</shortdesc>
<content type="string" default="10"/>
</parameter>
<parameter name="red_limit" unique="0">
<longdesc lang="en">
Upper limit of iowait percentage to switch the health attribute to red. I.e.
the #health-iowait will go red if the %iowait of the CPU get higher than 15%.
</longdesc>
<shortdesc lang="en">Upper limit for red health attribute</shortdesc>
<content type="string" default="15"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="10s" />
<action name="stop" timeout="10s" />
<action name="monitor" timeout="10s" interval="10s" start-delay="0s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="10s" />
</actions>
</resource-agent>
END
}
#######################################################################
agent_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
agent_start() {
agent_monitor
if [ $? = $OCF_SUCCESS ]; then
return $OCF_SUCCESS
fi
touch "${OCF_RESKEY_state}"
}
agent_stop() {
agent_monitor
if [ $? = $OCF_SUCCESS ]; then
rm ${OCF_RESKEY_state}
fi
return $OCF_SUCCESS
}
agent_monitor() {
# Monitor _MUST!_ differentiate correctly between running
# (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING).
# That is THREE states, not just yes/no.
if [ -f ${OCF_RESKEY_state} ]; then
WAIT=`top -b -n2 | grep Cpu | tail -1 | awk -F",|.[0-9][ %]wa" '{ print $5 }'`
# echo "System iowait: " $WAIT
# echo $OCF_RESKEY_yellow_limit
if [ $WAIT -gt ${OCF_RESKEY_red_limit} ] ; then
# echo "System state RED!"
attrd_updater -n "#health-iowait" -U "red" -d "5s"
return $OCF_SUCCESS
fi
if [ $WAIT -gt ${OCF_RESKEY_yellow_limit} ] ; then
# echo "System state yellow."
attrd_updater -n "#health-iowait" -U "yellow" -d "5s"
else
# echo "System state green."
attrd_updater -n "#health-iowait" -U "green" -d "5s"
fi
return $OCF_SUCCESS
fi
return $OCF_NOT_RUNNING
}
agent_validate() {
# Is the state directory writable?
state_dir=`dirname "$OCF_RESKEY_state"`
if [ -d "$state_dir" ] && [ -w "$state_dir" ] && [ -x "$state_dir" ]; then
return $OCF_ERR_ARGS
fi
return $OCF_SUCCESS
}
: ${OCF_RESKEY_CRM_meta_interval=0}
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
if [ "x$OCF_RESKEY_state" = "x" ]; then
if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
state="${HA_VARRUN%%/}/HealthIoWait-${OCF_RESOURCE_INSTANCE}.state"
#Strip off the trailing clone marker
OCF_RESKEY_state=`echo $state | sed s/:[0-9][0-9]*\.state/.state/`
else
OCF_RESKEY_state="${HA_VARRUN%%/}/HealthIoWait-${OCF_RESOURCE_INSTANCE}.state"
fi
fi
if [ "x${OCF_RESKEY_red_limit}" = "x" ] ; then
OCF_RESKEY_red_limit=15
fi
if [ "x${OCF_RESKEY_yellow_limit}" = "x" ] ; then
OCF_RESKEY_yellow_limit=10
fi
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) agent_start;;
stop) agent_stop;;
monitor) agent_monitor;;
validate-all) agent_validate;;
usage|help) agent_usage
exit $OCF_SUCCESS
;;
*) agent_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
rc=$?
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
exit $rc
diff --git a/extra/resources/HealthSMART.in b/extra/resources/HealthSMART.in
index f0c9b48860..344cb1418a 100755
--- a/extra/resources/HealthSMART.in
+++ b/extra/resources/HealthSMART.in
@@ -1,328 +1,315 @@
#!@BASH_PATH@
#
-#
-# HealthSMART OCF RA. Checks the S.M.A.R.T. status of all given
-# drives and writes the #health-smart status into the CIB
+# ocf:pacemaker:HealthSMART resource agent
#
# Copyright 2009-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
-# 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.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
#
-# 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.
+# Checks the S.M.A.R.T. status of all given drives and writes the #health-smart
+# status into the CIB
#
#######################################################################
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
. ${OCF_FUNCTIONS}
: ${__OCF_ACTION=$1}
#
SMARTCTL=/usr/sbin/smartctl
ATTRDUP=/usr/sbin/attrd_updater
#######################################################################
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="HealthSMART" version="0.1">
<version>1.0</version>
<longdesc lang="en">
Systhem health agent that checks the S.M.A.R.T. status of the given drives and
updates the #health-smart attribute.
</longdesc>
<shortdesc lang="en">SMART health status</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%%/}/HealthSMART-${OCF_RESOURCE_INSTANCE}.state" />
</parameter>
<parameter name="drives" unique="0">
<longdesc lang="en">
The drive(s) to check as a SPACE separated list. Enter the full path to the device, e.g. "/dev/sda".
</longdesc>
<shortdesc lang="en">Drives to check</shortdesc>
<content type="string" default="/dev/sda" />
</parameter>
<parameter name="devices" unique="0">
<longdesc lang="en">
The device type(s) to assume for the drive(s) being tested as a SPACE separated list.
</longdesc>
<shortdesc lang="en">Device types</shortdesc>
<content type="string" />
</parameter>
<parameter name="temp_lower_limit" unique="0">
<longdesc lang="en">
Lower limit of the temperature in deg C of the drive(s). Below this limit the status will be red.
</longdesc>
<shortdesc lang="en">Lower limit for the red smart attribute</shortdesc>
<content type="string" default="0"/>
</parameter>
<parameter name="temp_upper_limit" unique="0">
<longdesc lang="en">
Upper limit of the temperature if deg C of the drives(s). If the drive reports
a temperature higher than this value the status of #health-smart will be red.
</longdesc>
<shortdesc lang="en">Upper limit for red smart attribute</shortdesc>
<content type="string" default="60"/>
</parameter>
<parameter name="temp_warning" unique="0">
<longdesc lang="en">
Number of deg C below/above the upper/lower temp limits at which point the status of #health-smart will change to yellow.
</longdesc>
<shortdesc lang="en">Deg C below/above the upper limits for yellow smart attribute</shortdesc>
<content type="string" default="5"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="10s" />
<action name="stop" timeout="10s" />
<action name="monitor" timeout="10s" interval="10s" start-delay="0s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="10s" />
</actions>
</resource-agent>
END
}
#######################################################################
check_temperature() {
if [ $1 -lt ${lower_red_limit} ] ; then
ocf_log info "Drive ${DRIVE} ${DEVICE} too cold: ${1} C"
$ATTRDUP -n "#health-smart" -U "red" -d "5s"
return 1
fi
if [ $1 -gt ${upper_red_limit} ] ; then
ocf_log info "Drive ${DRIVE} ${DEVICE} too hot: ${1} C"
$ATTRDUP -n "#health-smart" -U "red" -d "5s"
return 1
fi
if [ $1 -lt ${lower_yellow_limit} ] ; then
ocf_log info "Drive ${DRIVE} ${DEVICE} quite cold: ${1} C"
$ATTRDUP -n "#health-smart" -U "yellow" -d "5s"
return 1
fi
if [ $1 -gt ${upper_yellow_limit} ] ; then
ocf_log info "Drive ${DRIVE} ${DEVICE} quite hot: ${1} C"
$ATTRDUP -n "#health-smart" -U "yellow" -d "5s"
return 1
fi
}
init_smart() {
#Set temperature defaults
if [ -z ${OCF_RESKEY_temp_warning} ]; then
yellow_threshold=5
else
yellow_threshold=${OCF_RESKEY_temp_warning}
fi
if [ -z ${OCF_RESKEY_temp_lower_limit} ] ; then
lower_red_limit=0
else
lower_red_limit=${OCF_RESKEY_temp_lower_limit}
fi
lower_yellow_limit=$((${lower_red_limit}+${yellow_threshold}))
if [ -z ${OCF_RESKEY_temp_upper_limit} ] ; then
upper_red_limit=60
else
upper_red_limit=${OCF_RESKEY_temp_upper_limit}
fi
upper_yellow_limit=$((${upper_red_limit}-${yellow_threshold}))
#Set disk defaults
if [ -z "${OCF_RESKEY_drives}" ] ; then
DRIVES="/dev/sda"
else
DRIVES=${OCF_RESKEY_drives}
fi
#Test for presence of smartctl
if [ ! -x $SMARTCTL ] ; then
ocf_log err "${SMARTCTL} not installed."
exit $OCF_ERR_INSTALLED
fi
for DRIVE in $DRIVES; do
if [ "${OCF_RESKEY_devices}" ]; then
for DEVICE in ${OCF_RESKEY_devices}; do
$SMARTCTL -d $DEVICE -i ${DRIVE} | grep -q "SMART support is: Enabled"
if [ $? -ne "0" ] ; then
ocf_log err "S.M.A.R.T. not enabled for drive "${DRIVE}
exit $OCF_ERR_INSTALLED
fi
done
else
$SMARTCTL -i ${DRIVE} | grep -q "SMART support is: Enabled"
if [ $? -ne "0" ] ; then
ocf_log err "S.M.A.R.T. not enabled for drive "${DRIVE}
exit $OCF_ERR_INSTALLED
fi
fi
done
}
HealthSMART_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
HealthSMART_start() {
HealthSMART_monitor
if [ $? = $OCF_SUCCESS ]; then
return $OCF_SUCCESS
fi
touch ${OCF_RESKEY_state}
}
HealthSMART_stop() {
HealthSMART_monitor
if [ $? = $OCF_SUCCESS ]; then
rm ${OCF_RESKEY_state}
fi
return $OCF_SUCCESS
}
HealthSMART_monitor() {
init_smart
# Monitor _MUST!_ differentiate correctly between running
# (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING).
# That is THREE states, not just yes/no.
if [ -f ${OCF_RESKEY_state} ]; then
# Check overall S.M.A.R.T. status
for DRIVE in $DRIVES; do
if [ "${OCF_RESKEY_devices}" ]; then
for DEVICE in ${OCF_RESKEY_devices}; do
$SMARTCTL -d $DEVICE -H ${DRIVE} | grep -q "SMART overall-health self-assessment test result: PASSED"
if [ $? -ne "0" ]; then
$ATTRDUP -n "#health-smart" -U "red" -d "5s"
return $OCF_SUCCESS
fi
done
else
$SMARTCTL -H ${DRIVE} | grep -q "SMART overall-health self-assessment test result: PASSED"
if [ $? -ne "0" ]; then
$ATTRDUP -n "#health-smart" -U "red" -d "5s"
return $OCF_SUCCESS
fi
fi
# Check drive temperature(s)
if [ "${OCF_RESKEY_devices}" ]; then
for DEVICE in ${OCF_RESKEY_devices}; do
check_temperature "$("$SMARTCTL" -d "$DEVICE" -A "${DRIVE}" | awk '/^194/ { print $10 }')"
if [ $? -ne 0 ]; then
return $OCF_SUCCESS
fi
done
else
check_temperature "$("$SMARTCTL" -A "${DRIVE}" | awk '/^194/ { print $10 }')"
if [ $? -ne 0 ]; then
return $OCF_SUCCESS
fi
fi
done
$ATTRDUP -n "#health-smart" -U "green" -d "5s"
return $OCF_SUCCESS
fi
return $OCF_NOT_RUNNING
}
HealthSMART_validate() {
init_smart
# Is the state directory writable?
state_dir=`dirname "$OCF_RESKEY_state"`
touch "$state_dir/$$"
if [ $? != 0 ]; then
return $OCF_ERR_ARGS
fi
rm "$state_dir/$$"
return $OCF_SUCCESS
}
: ${OCF_RESKEY_CRM_meta_interval=0}
: ${OCF_RESKEY_CRM_meta_globally_unique:="true"}
if [ "x$OCF_RESKEY_state" = "x" ]; then
if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
state="${HA_VARRUN%%/}/HealthSMART-${OCF_RESOURCE_INSTANCE}.state"
# Strip off the trailing clone marker
OCF_RESKEY_state=`echo $state | sed s/:[0-9][0-9]*\.state/.state/`
else
OCF_RESKEY_state="${HA_VARRUN%%/}/HealthSMART-${OCF_RESOURCE_INSTANCE}.state"
fi
fi
case $__OCF_ACTION in
start) HealthSMART_start;;
stop) HealthSMART_stop;;
monitor) HealthSMART_monitor;;
validate-all) HealthSMART_validate;;
meta-data)
meta_data
exit $OCF_SUCCESS
;;
usage|help)
HealthSMART_usage
exit $OCF_SUCCESS
;;
*) HealthSMART_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
rc=$?
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
exit $rc
diff --git a/extra/resources/Stateful b/extra/resources/Stateful
index e6e5f24750..2450a801f5 100755
--- a/extra/resources/Stateful
+++ b/extra/resources/Stateful
@@ -1,233 +1,238 @@
#!/bin/sh
#
-# Example of a stateful OCF Resource Agent
+# ocf:pacemaker:Stateful resource agent
+#
# Copyright 2006-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
+#
+# Example of a stateful OCF Resource Agent
+#
+
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
. ${OCF_FUNCTIONS}
: ${__OCF_ACTION=$1}
CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot"
#######################################################################
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="Stateful" version="1.1">
<version>1.0</version>
<longdesc lang="en">
This is an example resource agent that implements two states
</longdesc>
<shortdesc lang="en">Example stateful 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%%/}/Stateful-${OCF_RESOURCE_INSTANCE}.state" />
</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>
<parameter name="notify_delay" unique="0">
<longdesc lang="en">
The notify action will sleep for this many seconds before returning,
to simulate a long-running notify.
</longdesc>
<shortdesc lang="en">Notify delay in seconds</shortdesc>
<content type="string" default="" />
</parameter>
</parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" depth="0" timeout="20s" interval="10s" role="Master"/>
<action name="monitor" depth="0" timeout="20s" interval="10s" role="Slave"/>
<action name="notify" timeout="5s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
exit $OCF_SUCCESS
}
#######################################################################
stateful_usage() {
cat <<END
usage: $0 {start|stop|promote|demote|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
exit $1
}
stateful_update() {
echo $1 > ${OCF_RESKEY_state}
}
stateful_check_state() {
target=$1
if [ -f ${OCF_RESKEY_state} ]; then
state=`cat ${OCF_RESKEY_state}`
if [ "x$target" = "x$state" ]; then
return 0
fi
else
if [ "x$target" = "x" ]; then
return 0
fi
fi
return 1
}
dump_env() {
if [ "${OCF_RESKEY_envfile}" != "" ]; then
echo "### ${__OCF_ACTION} @ $(date) ###
$(env | sort)
###" >> "${OCF_RESKEY_envfile}"
fi
}
stateful_start() {
stateful_check_state master
if [ $? = 0 ]; then
# CRM Error - Should never happen
return $OCF_RUNNING_MASTER
fi
stateful_update slave
$CRM_MASTER -v ${slave_score}
return 0
}
stateful_demote() {
stateful_check_state
if [ $? = 0 ]; then
# CRM Error - Should never happen
return $OCF_NOT_RUNNING
fi
stateful_update slave
$CRM_MASTER -v ${slave_score}
return 0
}
stateful_promote() {
stateful_check_state
if [ $? = 0 ]; then
return $OCF_NOT_RUNNING
fi
stateful_update master
$CRM_MASTER -v ${master_score}
return 0
}
stateful_stop() {
$CRM_MASTER -D
stateful_check_state master
if [ $? = 0 ]; then
# CRM Error - Should never happen
return $OCF_RUNNING_MASTER
fi
if [ -f ${OCF_RESKEY_state} ]; then
rm ${OCF_RESKEY_state}
fi
return 0
}
stateful_monitor() {
stateful_check_state "master"
if [ $? = 0 ]; then
if [ $OCF_RESKEY_CRM_meta_interval = 0 ]; then
# Restore the master setting during probes
$CRM_MASTER -v ${master_score}
fi
return $OCF_RUNNING_MASTER
fi
stateful_check_state "slave"
if [ $? = 0 ]; then
if [ $OCF_RESKEY_CRM_meta_interval = 0 ]; then
# Restore the master setting during probes
$CRM_MASTER -v ${slave_score}
fi
return $OCF_SUCCESS
fi
if [ -f ${OCF_RESKEY_state} ]; then
echo "File '${OCF_RESKEY_state}' exists but contains unexpected contents"
cat ${OCF_RESKEY_state}
return $OCF_ERR_GENERIC
fi
return 7
}
stateful_notify() {
if [ "${OCF_RESKEY_notify_delay}" != "0" ]; then
sleep "${OCF_RESKEY_notify_delay}"
fi
return $OCF_SUCCESS
}
stateful_validate() {
exit $OCF_SUCCESS
}
: ${slave_score=5}
: ${master_score=10}
: ${OCF_RESKEY_CRM_meta_interval=0}
: ${OCF_RESKEY_notify_delay=0}
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
if [ "x$OCF_RESKEY_state" = "x" ]; then
if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
state="${HA_VARRUN%%/}/Stateful-${OCF_RESOURCE_INSTANCE}.state"
# Strip off the trailing clone marker
OCF_RESKEY_state=`echo $state | sed s/:[0-9][0-9]*\.state/.state/`
else
OCF_RESKEY_state="${HA_VARRUN%%/}/Stateful-${OCF_RESOURCE_INSTANCE}.state"
fi
fi
dump_env
case $__OCF_ACTION in
meta-data) meta_data;;
start) stateful_start;;
promote) stateful_promote;;
demote) stateful_demote;;
notify) stateful_notify ;;
stop) stateful_stop;;
monitor) stateful_monitor;;
validate-all) stateful_validate;;
usage|help) stateful_usage $OCF_SUCCESS;;
*) stateful_usage $OCF_ERR_UNIMPLEMENTED;;
esac
exit $?
diff --git a/extra/resources/SysInfo.in b/extra/resources/SysInfo.in
index 34eb848581..40400719c7 100755
--- a/extra/resources/SysInfo.in
+++ b/extra/resources/SysInfo.in
@@ -1,382 +1,370 @@
#!@BASH_PATH@
#
+# ocf:pacemaker:SysInfo resource agent
#
-# SysInfo OCF Resource Agent
-# It records (in the CIB) various attributes of a node
+# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Br<E9>e
+# Later changes copyright 2008-2018 the Pacemaker project contributors
#
-# Copyright 2004-2018 SUSE LINUX AG, Lars Marowsky-Br馥
-# All Rights Reserved.
+# The version control history for this file may have further details.
#
-# 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 source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
#
-# 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.
+# This agent records (in the CIB) various attributes of a node
#
#######################################################################
# 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="SysInfo" version="1.0">
<version>1.0</version>
<longdesc lang="en">
This is a SysInfo Resource Agent.
It records (in the CIB) various attributes of a node
Sample Linux output:
arch: i686
os: Linux-2.4.26-gentoo-r14
free_swap: 1999
cpu_info: Intel(R) Celeron(R) CPU 2.40GHz
cpu_speed: 4771.02
cpu_cores: 1
cpu_load: 0.00
ram_total: 513
ram_free: 117
root_free: 2.4
#health_disk: red
Sample Darwin output:
arch: i386
os: Darwin-8.6.2
cpu_info: Intel Core Duo
cpu_speed: 2.16
cpu_cores: 2
cpu_load: 0.18
ram_total: 2016
ram_free: 787
root_free: 13
#health_disk: green
Units:
free_swap: MB
ram_*: MB
cpu_speed (Linux): bogomips
cpu_speed (Darwin): GHz
*_free: GB (or user-defined: disk_unit)
</longdesc>
<shortdesc lang="en">SysInfo resource agent</shortdesc>
<parameters>
<parameter name="pidfile" unique="1">
<longdesc lang="en">PID file</longdesc>
<shortdesc lang="en">PID file</shortdesc>
<content type="string" default="$OCF_RESKEY_pidfile" />
</parameter>
<parameter name="delay" unique="0">
<longdesc lang="en">Interval to allow values to stabilize</longdesc>
<shortdesc lang="en">Dampening Delay</shortdesc>
<content type="string" default="0s" />
</parameter>
<parameter name="disks" unique="0">
<longdesc lang="en">
Filesystems or Paths to be queried for free disk space as a SPACE
separated list - e.g "/dev/sda1 /tmp".
Results will be written to an attribute with leading slashes
removed, and other slashes replaced with underscore, and the word
'free' appended - e.g for /dev/sda1 it would be 'dev_sda1_free'.
Note: The root filesystem '/' is always queried to an attribute
named 'root_free'
</longdesc>
<shortdesc lang="en">List of Filesytems/Paths to query for free disk space</shortdesc>
<content type="string" />
</parameter>
<parameter name="disk_unit" unique="0">
<longdesc lang="en">
Unit to report disk free space in.
Can be one of: B, K, M, G, T, P (case-insensitive)
</longdesc>
<shortdesc lang="en">Unit to report disk free space in</shortdesc>
<content type="string" default="G"/>
</parameter>
<parameter name="min_disk_free" unique="0">
<longdesc lang="en">
The amount of free space required in monitored disks. If any
of the monitored disks has less than this amount of free space,
, with the node attribute "#health_disk" changing to "red",
all resources will move away from the node. Set the node-health-strategy
property appropriately for this to take effect.
If the unit is not specified, it defaults to disk_unit.
</longdesc>
<shortdesc lang="en">minimum disk free space required</shortdesc>
<content type="string" default=""/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" timeout="20s" interval="60s"/>
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
}
#######################################################################
UpdateStat() {
name=$1; shift
value="$*"
printf "%s:\t%s\n" "$name" "$value"
if [ "$__OCF_ACTION" = "start" ] ; then
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n $name -B "$value"
else
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n $name -v "$value"
fi
}
SysInfoStats() {
UpdateStat arch "`uname -m`"
UpdateStat os "`uname -s`-`uname -r`"
case `uname -s` in
"Darwin")
mem=`top -l 1 | grep Mem: | awk '{print $10}'`
mem_used=`top -l 1 | grep Mem: | awk '{print $8}'`
mem=`SysInfo_mem_units $mem`
mem_used=`SysInfo_mem_units $mem_used`
mem_total=`expr $mem_used + $mem`
cpu_type=`system_profiler SPHardwareDataType | awk -F': ' '/^CPU Type/ {print $2; exit}'`
cpu_speed=`system_profiler SPHardwareDataType | awk -F': ' '/^CPU Speed/ {print $2; exit}'`
cpu_cores=`system_profiler SPHardwareDataType | awk -F': ' '/^Number Of/ {print $2; exit}'`
cpu_load=`uptime | awk '{ print $10 }'`
;;
"FreeBSD")
cpu_type=`sysctl -in hw.model`
cpu_speed=`sysctl -in dev.cpu.0.freq`
cpu_cores=`sysctl -in hw.ncpu`
cpu_load=`sysctl -in vm.loadavg | awk '{ print $4 }'`
free_pages=`sysctl -in vm.stats.vm.v_free_count`
page_count=`sysctl -in vm.stats.vm.v_page_count`
page_size=`sysctl -in vm.stats.vm.v_page_size`
mem=`expr $free_pages \* $page_size / 1024 / 1024`M
mem_total=`expr $page_count \* $page_size / 1024 / 1024`M
;;
"Linux")
if [ -f /proc/cpuinfo ]; then
cpu_type=`awk -F': ' '/model name/ {print $2; exit}' /proc/cpuinfo`
cpu_speed=`awk -F': ' '/bogomips/ {print $2; exit}' /proc/cpuinfo`
cpu_cores=`grep "^processor" /proc/cpuinfo | wc -l`
fi
cpu_load=`uptime | awk '{ print $10 }'`
if [ -f /proc/meminfo ]; then
# meminfo results are in kB
mem=`grep "SwapFree" /proc/meminfo | awk '{print $2"k"}'`
if [ ! -z $mem ]; then
UpdateStat free_swap "$(SysInfo_mem_units "$mem")"
fi
mem=`grep "Inactive" /proc/meminfo | awk '{print $2"k"}'`
mem_total=`grep "MemTotal" /proc/meminfo | awk '{print $2"k"}'`
else
mem=`top -n 1 | grep Mem: | awk '{print $7}'`
fi
;;
*)
esac
if [ x != x"$cpu_type" ]; then
UpdateStat cpu_info "$cpu_type"
fi
if [ x != x"$cpu_speed" ]; then
UpdateStat cpu_speed "$cpu_speed"
fi
if [ x != x"$cpu_cores" ]; then
UpdateStat cpu_cores "$cpu_cores"
fi
if [ x != x"$cpu_load" ]; then
UpdateStat cpu_load "$cpu_load"
fi
if [ ! -z "$mem" ]; then
# Massage the memory values
UpdateStat ram_total "$(SysInfo_mem_units "$mem_total")"
UpdateStat ram_free "$(SysInfo_mem_units "$mem")"
fi
# Portability notes:
# o tail: explicit "-n" not available in Solaris; instead simplify
# 'tail -n <c>' to the equivalent 'tail -<c>'.
for disk in "/" ${OCF_RESKEY_disks}; do
unset disk_free disk_label
disk_free=`df -h ${disk} | tail -1 | awk '{print $4}'`
if [ x != x"$disk_free" ]; then
disk_label=`echo $disk | sed -e 's#^/$#root#;s#^/*##;s#/#_#g'`
disk_free=`SysInfo_hdd_units $disk_free`
UpdateStat ${disk_label}_free $disk_free
if [ -n "$MIN_FREE" ]; then
if [ $disk_free -le $MIN_FREE ]; then
UpdateStat "#health_disk" "red"
else
UpdateStat "#health_disk" "green"
fi
fi
fi
done
}
SysInfo_megabytes() {
# Size in megabytes
echo $1 | awk '{ n = $0;
sub(/[0-9]+(.[0-9]+)?/, "");
split(n, a, $0);
n=a[1];
if ($0 == "G" || $0 == "") { n *= 1024 };
if (/^kB?/) { n /= 1024 };
printf "%d\n", n }' # Intentionally round to an integer
}
SysInfo_mem_units() {
mem=$1
if [ -z $1 ]; then
return
fi
mem=$(SysInfo_megabytes "$1")
# Round to the next multiple of 50
r=$(($mem % 50))
if [ $r != 0 ]; then
mem=$(($mem + 50 - $r))
fi
echo $mem
}
SysInfo_hdd_units() {
# Defauts to size in gigabytes
case $OCF_RESKEY_disk_unit in
[Pp]) echo $(($(SysInfo_megabytes "$1") / 1024 / 1024 / 1024));;
[Tt]) echo $(($(SysInfo_megabytes "$1") / 1024 / 1024));;
[Gg]) echo $(($(SysInfo_megabytes "$1") / 1024));;
[Mm]) echo "$(SysInfo_megabytes "$1")" ;;
[Kk]) echo $(($(SysInfo_megabytes "$1") * 1024));;
[Bb]) echo $(($(SysInfo_megabytes "$1") * 1024 * 1024));;
*)
ocf_log err "Invalid value for disk_unit: $OCF_RESKEY_disk_unit"
echo $(($(SysInfo_megabytes "$1") / 1024));;
esac
}
SysInfo_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
SysInfo_start() {
echo $OCF_RESKEY_clone > $OCF_RESKEY_pidfile
SysInfoStats
exit $OCF_SUCCESS
}
SysInfo_stop() {
rm $OCF_RESKEY_pidfile
exit $OCF_SUCCESS
}
SysInfo_monitor() {
if [ -f $OCF_RESKEY_pidfile ]; then
clone=`cat $OCF_RESKEY_pidfile`
fi
if [ x$clone = x ]; then
rm $OCF_RESKEY_pidfile
exit $OCF_NOT_RUNNING
elif [ $clone = $OCF_RESKEY_clone ]; then
SysInfoStats
exit $OCF_SUCCESS
elif ocf_is_true "$OCF_RESKEY_CRM_meta_globally_unique"; then
SysInfoStats
exit $OCF_SUCCESS
fi
exit $OCF_NOT_RUNNING
}
SysInfo_validate() {
return $OCF_SUCCESS
}
if [ $# -ne 1 ]; then
SysInfo_usage
exit $OCF_ERR_ARGS
fi
: ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/SysInfo-${OCF_RESOURCE_INSTANCE}"}
: ${OCF_RESKEY_disk_unit:="G"}
: ${OCF_RESKEY_clone:="0"}
if [ x != x${OCF_RESKEY_delay} ]; then
OCF_RESKEY_delay="-d ${OCF_RESKEY_delay}"
else
OCF_RESKEY_delay="-d 0"
fi
MIN_FREE=""
if [ -n "$OCF_RESKEY_min_disk_free" ]; then
ocf_is_decimal "$OCF_RESKEY_min_disk_free" &&
OCF_RESKEY_min_disk_free="$OCF_RESKEY_min_disk_free$OCF_RESKEY_disk_unit"
MIN_FREE=`SysInfo_hdd_units $OCF_RESKEY_min_disk_free`
fi
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) SysInfo_start
;;
stop) SysInfo_stop
;;
monitor) SysInfo_monitor
;;
validate-all) SysInfo_validate
;;
usage|help) SysInfo_usage
exit $OCF_SUCCESS
;;
*) SysInfo_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
diff --git a/extra/resources/SystemHealth b/extra/resources/SystemHealth
index a7785c2267..499f959369 100755
--- a/extra/resources/SystemHealth
+++ b/extra/resources/SystemHealth
@@ -1,253 +1,237 @@
#!/bin/sh
#
-# SystemHealth OCF RA.
+# ocf:pacemaker:SystemHealth resource agent
#
# Copyright 2009-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
-# 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.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
#
#######################################################################
# 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="SystemHealth" version="0.1">
<version>1.0</version>
<longdesc lang="en">
This is a SystemHealth Resource Agent. It is used to monitor
the health of a system via IPMI.
</longdesc>
<shortdesc lang="en">SystemHealth resource agent</shortdesc>
<parameters>
</parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" timeout="20s" />
<action name="reload" timeout="20s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="20s" />
</actions>
</resource-agent>
END
}
#######################################################################
SystemHealth_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
SystemHealth_check_tools() {
which servicelog_notify > /dev/null 2>&1
RC=$?
if [ $RC != 0 ]; then
ocf_log err "servicelog_notify not found!"
return $OCF_ERR_INSTALLED
fi
which ipmiservicelogd > /dev/null 2>&1
RC=$?
if [ $RC != 0 ]; then
ocf_log err "ipmiservicelogd not found!"
return $OCF_ERR_INSTALLED
fi
test -x $OCF_RESKEY_program
RC=$?
if [ $RC != 0 ]; then
ocf_log err "$OCF_RESKEY_program not found!"
return $OCF_ERR_INSTALLED
fi
}
SystemHealth_start() {
SystemHealth_monitor
RC=$?
if [ $RC = $OCF_ERR_GENERIC ]; then
return $OCF_ERR_GENERIC
elif [ $RC = $OCF_SUCCESS ]; then
ocf_log warn "starting an already started SystemHealth"
return $OCF_SUCCESS
fi
service ipmi start > /dev/null 2>&1
RC=$?
if [ $RC != 0 ]; then
ocf_log err "Could not start service IPMI!"
return $OCF_ERR_GENERIC
fi
ipmiservicelogd smi 0 > /dev/null 2>&1 &
RC=$?
if [ $RC != 0 ]; then
ocf_log err "Could not start ipmiservicelogd!"
return $OCF_ERR_GENERIC
fi
servicelog_notify --add --type=EVENT --command="$OCF_RESKEY_program" --method=num_arg --match='type=4' > /dev/null 2>&1
RC=$?
if [ $RC != 0 ]; then
ocf_log err "servicelog_notify register handler failed!"
return $OCF_ERR_GENERIC
fi
return $OCF_SUCCESS
}
SystemHealth_stop() {
SystemHealth_monitor
RC=$?
if [ $RC = $OCF_ERR_GENERIC ]; then
return $OCF_ERR_GENERIC
elif [ $RC = $OCF_SUCCESS ]; then
killall ipmiservicelogd
RC1=$?
if [ $RC1 != 0 ]; then
ocf_log err "Could not stop ipmiservicelogd!"
fi
servicelog_notify --remove --command="$OCF_RESKEY_program" > /dev/null 2>&1
RC2=$?
if [ $RC2 != 0 ]; then
ocf_log err "servicelog_notify remove handler failed!"
fi
if [ $RC1 -eq 0 ] && [ $RC2 -eq 0 ]; then
return $OCF_SUCCESS
else
return $OCF_ERR_GENERIC
fi
elif [ $RC = $OCF_NOT_RUNNING ]; then
ocf_log warn "stopping an already stopped SystemHealth"
return $OCF_SUCCESS
else
ocf_log err "SystemHealth_stop: should not be here!"
return $OCF_ERR_GENERIC
fi
}
SystemHealth_monitor() {
# Monitor _MUST!_ differentiate correctly between running
# (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING).
# That is THREE states, not just yes/no.
if [ ! -f /var/run/ipmiservicelogd.pid0 ]; then
ocf_log debug "ipmiservicelogd is not running!"
return $OCF_NOT_RUNNING
fi
ps -p "$(cat /var/run/ipmiservicelogd.pid0)" >/dev/null 2>&1
RC=$?
if [ $RC != 0 ]; then
ocf_log debug "ipmiservicelogd's pid `cat /var/run/ipmiservicelogd.pid0` is not running!"
rm /var/run/ipmiservicelogd.pid0
return $OCF_ERR_GENERIC
fi
servicelog_notify --list --command="$OCF_RESKEY_program" > /dev/null 2>&1
RC=$?
if [ $RC = 0 ]; then
return $OCF_SUCCESS
else
return $OCF_NOT_RUNNING
fi
}
SystemHealth_validate() {
SystemHealth_check_tools
RC=$?
if [ $RC != 0 ]; then
return $RC
fi
return $OCF_SUCCESS
}
: ${OCF_RESKEY_program=/usr/sbin/notifyServicelogEvent}
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
usage|help) SystemHealth_usage
exit $OCF_SUCCESS
;;
esac
SystemHealth_check_tools
RC=$?
if [ $RC != 0 ]; then
case $__OCF_ACTION in
stop) exit $OCF_SUCCESS;;
*) exit $RC;;
esac
fi
case $__OCF_ACTION in
start) SystemHealth_start;;
stop) SystemHealth_stop;;
monitor) SystemHealth_monitor;;
reload) ocf_log info "Reloading..."
SystemHealth_start
;;
validate-all) ;;
*) SystemHealth_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
rc=$?
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
exit $rc
diff --git a/extra/resources/attribute b/extra/resources/attribute
index d8b392cd01..57b690f1c5 100755
--- a/extra/resources/attribute
+++ b/extra/resources/attribute
@@ -1,235 +1,235 @@
#!/bin/sh
#
# ocf:pacemaker:attribute resource agent
#
# Copyright 2016-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
-# This source code is licensed under GNU General Public License version 2 or
-# later (GPLv2+) WITHOUT ANY WARRANTY.
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
USAGE="Usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set."
# Load OCF helper functions
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
. ${OCF_FUNCTIONS}
: ${__OCF_ACTION=$1}
# Ensure certain variables are set and not empty
: ${HA_VARRUN:="/var/run"}
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
: ${OCF_RESOURCE_INSTANCE:="undef"}
DEFAULT_STATE_FILE="${HA_VARRUN%%/}/opa-${OCF_RESOURCE_INSTANCE}.state"
if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
# Strip off any trailing clone marker (note + is not portable in sed)
DEFAULT_STATE_FILE=$(echo "$DEFAULT_STATE_FILE" | sed s/:[0-9][0-9]*\.state/.state/)
fi
DEFAULT_ATTR_NAME="opa-${OCF_RESOURCE_INSTANCE}"
DEFAULT_ACTIVE_VALUE="1"
DEFAULT_INACTIVE_VALUE="0"
: ${OCF_RESKEY_state:="$DEFAULT_STATE_FILE"}
: ${OCF_RESKEY_name:="$DEFAULT_ATTR_NAME"}
# Values may be empty string
if [ -z ${OCF_RESKEY_active_value+x} ]; then
OCF_RESKEY_active_value="$DEFAULT_ACTIVE_VALUE"
fi
if [ -z ${OCF_RESKEY_inactive_value+x} ]; then
OCF_RESKEY_inactive_value="$DEFAULT_INACTIVE_VALUE"
fi
usage() {
USAGE_RC=$1
cat <<END
$USAGE
END
return $USAGE_RC
}
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="attribute" version="1.0">
<version>1.0</version>
<shortdesc lang="en">Manages a node attribute</shortdesc>
<longdesc lang="en">
This resource agent controls a node attribute for the node it's running on.
It sets the attribute one way when started, and another way when stopped,
according to the configuration parameters.
</longdesc>
<parameters>
<parameter name="state" unique="1">
<longdesc lang="en">
Full path of a temporary file to store the resource state in
</longdesc>
<shortdesc lang="en">State file</shortdesc>
<content type="string" default="${DEFAULT_STATE_FILE}" />
</parameter>
<parameter name="name" unique="1">
<longdesc lang="en">
Name of node attribute to manage
</longdesc>
<shortdesc lang="en">Attribute name</shortdesc>
<content type="string" default="${DEFAULT_ATTR_NAME}" />
</parameter>
<parameter name="active_value" unique="0">
<longdesc lang="en">
Value to use for node attribute when resource becomes active (empty string is
discouraged, because monitor cannot distinguish it from a query error)
</longdesc>
<shortdesc lang="en">Attribute value when active</shortdesc>
<content type="string" default="$DEFAULT_ACTIVE_VALUE" />
</parameter>
<parameter name="inactive_value" unique="0">
<longdesc lang="en">
Value to use for node attribute when resource becomes inactive
</longdesc>
<shortdesc lang="en">Attribute value when inactive</shortdesc>
<content type="string" default="$DEFAULT_INACTIVE_VALUE" />
</parameter>
</parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" timeout="20s" interval="10s" depth="0"/>
<action name="reload" timeout="20s" />
<action name="migrate_to" timeout="20s" />
<action name="migrate_from" timeout="20s" />
<action name="validate-all" timeout="20s" />
<action name="meta-data" timeout="5s" />
</actions>
</resource-agent>
END
return $OCF_SUCCESS
}
validate() {
if [ "$OCF_RESKEY_active_value" = "$OCF_RESKEY_inactive_value" ]; then
ocf_exit_reason "active value '%s' must be different from inactive value '%s'" \
"$OCF_RESKEY_active_value" "$OCF_RESKEY_inactive_value"
return $OCF_ERR_CONFIGURED
fi
VALIDATE_DIR=$(dirname "${OCF_RESKEY_state}")
if [ ! -d "$VALIDATE_DIR" ]; then
ocf_exit_reason "state file '$OCF_RESKEY_state' does not have a valid directory"
return $OCF_ERR_PERM
fi
if [ ! -w "$VALIDATE_DIR" ] || [ ! -x "$VALIDATE_DIR" ]; then
ocf_exit_reason "insufficient privileges on directory of state file '$OCF_RESKEY_state'"
return $OCF_ERR_PERM
fi
return $OCF_SUCCESS
}
get_attribute() {
GET_LINE=$(attrd_updater -n "$OCF_RESKEY_name" -Q 2>/dev/null)
if [ $? -ne 0 ]; then
echo ""
else
echo "$GET_LINE" | sed -e "s/.* value=\"\(.*\)\"$/\1/"
fi
}
set_attribute() {
attrd_updater -n "$OCF_RESKEY_name" -U "$1" 2>/dev/null
# TODO if above call is async, loop until get_attribute returns expected value
}
check_attribute() {
CHECK_VALUE=$(get_attribute)
CHECK_REASON=""
if [ ! -f "$OCF_RESKEY_state" ]; then
if [ "$CHECK_VALUE" != "" ] && [ "$CHECK_VALUE" != "$OCF_RESKEY_inactive_value" ]; then
CHECK_REASON="Node attribute $OCF_RESKEY_name='$CHECK_VALUE' differs from expected value '$OCF_RESKEY_inactive_value'"
return $OCF_ERR_GENERIC
fi
return $OCF_NOT_RUNNING
fi
if [ "$CHECK_VALUE" != "$OCF_RESKEY_active_value" ]; then
CHECK_REASON="Node attribute $OCF_RESKEY_name='$CHECK_VALUE' differs from expected value '$OCF_RESKEY_active_value'"
return $OCF_ERR_GENERIC
fi
return $OCF_SUCCESS
}
monitor() {
check_attribute
MONITOR_RC=$?
if [ $MONITOR_RC -eq $OCF_ERR_GENERIC ]; then
ocf_exit_reason "$CHECK_REASON"
fi
return $MONITOR_RC
}
start() {
check_attribute
if [ $? -eq $OCF_SUCCESS ]; then
return $OCF_SUCCESS
fi
touch "${OCF_RESKEY_state}" 2>/dev/null
if [ $? -ne 0 ]; then
ocf_exit_reason "Unable to manage state file $OCF_RESKEY_state"
return $OCF_ERR_GENERIC
fi
set_attribute "${OCF_RESKEY_active_value}"
if [ $? -ne 0 ]; then
rm -f "${OCF_RESKEY_state}"
ocf_exit_reason "Unable to set node attribute $OCF_RESKEY_name='$OCF_RESKEY_active_value'"
return $OCF_ERR_GENERIC
fi
return $OCF_SUCCESS
}
stop() {
check_attribute
if [ $? -eq $OCF_NOT_RUNNING ]; then
return $OCF_SUCCESS
fi
rm -f ${OCF_RESKEY_state}
set_attribute "${OCF_RESKEY_inactive_value}"
if [ $? -ne 0 ]; then
ocf_exit_reason "Unable to set node attribute $OCF_RESKEY_name='$OCF_RESKEY_inactive_value'"
return $OCF_ERR_GENERIC
fi
return $OCF_SUCCESS
}
case $__OCF_ACTION in
meta-data) meta_data ;;
start) start ;;
stop) stop ;;
monitor) monitor ;;
# We don't do anything special for live migration, but we support it so that
# other resources that live migrate can depend on this one.
migrate_to) stop ;;
migrate_from) start ;;
reload) start ;;
validate-all) validate ;;
usage|help) usage $OCF_SUCCESS ;;
*) usage $OCF_ERR_UNIMPLEMENTED ;;
esac
exit $?
# vim: expandtab:tabstop=4:softtabstop=4:shiftwidth=4:textwidth=80
diff --git a/extra/resources/controld b/extra/resources/controld
index 2bf464fd74..977d2664f2 100755
--- a/extra/resources/controld
+++ b/extra/resources/controld
@@ -1,300 +1,286 @@
#!/bin/sh
#
-# OCF resource agent for managing the DLM controld process
+# ocf:pacemaker:controld resource agent
#
# Copyright 2008-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
-# 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.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
+
#
-# 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.
+# Manages the DLM controld process
#
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
. ${OCF_FUNCTIONS}
: ${__OCF_ACTION=$1}
#######################################################################
if [ -e "$OCF_ROOT/resource.d/heartbeat/controld" ]; then
ocf_log info "Using heartbeat controld agent"
$OCF_ROOT/resource.d/heartbeat/controld $1
exit $?
fi
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="controld" version="1.1">
<version>1.0</version>
<longdesc lang="en">
This Resource Agent can control the dlm_controld services needed by cluster-aware file systems.
It assumes that dlm_controld is in your default PATH.
In most cases, it should be run as an anonymous clone.
</longdesc>
<shortdesc lang="en">DLM Agent for cluster file systems</shortdesc>
<parameters>
<parameter name="args" unique="1">
<longdesc lang="en">
Any additional options to start the dlm_controld service with
</longdesc>
<shortdesc lang="en">DLM Options</shortdesc>
<content type="string" default="-s 0" />
</parameter>
<parameter name="daemon" unique="1">
<longdesc lang="en">
The daemon to start - supports gfs_controld and dlm_controld
</longdesc>
<shortdesc lang="en">The daemon to start</shortdesc>
<content type="string" default="dlm_controld" />
</parameter>
<parameter name="allow_stonith_disabled">
<longdesc lang="en">
Allow DLM start-up even if STONITH/fencing is disabled in the cluster.
Setting this option to true will cause cluster malfunction and hangs on
fail-over for DLM clients that require fencing (such as GFS2, OCFS2, and
cLVM2).
This option is advanced use only.
</longdesc>
<shortdesc lang="en">Allow start-up even without STONITH/fencing</shortdesc>
<content type="string" default="false" />
</parameter>
</parameters>
<actions>
<action name="start" timeout="90s" />
<action name="stop" timeout="100s" />
<action name="monitor" timeout="20s" interval="10s" depth="0" start-delay="0s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
}
#######################################################################
CONFIGFS_DIR="/sys/kernel/config"
DLM_CONFIGFS_DIR="${CONFIGFS_DIR}/dlm"
DLM_SYSFS_DIR="/sys/kernel/dlm"
controld_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
check_uncontrolled_locks()
{
CUL_TMP=$(ls $DLM_SYSFS_DIR 2>&1)
if [ $? -eq 0 ]; then
if [ -n "$CUL_TMP" ]; then
ocf_log err "Uncontrolled lockspace exists, system must reboot. Executing suicide fencing"
stonith_admin --reboot="$(crm_node -n)" --tag controld
exit $OCF_ERR_GENERIC
fi
fi
}
controld_start() {
controld_monitor; rc=$?
case $rc in
$OCF_SUCCESS) return $OCF_SUCCESS;;
$OCF_NOT_RUNNING) ;;
*) return $OCF_ERR_GENERIC;;
esac
# Ensure configfs is mounted
if [ ! -e "$CONFIGFS_DIR" ]; then
modprobe configfs
if [ ! -e "$CONFIGFS_DIR" ]; then
ocf_log err "$CONFIGFS_DIR not available"
return $OCF_ERR_INSTALLED
fi
fi
mount -t configfs | grep " $CONFIGFS_DIR " >/dev/null 2>/dev/null
if [ $? -ne 0 ]; then
mount -t configfs none "$CONFIGFS_DIR"
fi
# Ensure DLM is available
if [ ! -e "$DLM_CONFIGFS_DIR" ]; then
modprobe dlm
if [ ! -e "$DLM_CONFIGFS_DIR" ]; then
ocf_log err "$DLM_CONFIGFS_DIR not available"
return $OCF_ERR_INSTALLED
fi
fi
if ! ocf_is_true "$OCF_RESKEY_allow_stonith_disabled" && \
! ocf_is_true "`crm_attribute --type=crm_config --name=stonith-enabled --query --quiet --default=true`"; then
ocf_log err "The cluster property stonith-enabled may not be deactivated to use the DLM"
return $OCF_ERR_CONFIGURED
fi
${OCF_RESKEY_daemon} $OCF_RESKEY_args
while true
do
sleep 1
controld_monitor; rc=$?
case $rc in
$OCF_SUCCESS)
CS_ADDR_LIST="$(cat "${DLM_CONFIGFS_DIR}"/cluster/comms/*/addr_list 2>/dev/null)"
if [ $? -eq 0 ] && [ -n "$CS_ADDR_LIST" ]; then
return $OCF_SUCCESS
fi
;;
$OCF_NOT_RUNNING)
return $OCF_NOT_RUNNING
;;
*)
return $OCF_ERR_GENERIC
;;
esac
ocf_log debug "Waiting for ${OCF_RESKEY_daemon} to be ready"
done
}
controld_stop() {
controld_monitor; rc=$?
if [ $rc = $OCF_NOT_RUNNING ]; then
return $OCF_SUCCESS
fi
killall -TERM ${OCF_RESKEY_daemon}; rc=$?
if [ $rc != 0 ]; then
return $OCF_ERR_GENERIC
fi
rc=$OCF_SUCCESS
while [ $rc = $OCF_SUCCESS ]; do
controld_monitor; rc=$?
sleep 1
done
if [ $rc = $OCF_NOT_RUNNING ]; then
rc=$OCF_SUCCESS
fi
return $rc
}
controld_monitor() {
killall -0 ${OCF_RESKEY_daemon} >/dev/null 2>&1 ; CM_RC=$?
case $CM_RC in
0) smw=$(dlm_tool status -v | grep "stateful_merge_wait=" | cut -d= -f2)
if [ -n "$smw" ] && [ $smw -eq 1 ]; then
ocf_log err "DLM status is: stateful_merge_wait"
CM_RC=$OCF_ERR_GENERIC
elif [ -z "$smw" ] && dlm_tool ls | grep -q "wait fencing" && \
! stonith_admin -H '*' -V | grep -q "wishes to"; then
ocf_log err "DLM status is: wait fencing"
CM_RC=$OCF_ERR_GENERIC
else
CM_RC=$OCF_SUCCESS
fi
;;
1) CM_RC=$OCF_NOT_RUNNING;;
*) CM_RC=$OCF_ERR_GENERIC;;
esac
# if the dlm is not successfully running, but
# dlm lockspace bits are left over, we self must fence.
if [ $CM_RC -ne $OCF_SUCCESS ]; then
check_uncontrolled_locks
fi
return $CM_RC
}
controld_validate() {
check_binary killall
check_binary ${OCF_RESKEY_daemon}
case ${OCF_RESKEY_CRM_meta_globally_unique} in
yes|Yes|true|True|1)
ocf_log err "$OCF_RESOURCE_INSTANCE must be configured with the globally_unique=false meta attribute"
exit $OCF_ERR_CONFIGURED
;;
esac
[ -d /var/run/cluster ] || mkdir /var/run/cluster
return $OCF_SUCCESS
}
: ${OCF_RESKEY_sctp=false}
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
case "$OCF_RESOURCE_INSTANCE" in
*[gG][fF][sS]*)
: ${OCF_RESKEY_args=-g 0}
: ${OCF_RESKEY_daemon=gfs_controld}
;;
*[dD][lL][mM]*)
: ${OCF_RESKEY_args=-s 0}
: ${OCF_RESKEY_daemon=dlm_controld}
;;
*)
: ${OCF_RESKEY_args=-s 0}
: ${OCF_RESKEY_daemon=dlm_controld}
esac
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) controld_validate; controld_start;;
stop) controld_stop;;
monitor) controld_validate; controld_monitor;;
validate-all) controld_validate;;
usage|help) controld_usage
exit $OCF_SUCCESS
;;
*) controld_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
rc=$?
exit $rc
diff --git a/extra/resources/ifspeed.in b/extra/resources/ifspeed.in
index 676578e978..860d9d2984 100755
--- a/extra/resources/ifspeed.in
+++ b/extra/resources/ifspeed.in
@@ -1,540 +1,548 @@
#!@BASH_PATH@
#
-# OCF resource agent which monitors state of network interface and records it
-# as a node attribute in the CIB based on the sum of speeds of its active (up,
-# link detected, not blocked) underlying interfaces.
+# ocf:pacemaker:ifspeed resource agent
#
# Copyright 2011-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+
+#
+# OCF resource agent which monitors state of network interface and records it
+# as a node attribute in the CIB based on the sum of speeds of its active (up,
+# link detected, not blocked) underlying interfaces.
+#
# Partially based on 'ping' RA by Andrew Beekhof
#
# Change on 2017 by Tomer Azran <tomerazran@gmail.com>:
# Add "ip" parameter to detect network interface name by ip address:
# http://lists.clusterlabs.org/pipermail/users/2017-August/006224.html
#
# OCF instance parameters:
# OCF_RESKEY_name: name of attribute to set in CIB
# OCF_RESKEY_ip ip address to check
# OCF_RESKEY_iface: network interface to monitor
# OCF_RESKEY_bridge_ports: if not null and OCF_RESKEY_iface is a bridge, list of
# bridge ports to consider.
# Default is all ports which have designated_bridge=root_id
# OCF_RESKEY_weight_base: Relative weight of 1Gbps. This can be used to tune
# value of resulting CIB attribute.
#
# Initialization:
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
# If these aren't available, we can still show help,
# which is all that is needed to build the man pages.
[ -r "${OCF_FUNCTIONS}" ] && . "${OCF_FUNCTIONS}"
[ -r "${OCF_FUNCTIONS_DIR}/findif.sh" ] && . "${OCF_FUNCTIONS_DIR}/findif.sh"
: ${OCF_SUCCESS=0}
: ${__OCF_ACTION=$1}
FINDIF=findif
# Defaults
OCF_RESKEY_name_default="ifspeed"
OCF_RESKEY_bridge_ports_default="detect"
OCF_RESKEY_weight_base_default=1000
OCF_RESKEY_dampen_default=5
: ${OCF_RESKEY_name=${OCF_RESKEY_name_default}}
: ${OCF_RESKEY_bridge_ports=${OCF_RESKEY_bridge_ports_default}}
: ${OCF_RESKEY_weight_base=${OCF_RESKEY_weight_base_default}}
: ${OCF_RESKEY_dampen=${OCF_RESKEY_dampen_default}}
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="ifspeed" version="1.0">
<version>1.0</version>
<longdesc lang="en">
Every time the monitor action is run, this resource agent records (in the CIB)
(relative) speed of network interface it monitors.
This RA can monitor physical interfaces, bonds, bridges, vlans and (hopefully)
any combination of them.
Examples:
*) Bridge on top of one 10Gbps interface (eth2) and 802.3ad bonding (bond0) built
on two 1Gbps interfaces (eth0 and eth1).
*) Active-backup bonding built on top of one physical interface and one vlan on
another interface.
For STP-enabled bridges this RA tries to some-how guess network topology and by
default looks only on ports which are connected to upstream switch. This can be
overridden by 'bridge_ports' parameter. Active interfaces in this case are those
in "forwarding" state.
For balancing bonds this RA summs speeds of underlying "up" slave interfaces
(and applies coefficient 0.8 to result).
For non-balancing bonds ('active-backup' and probably 'broadcast'), only the
speed of the currently active slave is used.
</longdesc>
<shortdesc lang="en">Network interface speed monitor</shortdesc>
<parameters>
<parameter name="name" unique="1">
<longdesc lang="en">
The name of the attribute to set. This is the name to be used in the constraints.
</longdesc>
<shortdesc lang="en">Attribute name</shortdesc>
<content type="string" default="${OCF_RESKEY_name_default}"/>
</parameter>
<parameter name="iface" unique="0" required="1">
<longdesc lang="en">
Network interface to monitor.
</longdesc>
<shortdesc lang="en">Network interface</shortdesc>
<content type="string" default=""/>
</parameter>
<parameter name="ip" unique="0" required="0">
<longdesc lang="en">
Try to detect interface name by detecting the interface that holds the IP address.
The IPv4 (dotted quad notation) or IPv6 address (colon hexadecimal notation)
example IPv4 "192.168.1.1".
example IPv6 "2001:db8:DC28:0:0:FC57:D4C8:1FFF".
</longdesc>
<shortdesc lang="en">IPv4 or IPv6 address</shortdesc>
<content type="string" default="" />
</parameter>
<parameter name="bridge_ports" unique="0">
<longdesc lang="en">
If not null and OCF_RESKEY_iface is a bridge, list of bridge ports to consider.
Default is all ports which have designated_bridge=root_id.
</longdesc>
<shortdesc lang="en">Bridge ports</shortdesc>
<content type="string" default="${OCF_RESKEY_bridge_ports_default}"/>
</parameter>
<parameter name="weight_base" unique="0">
<longdesc lang="en">
Relative weight of 1Gbps in interface speed.
Can be used to tune how big attribute value will be.
</longdesc>
<shortdesc lang="en">Weight of 1Gbps</shortdesc>
<content type="integer" default="${OCF_RESKEY_weight_base_default}"/>
</parameter>
<parameter name="dampen" unique="0">
<longdesc lang="en">
The time to wait (dampening) for further changes to occur.
</longdesc>
<shortdesc lang="en">Dampening interval</shortdesc>
<content type="integer" default="${OCF_RESKEY_dampen_default}"/>
</parameter>
<parameter name="debug" unique="0">
<longdesc lang="en">
Log what have been done more verbosely.
</longdesc>
<shortdesc lang="en">Verbose logging</shortdesc>
<content type="string" default="false"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="30s" />
<action name="stop" timeout="30s" />
<action name="monitor" depth="0" timeout="30s" interval="10s"/>
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
}
usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
start() {
monitor
if [ $? -eq $OCF_SUCCESS ]; then
return $OCF_SUCCESS
fi
ha_pseudo_resource ${ha_pseudo_resource_name} start
update
return $?
}
stop() {
ha_pseudo_resource ${ha_pseudo_resource_name} stop
attrd_updater -D -n ${OCF_RESKEY_name} -d ${OCF_RESKEY_dampen} ${attrd_options}
return $OCF_SUCCESS
}
monitor() {
local ret
ha_pseudo_resource ${ha_pseudo_resource_name} monitor
ret=$?
if [ ${ret} -eq $OCF_SUCCESS ] ; then
update
fi
return ${ret}
}
# This function tries to guess nic interface by IP
get_nic_name_by_ip(){
# $FINDIF takes its parameters from the environment.
# Its output is as follows:
# [NIC_NAME] netmask [NETMASK] broadcast [BROADCAST}
NICINFO=$( ${FINDIF} )
rc=$?
if [ $rc -eq 0 ];then
# Get NIC_NAME part of findif function output.
echo "${NICINFO%% *}"
else
echo ""
fi
}
validate() {
# Check the interface parameter
if [ -z "${OCF_RESKEY_iface}" ]; then
if [ -z "${OCF_RESKEY_ip}" ]; then
ocf_log err "Empty iface and ip parameters. Please specify either an interface name or valid ip address."
exit $OCF_ERR_CONFIGURED
else
ipcheck_ipv4 "${OCF_RESKEY_ip}"
if [ $? -eq 1 ] ; then
ipcheck_ipv6 "${OCF_RESKEY_ip}"
if [ $? -eq 1 ] ; then
ocf_exit_reason "ip parameter [${OCF_RESKEY_ip}] is not a valid ip address."
exit $OCF_ERR_CONFIGURED
fi
fi
fi
fi
return $OCF_SUCCESS
}
iface_get_speed() {
local iface=$1
local operstate
local carrier
local speed
if [ ! -e "/sys/class/net/${iface}" ] ; then
echo "0"
elif iface_is_bridge ${iface} ; then # bridges do not have operstate
read carrier < "/sys/class/net/${iface}/carrier"
if [ "${carrier}" != "1" ] ; then
echo "0"
else
bridge_get_speed ${iface}
fi
else
read operstate < "/sys/class/net/${iface}/operstate"
read carrier < "/sys/class/net/${iface}/carrier"
if [ "${operstate}" != "up" ] || [ "${carrier}" != "1" ] ; then
echo "0"
elif iface_is_bond ${iface} ; then
bond_get_speed ${iface}
elif iface_is_vlan ${iface} ; then
iface_get_speed "$(vlan_get_phy "${iface}")"
elif iface_is_hfi1 "${iface}" ; then
hfi1_get_speed "${iface}"
else
read speed < "/sys/class/net/${iface}/speed"
echo ${speed}
fi
fi
}
iface_is_vlan() {
local iface=$1
[ -e "/proc/net/vlan/${iface}" ] && return 0 || return 1
}
iface_is_bridge() {
local iface=$1
[ -e "/sys/class/net/${iface}/bridge" ] && return 0 || return 1
}
iface_is_bond() {
local iface=$1
[ -e "/sys/class/net/${iface}/bonding" ] && return 0 || return 1
}
iface_is_hfi1() {
local iface=$1
driver=$(readlink /sys/class/net/${iface}/device/driver)
[[ $(basename ${driver}) =~ "hfi1" ]] && return 0 || return 1
}
vlan_get_phy() {
local iface=$1
sed -ne "s/^${iface} .*| *//p" < /proc/net/vlan/config
}
bridge_is_stp_enabled() {
local iface=$1
local stp
read stp < "/sys/class/net/${iface}/bridge/stp_state"
[ "${stp}" = "1" ] && return 0 || return 1
}
bridge_get_root_ports() {
local bridge=$1
local root_id
local root_ports=""
local bridge_id
read root_id < "/sys/class/net/${bridge}/bridge/root_id"
for port in /sys/class/net/${bridge}/brif/* ; do
read bridge_id < "${port}/designated_bridge"
if [ "${bridge_id}" = "${root_id}" ] ; then
root_ports="${root_ports} ${port##*/}"
fi
done
root_ports=${root_ports# }
if [ -n "$2" ] ; then # Record value in specified var. This expects we were called not in a sub-shell.
eval "$2=\${root_ports}"
else # Expect sub-shell
echo ${root_ports}
fi
}
# From /inlude/linux/if_bridge.h:
#define BR_STATE_DISABLED 0
#define BR_STATE_LISTENING 1
#define BR_STATE_LEARNING 2
#define BR_STATE_FORWARDING 3
#define BR_STATE_BLOCKING 4
bridge_get_active_ports() {
local bridge=$1
shift 1
local ports="$*"
local active_ports=""
local port_state
local stp_state
local warn=0
bridge_is_stp_enabled ${bridge}
stp_state=$?
if [ -z "${ports}" ] || [ "${ports}" = "detect" ] ; then
bridge_get_root_ports ${bridge} ports
fi
for port in $ports ; do
if [ ! -e "/sys/class/net/${bridge}/brif/${port}" ] ; then
ocf_log warning "Port ${port} doesn't belong to bridge ${bridge}"
continue
fi
read port_state < "/sys/class/net/${bridge}/brif/${port}/state"
if [ "${port_state}" = "3" ] ; then
if [ -n "${active_ports}" ] && ${stp_state} ; then
warn=1
fi
active_ports="${active_ports} ${port}"
fi
done
if [ ${warn} -eq 1 ] ; then
ocf_log warning "More then one upstream port in bridge '${bridge}' is in forwarding state while STP is enabled: ${active_ports}"
fi
echo "${active_ports# }"
}
bridge_get_speed() {
local iface=$1
local aggregate_speed=0
if ! iface_is_bridge ${iface} ; then
echo 0
return
fi
BGS_PORTS=$( bridge_get_active_ports "${iface}" "${OCF_RESKEY_bridge_ports}" )
for port in ${BGS_PORTS} ; do
: $(( aggregate_speed += $( iface_get_speed ${port} ) ))
done
if [ -n "$2" ] ; then # Record value in specified var. This expects we were called not in a sub-shell.
eval "$2=\${aggregate_speed}"
else # Expect sub-shell
echo ${aggregate_speed}
fi
}
hfi1_get_speed() {
local iface=$1
local hfi1_speed
local hfi1_value
local hfi1_desc
# Currently (9/14/2017 Intel Omni Path v10.5.0.0.155), Intel doesn't have
# dual- or multiple-port Host Channel Adapters, and it's safe to use this
# method to get the speed. Example output:
# [root@es-host0 ~]# cat /sys/class/net/ib0/device/infiniband/*/ports/*/rate
# 100 Gb/sec (4X EDR)
read hfi1_speed hfi1_value hfi1_desc < /sys/class/net/${iface}/device/infiniband/*/ports/*/rate
ocf_is_true ${OCF_RESKEY_debug} && ocf_log debug "Detected speed $hfi1_speed $hfi1_value $hfi1_desc"
# hfi1_value always in Gb/sec, so we need to convert hfi1_speed in Mb/sec
echo $(( hfi1_speed * 1000 ))
}
bond_get_slaves() {
local iface=$1
local slaves
read slaves < "/sys/class/net/${iface}/bonding/slaves"
if [ -n "$2" ] ; then # Record value in specified var. This expects we were called not in a sub-shell.
eval "$2=\${slaves}"
else # Expect sub-shell
echo ${slaves}
fi
}
bond_get_active_iface() {
local iface=$1
local active
read active < "/sys/class/net/${iface}/bonding/active_slave"
if [ -n "$2" ] ; then # Record value in specified var. This expects we were called not in a sub-shell.
eval "$2=\${active}"
else # Expect sub-shell
echo ${active}
fi
}
bond_is_balancing() {
local iface=$1
read mode mode_index < "/sys/class/net/${iface}/bonding/mode"
ocf_is_true ${OCF_RESKEY_debug} && ocf_log debug "Detected balancing $mode $mode_index"
case ${mode} in
"balance-rr"|"balance-xor"|"802.3ad"|"balance-tlb"|"balance-alb")
return 0
;;
*)
return 1
;;
esac
}
bond_get_speed() {
local iface=$1
local aggregate_speed=0
local active_iface
local bond_slaves
if ! iface_is_bond ${iface} ; then
echo 0
return
fi
bond_get_slaves ${iface} bond_slaves
if bond_is_balancing ${iface} ; then
for slave in ${bond_slaves} ; do
: $(( aggregate_speed += $( iface_get_speed ${slave} ) ))
done
# Bonding is unable to get speed*n
: $(( aggregate_speed = aggregate_speed * 8 / 10 ))
else
bond_get_active_iface ${iface} active_iface
aggregate_speed=$( iface_get_speed $active_iface )
fi
if [ -n "$2" ] ; then # Record value in specified var. This expects we were called not in a sub-shell.
eval "$2=\${aggregate_speed}"
else # Expect sub-shell
echo ${aggregate_speed}
fi
}
update() {
local speed;
local nic=${OCF_RESKEY_iface};
if [ -z "${OCF_RESKEY_iface}" ]; then
nic=$( get_nic_name_by_ip )
if [ -z "${nic}" ];then
ocf_log err "Could not retrieve network interface name from ip address (${OCF_RESKEY_ip})"
exit $OCF_ERR_GENERIC
fi
fi
speed=$( iface_get_speed ${nic} )
: $(( score = speed * ${OCF_RESKEY_weight_base} / 1000 ))
if [ "$__OCF_ACTION" = "start" ] ; then
attrd_updater -n ${OCF_RESKEY_name} -B ${score} -d ${OCF_RESKEY_dampen} ${attrd_options}
else
attrd_updater -n ${OCF_RESKEY_name} -v ${score} -d ${OCF_RESKEY_dampen} ${attrd_options}
fi
rc=$?
case ${rc} in
0)
ocf_is_true ${OCF_RESKEY_debug} && ocf_log debug "Updated ${OCF_RESKEY_name} = ${score}"
;;
*)
ocf_log warn "Could not update ${OCF_RESKEY_name} = ${score}: rc=${rc}"
;;
esac
return ${rc}
}
case $__OCF_ACTION in
meta-data)
meta_data
exit $OCF_SUCCESS
;;
usage|help)
usage
exit $OCF_SUCCESS
;;
esac
if [ "$(uname)" != "Linux" ] ; then
ocf_log err "This RA works only on linux."
exit $OCF_ERR_INSTALLED
fi
: ${ha_pseudo_resource_name:="ifspeed-${OCF_RESOURCE_INSTANCE}"}
attrd_options='-q'
if ocf_is_true ${OCF_RESKEY_debug} ; then
attrd_options=''
fi
validate || exit $?
case $__OCF_ACTION in
start)
start
;;
stop)
stop
;;
monitor)
monitor
;;
validate-all)
;;
*)
usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
diff --git a/extra/resources/o2cb.in b/extra/resources/o2cb.in
index e938c9c13b..b71cc6f1a1 100755
--- a/extra/resources/o2cb.in
+++ b/extra/resources/o2cb.in
@@ -1,454 +1,445 @@
#!@BASH_PATH@
#
+# ocf:pacemaker:o2cb resource agent
+#
# Original copyright 2005-2008 Oracle
# Later changes copyright 2008-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
-# 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.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
#
+
#######################################################################
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
. ${OCF_FUNCTIONS}
: ${__OCF_ACTION=$1}
: ${OCF_RESKEY_stack:="pcmk"}
: ${OCF_RESKEY_sysfs:="/sys/fs"}
: ${OCF_RESKEY_configfs:="/sys/kernel/config"}
: ${OCF_RESKEY_daemon_timeout:="10"} # How long to wait for things to start
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
DAEMON="/usr/sbin/ocfs2_controld.${OCF_RESKEY_stack}"
CLUSTER_STACK_FILE="${OCF_RESKEY_sysfs}/ocfs2/cluster_stack"
LOADED_PLUGINS_FILE="${OCF_RESKEY_sysfs}/ocfs2/loaded_cluster_plugins"
#
# Check to see if a filesystem driver is loaded.
# 0 is loaded, 1 is not.
#
driver_filesystem() {
if [ -z "$1" ]
then
ocf_log err "driver_filesystem(): Missing an argument"
exit 1
fi
FSNAME="$1"
FSOUT="$(awk '(NF == 1 && $1 ~ /^'$FSNAME'$/) || $2 ~ /^'$FSNAME'$/{
print $1;exit
}' /proc/filesystems 2>/dev/null)"
test -n "$FSOUT"
return $?
}
#
# Check to see if a filesystem of type $1 is mounted at $2.
#
# 0 is mounted, 1 is not.
#
check_filesystem()
{
if [ "$#" != "2" -o -z "$1" -o -z "$2" ]
then
ocf_log err "check_filesystem(): Missing arguments"
exit 4
fi
FSNAME="$1"
MOUNTPOINT="$2"
FULL_MOUNTSEARCH="`echo "$MOUNTPOINT" | sed -e 's/\//\\\\\//g'`"
MOUNTOUT="`awk '$2 ~ /^'$FULL_MOUNTSEARCH'$/ && $3 ~ /^'$FSNAME'$/{print $2; exit}' < /proc/mounts 2>/dev/null`"
test -n "$MOUNTOUT"
return $?
}
#
# Unload a filesystem driver.
# Be careful to notice if the driver is built-in and do nothing.
#
# 0 is success, 1 is error, 2 is already unloaded.
#
unload_filesystem()
{
if [ "$#" != "1" -o -z "$1" ]
then
ocf_log err "unload_filesystem(): Missing an argument"
return 1
fi
FSNAME="$1"
driver_filesystem "$FSNAME" || return 2
MODOUT="`awk '$1 ~ /^'$FSNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null`"
if [ -z "$MODOUT" ]; then
# The driver is built in, we can't unload it.
return 0
fi
case "$MODOUT" in
$FSNAME\ 0)
;;
$FSNAME\ *)
# The driver is busy, leave it alone
ocf_log err "Module $FSNAME is still in use"
return 1
;;
*)
ocf_log err "Invalid module parsing! "
return 1
;;
esac
modprobe -rs "$FSNAME"
if [ "$?" != 0 ]; then
ocf_log err "Unable to unload module: $FSNAME"
return 1
fi
return 0
}
status_daemon()
{
PID=`pidof "$DAEMON"`
if [ -n "$PID" ]; then
return $OCF_SUCCESS
fi
return $OCF_NOT_RUNNING
}
bringup_daemon()
{
if [ ! -e "$DAEMON" ]; then
ocf_log err "Required binary not found: $DAEMON"
return $OCF_ERR_INSTALLED
fi
"$DAEMON"; rc=$?
if [ $rc != 0 ]; then
ocf_log err "Could not start $DAEMON"
return $OCF_ERR_GENERIC
fi
sleep 1
COUNT=0
rc=$OCF_NOT_RUNNING
while [ $rc = $OCF_NOT_RUNNING ]; do
COUNT=`expr $COUNT + 1`
if [ $COUNT -gt $OCF_RESKEY_daemon_timeout ]; then
ocf_log err "`basename $DAEMON` did not come up"
return $OCF_ERR_GENERIC
fi
status_daemon; rc=$?
sleep 1
done
return $rc
}
kill_daemon()
{
status_daemon; rc=$?
if [ $rc != $OCF_SUCCESS ]; then
return $rc
fi
ocf_log info "Stopping `basename "$DAEMON"`"
killproc "$DAEMON"
while [ $rc = $OCF_NOT_RUNNING ]; do
sleep 1
status_daemon; rc=$?
done
return $OCF_SUCCESS
}
#
# Unload a module
# 0 is success, 1 is error, 2 is not loaded
#
unload_module()
{
if [ "$#" -lt "1" -o -z "$1" ]
then
ocf_log err "unload_module(): Requires an argument"
return 1
fi
MODNAME="$1"
MODOUT="`awk '$1 ~ /^'$MODNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null`"
if [ -z "$MODOUT" ]
then
return 2
fi
case "$MODOUT" in
$MODNAME\ 0)
;;
$MODNAME\ *)
return 2
;;
*)
ocf_log err "Invalid module parsing!"
return 1
;;
esac
modprobe -rs "$MODNAME"
if [ "$?" != 0 ]; then
ocf_log err "Unable to unload module \"$MODNAME\""
return 1
fi
return 0
}
o2cb_start() {
o2cb_monitor; rc=$?
if [ $rc != $OCF_NOT_RUNNING ]; then
return $rc
fi
ocf_log info "Starting $OCF_RESOURCE_INSTANCE"
if [ ! -e "$CLUSTER_STACK_FILE" ]; then
modprobe -s ocfs2_stackglue
if [ $? != 0 ]; then
ocf_log err "Could not load ocfs2_stackglue"
return $OCF_ERR_INSTALLED
fi
fi
SP_OUT="$(awk '/^'user'$/{print; exit}' "$LOADED_PLUGINS_FILE" 2>/dev/null)"
if [ -z "$SP_OUT" ]
then
modprobe -s ocfs2_stack_user
if [ $? != 0 ]; then
ocf_log err "Could not load ocfs2_stack_user"
return $OCF_ERR_INSTALLED
fi
fi
SP_OUT="$(awk '/^'user'$/{print; exit}' "$LOADED_PLUGINS_FILE" 2>/dev/null)"
if [ -z "$SP_OUT" ]; then
ocf_log err "Switch to userspace stack unsuccessful"
return $OCF_ERR_INSTALLED
fi
if [ -f "$CLUSTER_STACK_FILE" ]; then
echo "$OCF_RESKEY_stack" >"$CLUSTER_STACK_FILE"
if [ $? != 0 ]; then
ocf_log err "Userspace stack '$OCF_RESKEY_stack' not supported"
return $OCF_ERR_INSTALLED
fi
else
ocf_log err "Switch to userspace stack not supported"
return $OCF_ERR_INSTALLED
fi
driver_filesystem ocfs2; rc=$?
if [ $rc != 0 ]; then
modprobe -s ocfs2
if [ "$?" != 0 ]; then
ocf_log err "Unable to load ocfs2 module"
return $OCF_ERR_INSTALLED
fi
fi
bringup_daemon
return $?
}
o2cb_stop() {
o2cb_monitor; rc=$?
case $rc in
$OCF_NOT_RUNNING) return $OCF_SUCCESS;;
esac
ocf_log info "Stopping $OCF_RESOURCE_INSTANCE"
kill_daemon
if [ $? != 0 ]; then
ocf_log err "Unable to unload modules: the cluster is still online"
return $OCF_ERR_GENERIC
fi
unload_filesystem ocfs2
if [ $? = 1 ]; then
ocf_log err "Unable to unload ocfs2 module"
return $OCF_ERR_GENERIC
fi
# If we can't find the stack glue, we have nothing to do.
[ ! -e "$LOADED_PLUGINS_FILE" ] && return $OCF_SUCCESS
while read plugin
do
unload_module "ocfs2_stack_${plugin}"
if [ $? = 1 ]; then
ocf_log err "Unable to unload ocfs2_stack_${plugin}"
return $OCF_ERR_GENERIC
fi
done <"$LOADED_PLUGINS_FILE"
unload_module "ocfs2_stackglue"
if [ $? = 1 ]; then
ocf_log err "Unable to unload ocfs2_stackglue"
return $OCF_ERR_GENERIC
fi
# Don't unmount configfs - it's always in use by libdlm
}
o2cb_monitor() {
o2cb_validate
# Assume that ocfs2_controld will terminate if any of the conditions below are met
driver_filesystem configfs; rc=$?
if [ $rc != 0 ]; then
ocf_log info "configfs not loaded"
return $OCF_NOT_RUNNING
fi
check_filesystem configfs "${OCF_RESKEY_configfs}"; rc=$?
if [ $rc != 0 ]; then
ocf_log info "configfs not mounted"
return $OCF_NOT_RUNNING
fi
if [ ! -e "$LOADED_PLUGINS_FILE" ]; then
ocf_log info "Stack glue driver not loaded"
return $OCF_NOT_RUNNING
fi
grep user "$LOADED_PLUGINS_FILE" >/dev/null 2>&1; rc=$?
if [ $rc != 0 ]; then
ocf_log err "Wrong stack `cat $LOADED_PLUGINS_FILE`"
return $OCF_ERR_INSTALLED
fi
driver_filesystem ocfs2; rc=$?
if [ $rc != 0 ]; then
ocf_log info "ocfs2 not loaded"
return $OCF_NOT_RUNNING
fi
status_daemon
return $?
}
o2cb_usage() {
echo "usage: $0 {start|stop|monitor|validate-all|meta-data}"
echo " Expects to have a fully populated OCF RA-compliant environment set."
echo " In particualr, a value for OCF_ROOT"
}
o2cb_validate() {
check_binary ${DAEMON}
case ${OCF_RESKEY_CRM_meta_globally_unique} in
yes|Yes|true|True|1)
ocf_log err "$OCF_RESOURCE_INSTANCE must be configured with the globally_unique=false meta attribute"
exit $OCF_ERR_CONFIGURED
;;
esac
return $OCF_SUCCESS
}
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="o2cb" version="1.0">
<version>1.0</version>
<shortdesc lang="en">OCFS2 daemon resource agent</shortdesc>
<longdesc lang="en">
This Resource Agent controls the userspace daemon needed by OCFS2.
</longdesc>
<parameters>
<parameter name="sysfs" unique="0">
<longdesc lang="en">
Location where sysfs is mounted
</longdesc>
<shortdesc lang="en">Sysfs location</shortdesc>
<content type="string" default="/sys/fs"/>
</parameter>
<parameter name="configfs" unique="0">
<longdesc lang="en">
Location where configfs is mounted
</longdesc>
<shortdesc lang="en">Configfs location</shortdesc>
<content type="string" default="/sys/kernel/config"/>
</parameter>
<parameter name="stack" unique="0">
<longdesc lang="en">
Which userspace stack to use. Known values: pcmk
</longdesc>
<shortdesc lang="en">Userspace stack</shortdesc>
<content type="string" default="pcmk"/>
</parameter>
<parameter name="daemon_timeout" unique="0">
<longdesc lang="en">
Number of seconds to allow the control daemon to come up
</longdesc>
<shortdesc lang="en">Daemon Timeout</shortdesc>
<content type="string" default="10"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="90s" />
<action name="stop" timeout="100s" />
<action name="monitor" timeout="20s" depth="0"/>
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
}
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) o2cb_start
;;
stop) o2cb_stop
;;
monitor) o2cb_monitor
;;
validate-all) o2cb_validate
;;
usage|help) o2cb_usage
exit $OCF_SUCCESS
;;
*) o2cb_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
diff --git a/extra/resources/ping b/extra/resources/ping
index 1210540e6e..81c76868c9 100755
--- a/extra/resources/ping
+++ b/extra/resources/ping
@@ -1,416 +1,417 @@
#!/bin/sh
#
-# Ping OCF RA that utilizes the system ping
+# ocf:pacemaker:ping resource agent
#
# Copyright 2009-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
+
#######################################################################
# 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="ping" version="1.0">
<version>1.0</version>
<longdesc lang="en">
Every time the monitor action is run, this resource agent records (in the CIB) the current number of nodes the host can connect to using the system fping (preferred) or ping tool.
</longdesc>
<shortdesc lang="en">node connectivity</shortdesc>
<parameters>
<parameter name="pidfile" unique="0">
<longdesc lang="en">PID file</longdesc>
<shortdesc lang="en">PID file</shortdesc>
<content type="string" default="${HA_VARRUN%%/}/ping-${OCF_RESOURCE_INSTANCE}" />
</parameter>
<parameter name="dampen" unique="0">
<longdesc lang="en">
The time to wait (dampening) further changes occur
</longdesc>
<shortdesc lang="en">Dampening interval</shortdesc>
<content type="integer" default="5s"/>
</parameter>
<parameter name="name" unique="0">
<longdesc lang="en">
The name of the attributes to set. This is the name to be used in the constraints.
</longdesc>
<shortdesc lang="en">Attribute name</shortdesc>
<content type="string" default="pingd"/>
</parameter>
<parameter name="multiplier" unique="0">
<longdesc lang="en">
The number by which to multiply the number of connected ping nodes by
</longdesc>
<shortdesc lang="en">Value multiplier</shortdesc>
<content type="integer" default="1"/>
</parameter>
<parameter name="host_list" unique="0" required="1">
<longdesc lang="en">
A space separated list of ping nodes to count.
</longdesc>
<shortdesc lang="en">Host list</shortdesc>
<content type="string" default=""/>
</parameter>
<parameter name="attempts" unique="0">
<longdesc lang="en">
Number of ping attempts, per host, before declaring it dead
</longdesc>
<shortdesc lang="en">no. of ping attempts</shortdesc>
<content type="integer" default="3"/>
</parameter>
<parameter name="timeout" unique="0">
<longdesc lang="en">
How long, in seconds, to wait before declaring a ping lost
</longdesc>
<shortdesc lang="en">ping timeout in seconds</shortdesc>
<content type="integer" default="2"/>
</parameter>
<parameter name="options" unique="0">
<longdesc lang="en">
A catch all for any other options that need to be passed to ping.
</longdesc>
<shortdesc lang="en">Extra Options</shortdesc>
<content type="string" default=""/>
</parameter>
<parameter name="failure_score" unique="0">
<longdesc lang="en">
Resource is failed if the score is less than failure_score.
Default never fails.
</longdesc>
<shortdesc lang="en">failure_score</shortdesc>
<content type="integer" default=""/>
</parameter>
<parameter name="use_fping" unique="0">
<longdesc lang="en">
Use fping rather than ping, if found. If set to 0, fping
will not be used even if present.
</longdesc>
<shortdesc lang="en">Use fping if available</shortdesc>
<content type="boolean" default="1"/>
</parameter>
<parameter name="debug" unique="0">
<longdesc lang="en">
Enables to use default attrd_updater verbose logging on every call.
</longdesc>
<shortdesc lang="en">Verbose logging</shortdesc>
<content type="string" default="false"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="60s" />
<action name="stop" timeout="20s" />
<action name="monitor" depth="0" timeout="60s" interval="10s"/>
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
}
#######################################################################
ping_conditional_log() {
level=$1; shift
if [ ${OCF_RESKEY_debug} = "true" ]; then
ocf_log $level "$*"
fi
}
ping_usage() {
cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
ping_start() {
ping_monitor
if [ $? = $OCF_SUCCESS ]; then
return $OCF_SUCCESS
fi
touch ${OCF_RESKEY_pidfile}
ping_update
}
ping_stop() {
rm -f ${OCF_RESKEY_pidfile}
attrd_updater -D -n $OCF_RESKEY_name -d $OCF_RESKEY_dampen $attrd_options
return $OCF_SUCCESS
}
ping_monitor() {
if [ -f ${OCF_RESKEY_pidfile} ]; then
ping_update
if [ $? -eq 0 ]; then
return $OCF_SUCCESS
fi
return $OCF_ERR_GENERIC
fi
return $OCF_NOT_RUNNING
}
ping_validate() {
# Is the state directory writable?
state_dir=`dirname "$OCF_RESKEY_pidfile"`
touch "$state_dir/$$"
if [ $? != 0 ]; then
ocf_log err "Invalid location for 'state': $state_dir is not writable"
return $OCF_ERR_ARGS
fi
rm "$state_dir/$$"
# Pidfile better be an absolute path
case $OCF_RESKEY_pidfile in
/*) ;;
*) ocf_log warn "You should use an absolute path for pidfile not: $OCF_RESKEY_pidfile" ;;
esac
# Check the host list
if [ "x" = "x$OCF_RESKEY_host_list" ]; then
ocf_log err "Empty host_list. Please specify some nodes to ping"
exit $OCF_ERR_CONFIGURED
fi
# For fping allow only same IP versions or hostnames
if use_fping; then
hosts_family
if [ $? -eq 99 ]; then
ocf_log err "host_list can contain only host with same IP versions for fping"
exit $OCF_ERR_CONFIGURED
fi
fi
check_binary ping
return $OCF_SUCCESS
}
fping_check() {
p_exe=fping
hosts_family
case $? in
6) p_exe=fping6 ;;
99) ocf_log err "Ambiguous IP versions in host_list: '$OCF_RESKEY_host_list'"; exit $OCF_ERR_CONFIGURED;;
esac
active=0
timeout=`expr $OCF_RESKEY_timeout \* 1000 / $OCF_RESKEY_attempts`
cmd="$p_exe -r $OCF_RESKEY_attempts -t $timeout -B 1.0 $OCF_RESKEY_options $OCF_RESKEY_host_list"
output=`$cmd 2>&1`; rc=$?
active=`echo "$output" | grep "is alive" | wc -l`
case $rc in
0)
;;
1)
for h in `echo "$output" | grep "is unreachable" | awk '{print $1}'`; do
ping_conditional_log warn "$h is inactive"
done
;;
*)
ocf_log err "Unexpected result for '$cmd' $rc: `echo "$output" | tr '\n' ';'`"
;;
esac
return $active
}
ping_check() {
active=0
for host in $OCF_RESKEY_host_list; do
p_exe=ping
case `uname` in
Linux) p_args="-n -q -W $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts";;
Darwin) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";;
FreeBSD) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";;
*) ocf_log err "Unknown host type: `uname`"; exit $OCF_ERR_INSTALLED;;
esac
case $host in
*:*) p_exe=ping6
esac
p_out=`$p_exe $p_args $OCF_RESKEY_options $host 2>&1`; rc=$?
case $rc in
0) active=`expr $active + 1`;;
1) ping_conditional_log warn "$host is inactive: $p_out";;
*) ocf_log err "Unexpected result for '$p_exe $p_args $OCF_RESKEY_options $host' $rc: $p_out";;
esac
done
return $active
}
ping_update() {
if use_fping; then
fping_check
active=$?
else
ping_check
active=$?
fi
score=`expr $active \* $OCF_RESKEY_multiplier`
if [ "$__OCF_ACTION" = "start" ] ; then
attrd_updater -n $OCF_RESKEY_name -B $score -d $OCF_RESKEY_dampen $attrd_options
else
attrd_updater -n $OCF_RESKEY_name -v $score -d $OCF_RESKEY_dampen $attrd_options
fi
rc=$?
case $rc in
0) ping_conditional_log debug "Updated $OCF_RESKEY_name = $score" ;;
*) ocf_log warn "Could not update $OCF_RESKEY_name = $score: rc=$rc";;
esac
if [ $rc -ne 0 ]; then
return $rc
fi
if [ -n "$OCF_RESKEY_failure_score" ] && [ "$score" -lt "$OCF_RESKEY_failure_score" ]; then
ocf_log warn "$OCF_RESKEY_name is less than failure_score($OCF_RESKEY_failure_score)"
return 1
fi
return 0
}
use_fping() {
ocf_is_true "$OCF_RESKEY_use_fping" && have_binary fping;
}
# return values:
# 4 IPv4
# 6 IPv6
# 0 indefinite (i.e. hostname)
host_family() {
case $1 in
*[0-9].*[0-9].*[0-9].*[0-9]) return 4 ;;
*:*) return 6 ;;
*) return 0 ;;
esac
}
# return values same as host_family plus
# 99 ambiguous families
hosts_family() {
# For fping allow only same IP versions or hostnames
family=0
for host in $OCF_RESKEY_host_list; do
host_family $host
f=$?
if [ $family -ne 0 ] && [ $f -ne 0 ] && [ $f -ne $family ] ; then
family=99
break
fi
[ $f -ne 0 ] && family=$f
done
return $family
}
: ${OCF_RESKEY_name:="pingd"}
: ${OCF_RESKEY_dampen:="5s"}
: ${OCF_RESKEY_attempts:="3"}
: ${OCF_RESKEY_multiplier:="1"}
: ${OCF_RESKEY_debug:="false"}
: ${OCF_RESKEY_failure_score:="0"}
: ${OCF_RESKEY_use_fping:="1"}
: ${OCF_RESKEY_CRM_meta_timeout:="20000"}
: ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
integer=`echo ${OCF_RESKEY_timeout} | egrep -o '[0-9]*'`
case ${OCF_RESKEY_timeout} in
*[0-9]ms|*[0-9]msec) OCF_RESKEY_timeout=`expr $integer / 1000`;;
*[0-9]m|*[0-9]min) OCF_RESKEY_timeout=`expr $integer \* 60`;;
*[0-9]h|*[0-9]hr) OCF_RESKEY_timeout=`expr $integer \* 60 \* 60`;;
*) OCF_RESKEY_timeout=$integer;;
esac
if [ -z ${OCF_RESKEY_timeout} ]; then
if [ x"$OCF_RESKEY_host_list" != x ]; then
host_count=`echo $OCF_RESKEY_host_list | awk '{print NF}'`
OCF_RESKEY_timeout=`expr $OCF_RESKEY_CRM_meta_timeout / $host_count / $OCF_RESKEY_attempts`
OCF_RESKEY_timeout=`expr $OCF_RESKEY_timeout / 1100` # Convert to seconds and finish 10% early
else
OCF_RESKEY_timeout=5
fi
fi
if [ ${OCF_RESKEY_timeout} -lt 1 ]; then
OCF_RESKEY_timeout=5
elif [ ${OCF_RESKEY_timeout} -gt 1000 ]; then
# ping actually complains if this value is too high, 5 minutes is plenty
OCF_RESKEY_timeout=300
fi
if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
: ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/ping-${OCF_RESKEY_name}"}
else
: ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/ping-${OCF_RESOURCE_INSTANCE}"}
fi
# Check the debug option
case "${OCF_RESKEY_debug}" in
true|True|TRUE|1) OCF_RESKEY_debug=true;;
false|False|FALSE|0) OCF_RESKEY_debug=false;;
*)
ocf_log warn "Value for 'debug' is incorrect. Please specify 'true' or 'false' not: ${OCF_RESKEY_debug}"
OCF_RESKEY_debug=false
;;
esac
attrd_options='-q'
if [ ${OCF_RESKEY_debug} = "true" ]; then
attrd_options=''
fi
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) ping_start;;
stop) ping_stop;;
monitor) ping_monitor;;
validate-all) ping_validate;;
usage|help) ping_usage
exit $OCF_SUCCESS
;;
*) ping_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
diff --git a/extra/resources/pingd b/extra/resources/pingd
index 58e3d0888a..7649bd3607 100755
--- a/extra/resources/pingd
+++ b/extra/resources/pingd
@@ -1,202 +1,187 @@
#!/bin/sh
#
-#
-# pingd OCF Resource Agent
-# Records (in the CIB) the current number of ping nodes a
-# cluster node can connect to.
+# ocf:pacemaker:pingd resource agent
#
# Copyright 2006-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
-# 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.
+# This source code is licensed under the GNU General Public License version 2
+# (GPLv2) WITHOUT ANY WARRANTY.
#
-# 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.
+# Records (in the CIB) the current number of ping nodes a
+# cluster node can connect to.
#
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
. ${OCF_FUNCTIONS}
: ${__OCF_ACTION=$1}
: ${OCF_RESKEY_name:="pingd"}
: ${OCF_RESKEY_interval:="1"}
: ${OCF_RESKEY_CRM_meta_interval:=0}
upgrade1="This agent (ocf:pacemaker:pingd) has been replaced by the more reliable ocf:pacemaker:ping."
upgrade2="Attempting automated conversion, run 'crm ra info ocf:pacemaker:ping' for all configuration options"
upgrade3="You will need to remove the existing resource and replace it with one that uses 'ocf:pacemaker:ping' directly"
case $__OCF_ACTION in
start|monitor)
if [ "x" != "x$OCF_RESKEY_host_list" ]; then
ocf_log err "$upgrade1"
ocf_log err "$upgrade2"
ocf_log err "Automatic conversion to ocf:pacemaker:ping failed: no hosts were configured to check for connectivity"
ocf_log err "$upgrade3"
exit $OCF_ERR_ARGS
fi
recurring=`crm configure show $OCF_RESOURCE_INSTANCE | grep "op monitor.*interval=\"[1-9]" | sed s/.*interval=// | awk -F\" '{print $2}' | sed s/.*interval=// | awk -F\" '{print $2}' | sort | head -n 1`
if [ -z $recurring ]; then
ocf_log err "$upgrade1"
ocf_log err "$upgrade2"
ocf_log err "Automatic conversion to ocf:pacemaker:ping failed: no monitor operation configured"
ocf_log err "Without an explicit monitor operation for '$OCF_RESOURCE_INSTANCE', connectivity changes will not be noticed"
ocf_log err "Preventing startup to ensure the issue is addressed before it matters"
exit $OCF_ERR_ARGS
fi
if [ $OCF_RESKEY_CRM_meta_interval = 0 ]; then
ocf_log warn "$upgrade1"
ocf_log warn "$upgrade2"
if [ $recurring != $OCF_RESKEY_interval ]; then
ocf_log warn "Your monitor operation happens every $recurring, which means that the $OCF_RESKEY_name attribute will be updated with a different frequency than the previously configured ( $OCF_RESKEY_interval )"
ocf_log warn "Either change the monitor interval to match or, ideally, switch to the ocf:pacemaker:ping agent and avoid all this compatibility nonsense."
fi
fi
;;
meta-data)
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="pingd" version="1.0">
<version>1.0</version>
<longdesc lang="en">
This agent (ocf:pacemaker:pingd) has been replaced by the more reliable ocf:pacemaker:ping.
It records (in the CIB) the current number of ping nodes (specified in the 'host_list' parameter) a cluster node can connect to.
</longdesc>
<shortdesc lang="en">pingd resource agent</shortdesc>
<parameters>
<parameter name="pidfile" unique="0">
<longdesc lang="en">PID file</longdesc>
<shortdesc lang="en">PID file</shortdesc>
<content type="string" default="${HA_VARRUN%%1}/pingd-${OCF_RESOURCE_INSTANCE}" />
</parameter>
<parameter name="user" unique="0">
<longdesc lang="en">
The user we want to run pingd as
</longdesc>
<shortdesc lang="en">The user we want to run pingd as</shortdesc>
<content type="string" default="root" />
</parameter>
<parameter name="dampen" unique="0">
<longdesc lang="en">
The time to wait (dampening) further changes occur
</longdesc>
<shortdesc lang="en">Dampening interval</shortdesc>
<content type="integer" default="5s"/>
</parameter>
<parameter name="set" unique="0">
<longdesc lang="en">
The name of the instance_attributes set to place the value in. Rarely needs to be specified.
</longdesc>
<shortdesc lang="en">Set name</shortdesc>
<content type="string" default=""/>
</parameter>
<parameter name="name" unique="0">
<longdesc lang="en">
The name of the attributes to set. This is the name to be used in the constraints.
</longdesc>
<shortdesc lang="en">Attribute name</shortdesc>
<content type="string" default="pingd"/>
</parameter>
<parameter name="section" unique="0">
<longdesc lang="en">
The section place the value in. Rarely needs to be specified.
</longdesc>
<shortdesc lang="en">Section name</shortdesc>
<content type="string" default=""/>
</parameter>
<parameter name="multiplier" unique="0">
<longdesc lang="en">
The number by which to multiply the number of connected ping nodes by
</longdesc>
<shortdesc lang="en">Value multiplier</shortdesc>
<content type="integer" default=""/>
</parameter>
<parameter name="host_list" unique="0">
<longdesc lang="en">
The list of ping nodes to count. Defaults to all configured ping nodes. Rarely needs to be specified.
</longdesc>
<shortdesc lang="en">Host list</shortdesc>
<content type="string" default=""/>
</parameter>
<parameter name="interval" unique="0">
<longdesc lang="en">
How often, in seconds, to check for node liveliness
</longdesc>
<shortdesc lang="en">ping interval in seconds</shortdesc>
<content type="integer" default="1"/>
</parameter>
<parameter name="attempts" unique="0">
<longdesc lang="en">
Number of ping attempts, per host, before declaring it dead
</longdesc>
<shortdesc lang="en">no. of ping attempts</shortdesc>
<content type="integer" default="2"/>
</parameter>
<parameter name="timeout" unique="0">
<longdesc lang="en">
How long, in seconds, to wait before declaring a ping lost
</longdesc>
<shortdesc lang="en">ping timeout in seconds</shortdesc>
<content type="integer" default="2"/>
</parameter>
<parameter name="options" unique="0">
<longdesc lang="en">
A catch all for any other options that need to be passed to pingd.
</longdesc>
<shortdesc lang="en">Extra Options</shortdesc>
<content type="string" default=""/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="90s" />
<action name="stop" timeout="100s" />
<action name="monitor" depth="0" timeout="20s" interval="10s" start-delay="1m" />
<action name="meta-data" timeout="5s" />
<action name="validate-all" timeout="30s" />
</actions>
</resource-agent>
END
exit $OCF_SUCCESS
;;
esac
${OCF_ROOT}/resource.d/pacemaker/ping $1
exit $?
diff --git a/extra/resources/remote b/extra/resources/remote
index 2828b0aadc..aa85b9ab59 100755
--- a/extra/resources/remote
+++ b/extra/resources/remote
@@ -1,111 +1,111 @@
#!/bin/sh
#
-# ocf:pacmaker:remote OCF resource agent
-#
-# This script provides metadata for Pacemaker's internal remote agent.
-# Outside of acting as a placeholder so the agent can be indexed, and
-# providing metadata, this script should never be invoked. The actual
-# functionality behind the remote connection lives within Pacemaker's
-# controller daemon.
+# ocf:pacemaker:remote OCF resource agent
#
# Copyright 2013-2018 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# (GPLv2) WITHOUT ANY WARRANTY.
#
+# This script provides metadata for Pacemaker's internal remote agent.
+# Outside of acting as a placeholder so the agent can be indexed, and
+# providing metadata, this script should never be invoked. The actual
+# functionality behind the remote connection lives within Pacemaker's
+# controller daemon.
+#
#######################################################################
# 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="remote" version="0.1">
<version>1.0</version>
<shortdesc lang="en">remote resource agent</shortdesc>
<parameters>
<parameter name="server" unique="1">
<longdesc lang="en">
Server location to connect to. This can be an ip address or hostname.
</longdesc>
<shortdesc lang="en">Server location</shortdesc>
<content type="string"/>
</parameter>
<parameter name="port">
<longdesc lang="en">
tcp port to connect to.
</longdesc>
<shortdesc lang="en">tcp port</shortdesc>
<content type="string" default="3121"/>
</parameter>
<parameter name="reconnect_interval" unique="0">
<longdesc lang="en">
Interval in seconds at which Pacemaker will attempt to reconnect to a
remote node after an active connection to the remote node has been
severed. When this value is nonzero, Pacemaker will retry the connection
indefinitely, at the specified interval. As with any time-based actions,
this is not guaranteed to be checked more frequently than the value of
the cluster-recheck-interval cluster option.
</longdesc>
<shortdesc lang="en">reconnect interval</shortdesc>
<content type="string" default="0"/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="60s" />
<action name="stop" timeout="60s" />
<action name="reload" timeout="60s" />
<action name="monitor" timeout="30s" />
<action name="migrate_to" timeout="60s" />
<action name="migrate_from" timeout="60s" />
<action name="meta-data" timeout="5s" />
</actions>
</resource-agent>
END
}
#######################################################################
remote_usage() {
cat <<END
usage: $0 {meta-data}
Expects to have a fully populated OCF RA-compliant environment set.
END
}
remote_unsupported() {
ocf_log info "The ocf:pacemaker:remote agent should not be directly invoked except for meta-data action"
return $OCF_ERR_GENERIC
}
case $__OCF_ACTION in
meta-data) meta_data
exit $OCF_SUCCESS
;;
start) remote_unsupported;;
stop) remote_unsupported;;
monitor) remote_unsupported;;
migrate_to) remote_unsupported;;
migrate_from) remote_unsupported;;
reload) remote_unsupported;;
validate-all) remote_unsupported;;
usage|help) remote_usage
exit $OCF_SUCCESS
;;
*) remote_usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
rc=$?
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
exit $rc

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 5:01 PM (14 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1019023
Default Alt Text
(129 KB)

Event Timeline