diff --git a/extra/resources/ClusterMon.in b/extra/resources/ClusterMon.in
index cf6584f863..76489236b1 100755
--- a/extra/resources/ClusterMon.in
+++ b/extra/resources/ClusterMon.in
@@ -1,277 +1,276 @@
 #!@BASH_PATH@
 #
 # ocf:pacemaker:ClusterMon resource agent
 #
 # Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Br<E9>e
-# Later changes copyright 2008-2021 the Pacemaker project contributors
+# Later changes copyright 2008-2023 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.
 #
 
 # Starts crm_mon in background which logs cluster status as
 # html to the specified file.
 
 #######################################################################
 # Initialization:
 : ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"}
 . "${OCF_FUNCTIONS}"
 : ${__OCF_ACTION:="$1"}
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${OCF_RESKEY_user:=""}
 : ${OCF_RESKEY_pidfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid"}
 : ${OCF_RESKEY_update:="15000"}
 : ${OCF_RESKEY_extra_options:=""}
 : ${OCF_RESKEY_htmlfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html"}
 
 #######################################################################
 
 meta_data() {
     cat <<END
 <?xml version="1.0"?>
 <resource-agent name="ClusterMon" version="1.2">
 <version>1.1</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">
 <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">
 <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">
 <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-group="pidfile">
 <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-group="htmlfile" 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" />
+<action name="validate-all"  timeout="30s" depth="0" />
 </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 -ne 0 ]; then
         exit $OCF_ERR_GENERIC
     else
         exit $OCF_SUCCESS
     fi
 }
 
 ClusterMon_start() {
     if [ -n "$OCF_RESKEY_user" ]; then
         su - "$OCF_RESKEY_user" -c "$CMON_CMD"
     else
         eval $CMON_CMD
     fi
     ClusterMon_exit $?
 }
 
 ClusterMon_stop() {
     if [ -f "$OCF_RESKEY_pidfile" ]; then
         pid=$(cat "$OCF_RESKEY_pidfile")
         if [ -n "$pid" ]; then
             kill -s 9 $pid
             rm -f "$OCF_RESKEY_pidfile"
         fi
     fi
     ClusterMon_exit 0
 }
 
 ClusterMon_monitor() {
     local USERARG=""
     local header
     local pid
 
     if [ -f "$OCF_RESKEY_pidfile" ]; then
         pid=$(cat "$OCF_RESKEY_pidfile")
         if [ -n "$pid" ]; then
             if [ -n "$OCF_RESKEY_user" ]; then
                 USERARG="-u $OCF_RESKEY_user"
             fi
 
             # Use column header wide as command, to ensure it's shown in full
             header=$(echo $CMON_CMD | tr 'crmon, \t' 'xxxxxxxx')
 
             ps $USERARG -o "args=${header}" -p $pid 2>/dev/null | \
                 grep -qE "[c]rm_mon.*${OCF_RESKEY_pidfile}"
 
             case $? 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
 
     case "$OCF_RESKEY_extra_options" in
     *--output-as*)  ocf_log warn "You should not have specified the -output-as option, since OCF_RESKEY_htmlfile is set already!";;
     *--output-to*)  ocf_log warn "You should not have specified the -output-to option, since OCF_RESKEY_htmlfile is set already!";;
     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() {
-# Host-specific checks
-if [ "$OCF_CHECK_LEVEL" = "10" ]; then
+    # Host-specific checks
+    if [ "$OCF_CHECK_LEVEL" = "10" ]; then
 
-    # Existence of the user
+        # Existence of the user
         if [ -n "$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
+    fi
 
-fi
-
-# Pidfile better be an absolute path
+    # Pidfile should be an absolute path
     case "$OCF_RESKEY_pidfile" in
         /*) ;;
-        *) ocf_log warn "You should have pidfile($OCF_RESKEY_pidfile) of absolute path!" ;;
+        *) ocf_log warn "pidfile ($OCF_RESKEY_pidfile) is not an absolute path" ;;
     esac
 
-# Check the update interval
+    # 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
+    # Htmlfile should be an absolute path
     case "$OCF_RESKEY_htmlfile" in
         /*) ;;
-        *) ocf_log warn "You should have htmlfile($OCF_RESKEY_htmlfile) of absolute path!" ;;
+        *) ocf_log warn "htmlfile ($OCF_RESKEY_htmlfile) is not an absolute path" ;;
     esac
 
     echo "Validate OK"
     return $OCF_SUCCESS
 }
 
 if [ $# -ne 1 ]; then
     ClusterMon_usage
     exit $OCF_ERR_ARGS
 fi
 
 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 --output-as=html --output-to=\"$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 $?
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/Dummy b/extra/resources/Dummy
index 56584e5647..3afd8a234b 100755
--- a/extra/resources/Dummy
+++ b/extra/resources/Dummy
@@ -1,323 +1,323 @@
 #!/bin/sh
 #
 # ocf:pacemaker:Dummy resource agent
 #
 # Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Br<E9>e
-# Later changes copyright 2008-2021 the Pacemaker project contributors
+# Later changes copyright 2008-2023 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.
 
 #
 # The Dummy agent is intended primarily for testing, and has various options to
 # make actions intentionally fail or take a long time. It may also be used as a
 # template for resource agent writers, in which case:
 #
 # - Replace all occurrences of "dummy" and "Dummy" with your agent name.
 # - Update the meta-data appropriately for your agent, such as the description
 #   and supported options. Pay particular attention to the timeouts specified in
 #   the actions section; they should be meaningful for the kind of service the
 #   agent manages. They should be the minimum advised timeouts, but shouldn't
 #   try to cover _all_ possible instances. So, try to be neither overly generous
 #   nor too stingy, but moderate. The minimum timeouts should never be below 10
 #   seconds.
 # - Don't copy the stuff here that is just for testing, such as the
 #   sigterm_handler() or dump_env().
 # - You don't need the state file stuff here if you have a better way of
 #   determining whether your service is running. It's only useful for agents
 #   such as health agents that don't actually correspond to a running service.
 # - Implement the actions appropriately for your service. Your monitor action
 #   must differentiate correctly between running, not running, and failed (that
 #   is THREE states, not just yes/no). The migrate_to, migrate_from, and reload
 #   actions are optional and not appropriate to all services.
 #
 
 #######################################################################
 # Initialization:
 
 : ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"}
 . "${OCF_FUNCTIONS}"
 : ${__OCF_ACTION:="$1"}
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${OCF_RESKEY_fake:="dummy"}
 : ${OCF_RESKEY_op_sleep:=0}
 : ${OCF_RESKEY_CRM_meta_interval:=0}
 : ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
 : ${OCF_RESKEY_envfile:=""}
 : ${OCF_RESKEY_fail_start_on:=""}
 : ${OCF_RESKEY_migrate_source:=""}
 : ${OCF_RESKEY_migrate_target:=""}
 : ${OCF_RESKEY_envfile:=""}
 : ${OCF_RESKEY_state:=""}
 
 #######################################################################
 
 meta_data() {
     cat <<END
 <?xml version="1.0"?>
 <resource-agent name="Dummy" version="2.1">
 <version>1.1</version>
 
 <longdesc lang="en">
 This is a dummy OCF resource agent. It does absolutely nothing except keep track
 of whether it is running or not, and can be configured so that actions fail or
 take a long time. Its purpose is primarily for testing, and to serve as a
 template for resource agent writers.
 </longdesc>
 <shortdesc lang="en">Example stateless resource agent</shortdesc>
 
 <parameters>
 <parameter name="state" unique-group="state">
 <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" reloadable="1">
 <longdesc lang="en">
 Fake password field
 </longdesc>
 <shortdesc lang="en">Password</shortdesc>
 <content type="string" default="" />
 </parameter>
 
 <parameter name="fake" reloadable="1">
 <longdesc lang="en">
 Fake attribute that can be changed to cause an agent reload
 </longdesc>
 <shortdesc lang="en">Fake attribute that can be changed to cause an agent reload</shortdesc>
 <content type="string" default="dummy" />
 </parameter>
 
 <parameter name="op_sleep" reloadable="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" reloadable="1">
 <longdesc lang="en">
 Start, migrate_from, and reload-agent actions will return failure if running on
 the host specified here, but the resource will run 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" reloadable="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="reload-agent" timeout="20s" />
 <action name="migrate_to"   timeout="20s" />
 <action name="migrate_from" timeout="20s" />
-<action name="validate-all" timeout="20s" />
+<action name="validate-all" timeout="20s" depth="0" />
 <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|reload|reload-agent|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() {
     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
             ;;
 
             40)
             # monitor level that returns error code from state file
             rc=$(cat ${OCF_RESKEY_state})
             [ -n "$rc" ] && ocf_exit_reason "CPU ejected. Observed leaving the Kronosnet galaxy at $rc times the speed of light." && return $rc
             ;;
 
             *)
             ;;
         esac
         return $OCF_SUCCESS
     fi
     return $OCF_NOT_RUNNING
 }
 
 dummy_validate() {
     # If specified, is op_sleep an integer?
     case "$OCF_RESKEY_op_sleep" in
         ""|*[0-9]*) ;;
         *) return $OCF_ERR_CONFIGURED ;;
     esac
 
     # Host-specific checks
     if [ "$OCF_CHECK_LEVEL" = "10" ]; then
 
         # Is the state directory writable?
         state_dir=$(dirname "$OCF_RESKEY_state")
         [ -d "$state_dir" ] && [ -w "$state_dir" ] && [ -x "$state_dir" ]
         if [ $? -ne 0 ]; then
             return $OCF_ERR_ARGS
         fi
 
         # If specified, is the environment file directory writable?
         if [ -n "$OCF_RESKEY_envfile" ]; then
             envfile_dir=$(dirname "$OCF_RESKEY_envfile")
             [ -d "$envfile_dir" ] && [ -w "$envfile_dir" ] && [ -x "$envfile_dir" ]
             if [ $? -ne 0 ]; then
                 return $OCF_ERR_ARGS
             fi
         fi
 
     fi
     return $OCF_SUCCESS
 }
 
 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 debug "Reloading $OCF_RESOURCE_INSTANCE (service)"
                 exit $OCF_SUCCESS
                 ;;
 reload-agent)   ocf_log err "Reloading $OCF_RESOURCE_INSTANCE (agent)"
                 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
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/HealthCPU b/extra/resources/HealthCPU
index 64df4cfb3a..449f2704f9 100755
--- a/extra/resources/HealthCPU
+++ b/extra/resources/HealthCPU
@@ -1,212 +1,212 @@
 #!/bin/sh
 #
 # ocf:pacemaker:HealthCPU resource agent
 #
-# Copyright 2004-2022 the Pacemaker project contributors
+# Copyright 2004-2023 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"?>
 <resource-agent name="HealthCPU" version="1.1">
 <version>1.1</version>
 
 <longdesc lang="en">
 System 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-group="state">
 <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" reloadable="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" reloadable="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="reload-agent" timeout="20s" />
 <action name="meta-data"    timeout="5s" />
-<action name="validate-all"   timeout="10s" />
+<action name="validate-all"   timeout="10s" depth="0" />
 </actions>
 </resource-agent>
 END
 }
 
 #######################################################################
 
 healthcpu_usage() {
     cat <<END
 usage: $0 {start|stop|monitor|reload-agent|validate-all|meta-data}
 
 Expects to have a fully populated OCF RA-compliant environment set.
 END
 }
 
 healthcpu_start() {
     healthcpu_monitor
     if [ $? -eq $OCF_SUCCESS ]; then
         return $OCF_SUCCESS
     fi
     touch "${OCF_RESKEY_state}"
 }
 
 healthcpu_stop() {
     healthcpu_monitor
     if [ $? -eq $OCF_SUCCESS ]; then
         rm "${OCF_RESKEY_state}"
     fi
     return $OCF_SUCCESS
 }
 
 healthcpu_monitor() {
     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
 
     return $OCF_NOT_RUNNING
 }
 
 healthcpu_reload_agent() {
     # No action required
     :;
 }
 
 healthcpu_validate() {
     # If specified, is yellow_limit a non-negative integer?
     case "$OCF_RESKEY_yellow_limit" in
         0|[1-9]|[1-9][0-9]|100) ;;
         *) return $OCF_ERR_CONFIGURED ;;
     esac
 
     # If specified, is red_limit a non-negative integer?
     case "$OCF_RESKEY_red_limit" in
         0|[1-9]|[1-9][0-9]|100) ;;
         *) return $OCF_ERR_CONFIGURED ;;
     esac
 
     # Host-specific checks
     if [ "$OCF_CHECK_LEVEL" = "10" ]; then
 
         # Is the state directory writable?
         state_dir=$(dirname "$OCF_RESKEY_state")
         [ -d "$state_dir" ] && [ -w "$state_dir" ] && [ -x "$state_dir" ]
         if [ $? -ne 0 ]; then
             ocf_log err "Invalid location for 'state': $state_dir is not writable"
             return $OCF_ERR_ARGS
         fi
     fi
 
     return $OCF_SUCCESS
 }
 
 : ${OCF_RESKEY_CRM_meta_interval:=0}
 : ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
 
 if [ -z "$OCF_RESKEY_state" ]; then
     state="${HA_VARRUN%%/}/HealthCPU-${OCF_RESOURCE_INSTANCE}.state"
     if [ "${OCF_RESKEY_CRM_meta_globally_unique}" = "false" ]; then
         # Strip off the trailing clone marker
         OCF_RESKEY_state=$(echo $state | sed s/:[0-9][0-9]*\.state/.state/)
     else
         OCF_RESKEY_state="$state"
     fi
 fi
 
 if [ -z "${OCF_RESKEY_red_limit}" ] ; then
     OCF_RESKEY_red_limit=10
 fi
 
 if [ -z "${OCF_RESKEY_yellow_limit}" ] ; then
     OCF_RESKEY_yellow_limit=50
 fi
 
 case "$__OCF_ACTION" in
 meta-data)      meta_data
                 exit $OCF_SUCCESS
                 ;;
 start)          healthcpu_start;;
 stop)           healthcpu_stop;;
 monitor)        healthcpu_monitor;;
 reload-agent)   healthcpu_reload_agent;;
 validate-all)   healthcpu_validate;;
 usage|help)     healthcpu_usage
                 exit $OCF_SUCCESS
                 ;;
 *)              healthcpu_usage
                 exit $OCF_ERR_UNIMPLEMENTED
                 ;;
 esac
 rc=$?
 ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
 exit $rc
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/HealthIOWait b/extra/resources/HealthIOWait
index 5f1483ef74..3ce6e6d484 100755
--- a/extra/resources/HealthIOWait
+++ b/extra/resources/HealthIOWait
@@ -1,197 +1,197 @@
 #!/bin/sh
 #
 # ocf:pacemaker:HealthIOWait resource agent
 #
-# Copyright 2004-2021 the Pacemaker project contributors
+# Copyright 2004-2023 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"?>
 <resource-agent name="HealthIOWait" version="1.2">
 <version>1.1</version>
 
 <longdesc lang="en">
 System 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-group="state">
 <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">
 <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="integer" default="10"/>
 </parameter>
 
 <parameter name="red_limit">
 <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="integer" 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" />
+<action name="validate-all" timeout="10s" depth="0" />
 </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 [ $? -eq $OCF_SUCCESS ]; then
       return $OCF_SUCCESS
     fi
     touch "${OCF_RESKEY_state}"
 }
 
 agent_stop() {
     agent_monitor
     if [ $? -eq $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
 }
 
 is_integer() {
     case "$1" in
         ""|*[0-9]*) return 0 ;;
         *)          return 1 ;;
     esac
 }
 
 is_writable_dir() {
     dir=$(dirname "$1")
     [ -d "$dir" ] && [ -w "$dir" ] && [ -x "$dir" ]
 }
 
 agent_validate() {
 
     is_integer "$OCF_RESKEY_yellow_limit" && is_integer "$OCF_RESKEY_red_limit"
     if [ $? -ne 0 ]; then
         return $OCF_ERR_CONFIGURED
     fi
 
     if [ "$OCF_CHECK_LEVEL" = "10" ]; then
         is_writable_dir "$OCF_RESKEY_state"
         if [ $? -ne 0 ]; then
           return $OCF_ERR_ARGS
         fi
     fi
 
     return $OCF_SUCCESS
 }
 
 : ${OCF_RESKEY_CRM_meta_interval:=0}
 : ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
 
 if [ -z "$OCF_RESKEY_state" ]; 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 [ -z "${OCF_RESKEY_red_limit}" ] ; then
   OCF_RESKEY_red_limit=15
 fi
 
 if [ -z "${OCF_RESKEY_yellow_limit}" ] ; 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
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/HealthSMART.in b/extra/resources/HealthSMART.in
index 27572a2b22..d6d0508e5f 100755
--- a/extra/resources/HealthSMART.in
+++ b/extra/resources/HealthSMART.in
@@ -1,372 +1,372 @@
 #!@BASH_PATH@
 #
 # ocf:pacemaker:HealthSMART resource agent
 #
-# Copyright 2009-2022 the Pacemaker project contributors
+# Copyright 2009-2023 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.
 #
 
 #
 # 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"}
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${OCF_RESKEY_CRM_meta_interval:=0}
 : ${OCF_RESKEY_CRM_meta_globally_unique:="true"}
 : ${OCF_RESKEY_temp_warning:=""}
 : ${OCF_RESKEY_temp_lower_limit:=""}
 : ${OCF_RESKEY_temp_upper_limit:=""}
 : ${OCF_RESKEY_drives:="/dev/sda"}
 : ${OCF_RESKEY_devices:=""}
 : ${OCF_RESKEY_state:=""}
 : ${OCF_RESKEY_smartctl:="/usr/sbin/smartctl"}
 : ${OCF_RESKEY_dampen:="5s"}
 
 # Turn these into arrays so we can iterate them later.
 DRIVES=(${OCF_RESKEY_drives})
 DEVICES=(${OCF_RESKEY_devices})
 
 #######################################################################
 
 meta_data() {
     cat <<END
 <?xml version="1.0"?>
 <resource-agent name="HealthSMART" version="1.0">
 <version>1.1</version>
 
 <longdesc lang="en">
 System 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-group="state">
 <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" reloadable="1">
 <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" reloadable="1">
 <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" reloadable="1">
 <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" reloadable="1">
 <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" reloadable="1">
 <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>
 
 <parameter name="smartctl" reloadable="1">
 <longdesc lang="en">
 The path to the smartctl program, used for querying device health.
 </longdesc>
 <shortdesc lang="en">The path to the smartctl program</shortdesc>
 <content type="string" default="/usr/sbin/smartctl"/>
 </parameter>
 
 <parameter name="dampen" reloadable="1">
 <longdesc lang="en">
 The time to wait (dampening) for further changes to occur
 </longdesc>
 <shortdesc lang="en">Dampening interval</shortdesc>
 <content type="integer" default="5s"/>
 </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" />
+<action name="validate-all"   timeout="10s" depth="0" />
 <action name="reload-agent"   timeout="20s" />
 </actions>
 </resource-agent>
 END
 }
 
 #######################################################################
 
 check_temperature() {
 
     if [ $1 -lt ${lower_red_limit} ] ; then
         ocf_log info "Drive ${DRIVE} ${DEVICE} too cold: ${1} C"
         attrd_updater -n "#health-smart" -U "red" -d "${OCF_RESKEY_dampen}"
         return 1
     fi
 
     if [ $1 -gt ${upper_red_limit} ] ; then
         ocf_log info "Drive ${DRIVE} ${DEVICE} too hot: ${1} C"
         attrd_updater -n "#health-smart" -U "red" -d "${OCF_RESKEY_dampen}"
         return 1
     fi
 
     if [ $1 -lt ${lower_yellow_limit} ] ; then
         ocf_log info "Drive ${DRIVE} ${DEVICE} quite cold: ${1} C"
         attrd_updater -n "#health-smart" -U "yellow" -d "${OCF_RESKEY_dampen}"
         return 1
     fi
 
     if [ $1 -gt ${upper_yellow_limit} ] ; then
         ocf_log info "Drive ${DRIVE} ${DEVICE} quite hot: ${1} C"
         attrd_updater -n "#health-smart" -U "yellow" -d "${OCF_RESKEY_dampen}"
         return 1
     fi
 }
 
 common_checks() {
     # Each item in $OCF_RESKEY_drives must have a corresponding item in
     # $OCF_RESKEY_devices with the device type.  Alternately,
     # $OCF_RESKEY_devices can be empty.
     drives_len=${#DRIVES[@]}
     devices_len=${#DEVICES[@]}
 
     if [ "${drives_len}" -ne "${devices_len}" ] && [ "${devices_len}" -gt 0 ]; then
         ocf_log err "OCF_RESKEY_devices must be empty or the same length as OCF_RESKEY_drives."
         exit $OCF_ERR_ARGS
     fi
 
     # Each item in $OCF_RESKEY_drives must look like a device node.
     for d in "${DRIVES[@]}"; do
         if [[ "$d" != /dev/* ]]; then
             ocf_log err "Device in OCF_RESKEY_devices does not look like a device node: $d"
             exit $OCF_ERR_ARGS
         fi
     done
 }
 
 
 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}))
 
     for ndx in ${!DRIVES[*]}; do
         DRIVE=${DRIVES[$ndx]}
 
         if [ -n "${OCF_RESKEY_devices}" ]; then
             DEVICE=${DEVICES[$ndx]}
 
             "${OCF_RESKEY_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
         else
             "${OCF_RESKEY_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|reload-agent}
 
 Expects to have a fully populated OCF RA-compliant environment set.
 END
 }
 
 HealthSMART_start() {
     HealthSMART_monitor
     if [ $? -eq $OCF_SUCCESS ]; then
         return $OCF_SUCCESS
     fi
     touch "${OCF_RESKEY_state}"
 }
 
 HealthSMART_stop() {
     attrd_updater -D -n "#health-smart" -d "${OCF_RESKEY_dampen}"
 
     rm "${OCF_RESKEY_state}"
 
     if [ $? -eq 0 ]; then
         return $OCF_SUCCESS
     else
         return $OCF_ERR_GENERIC
     fi
 }
 
 HealthSMART_monitor() {
     common_checks
 
     # Test for presence of smartctl
     check_binary smartctl
 
     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
 
         for ndx in ${!DRIVES[*]}; do
             DRIVE=${DRIVES[$ndx]}
 
             if [ -n "${OCF_RESKEY_devices}" ]; then
                 DEVICE=${DEVICES[$ndx]}
 
                 # Check overall S.M.A.R.T. status
                 "${OCF_RESKEY_smartctl}" -d "${DEVICE}" -H ${DRIVE} | grep -q "SMART overall-health self-assessment test result: PASSED"
                 if [ $? -ne 0 ]; then
                     attrd_updater -n "#health-smart" -U "red" -d "${OCF_RESKEY_dampen}"
                     return $OCF_SUCCESS
                 fi
 
                 # Check drive temperature(s)
                 check_temperature "$("${OCF_RESKEY_smartctl}" -d "${DEVICE}" -A "${DRIVE}" | awk '/^194/ { print $10 }')"
                 if [ $? -ne 0 ]; then
                     return $OCF_SUCCESS
                 fi
             else
                 "${OCF_RESKEY_smartctl}" -H "${DRIVE}" | grep -q "SMART overall-health self-assessment test result: PASSED"
                 if [ $? -ne 0 ]; then
                     attrd_updater -n "#health-smart" -U "red" -d "${OCF_RESKEY_dampen}"
                     return $OCF_SUCCESS
                 fi
 
                 check_temperature "$("${OCF_RESKEY_smartctl}" -A "${DRIVE}" | awk '/^194/ { print $10 }')"
                 if [ $? -ne 0 ]; then
                     return $OCF_SUCCESS
                 fi
             fi
         done
 
         attrd_updater -n "#health-smart" -U "green" -d "${OCF_RESKEY_dampen}"
         return $OCF_SUCCESS
     fi
 
     return $OCF_NOT_RUNNING
 
 }
 
 HealthSMART_validate() {
     common_checks
 
     # Host-specific checks
     if [ "$OCF_CHECK_LEVEL" = "10" ]; then
         # Test for presence of smartctl
         check_binary smartctl
 
         init_smart
 
         # 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/$$"
     fi
 
     return $OCF_SUCCESS
 }
 
 HealthSMART_reload_agent() {
     return $OCF_SUCCESS
 }
 
 
 if [ -z "$OCF_RESKEY_state" ]; 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;;
     reload-agent) HealthSMART_reload_agent;;
     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
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/Stateful b/extra/resources/Stateful
index 2ebe6725f7..af25912ba9 100755
--- a/extra/resources/Stateful
+++ b/extra/resources/Stateful
@@ -1,267 +1,267 @@
 #!/bin/sh
 #
 # ocf:pacemaker:Stateful resource agent
 #
-# Copyright 2006-2021 the Pacemaker project contributors
+# Copyright 2006-2023 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"}
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${OCF_RESKEY_CRM_meta_interval:=0}
 : ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
 : ${OCF_RESKEY_notify_delay:=0}
 : ${OCF_RESKEY_envfile:=""}
 : ${OCF_RESKEY_state:=""}
 
 # Until we can assume the new name is available ...
 : ${OCF_RUNNING_PROMOTED:=$OCF_RUNNING_MASTER}
 
 SCORE_UNPROMOTED=5
 SCORE_PROMOTED=10
 
 #######################################################################
 
 meta_data() {
     cat <<END
 <?xml version="1.0"?>
 <resource-agent name="Stateful" version="1.2">
 <version>1.1</version>
 
 <longdesc lang="en">
 This is an example resource agent that implements Promoted and Unpromoted roles
 </longdesc>
 <shortdesc lang="en">Example stateful resource agent</shortdesc>
 
 <parameters>
 
 <parameter name="state" unique-group="state">
 <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" reloadable="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" reloadable="1">
 <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="Promoted"/>
 <action name="monitor" depth="0" timeout="20s" interval="11s" role="Unpromoted"/>
 <action name="promote" timeout="10s" />
 <action name="demote"  timeout="10s" />
 <action name="notify"  timeout="5s" />
 <action name="meta-data"  timeout="5s" />
 <action name="reload-agent"  timeout="10s" />
-<action name="validate-all"  timeout="30s" />
+<action name="validate-all"  timeout="30s" depth="0" />
 </actions>
 </resource-agent>
 END
     exit $OCF_SUCCESS
 }
 
 #######################################################################
 
 stateful_usage() {
     cat <<END
 Usage: $0 <action>
 
 where <action> is one of: meta-data validate-all start stop monitor
                           promote demote notify reload-agent
 
 This conforms to the OCF Resource Agent API version 1.1, and expects
 to have OCF-compliant environment variables provided.
 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 [ "$target" = "$state" ]; then
             return 0
         fi
 
     else
         if [ -z "$target" ]; then
             return 0
         fi
     fi
 
     return 1
 }
 
 dump_env() {
     if [ "${OCF_RESKEY_envfile}" != "" ]; then
             echo "### ${__OCF_ACTION} @ $(date) ###
 $(env | sort)
 ###" >> "${OCF_RESKEY_envfile}"
     fi
 }
 
 set_promotion_score() {
     "${HA_SBIN_DIR}/crm_attribute" --promotion -v "$1"
 }
 
 stateful_start() {
     stateful_check_state Promoted
     if [ $? -eq 0 ]; then
         # CRM Error - Should never happen
         return $OCF_RUNNING_PROMOTED
     fi
     stateful_update Unpromoted
     set_promotion_score $SCORE_UNPROMOTED
     return 0
 }
 
 stateful_demote() {
     stateful_check_state
     if [ $? -eq 0 ]; then
         # CRM Error - Should never happen
         return $OCF_NOT_RUNNING
     fi
     stateful_update Unpromoted
     set_promotion_score $SCORE_UNPROMOTED
     return 0
 }
 
 stateful_promote() {
     stateful_check_state
     if [ $? -eq 0 ]; then
         return $OCF_NOT_RUNNING
     fi
     stateful_update Promoted
     set_promotion_score $SCORE_PROMOTED
     return 0
 }
 
 stateful_stop() {
     "${HA_SBIN_DIR}/crm_attribute" --promotion -D
     stateful_check_state Promoted
     if [ $? -eq 0 ]; then
         # CRM Error - Should never happen
         return $OCF_RUNNING_PROMOTED
     fi
     if [ -f "${OCF_RESKEY_state}" ]; then
         rm "${OCF_RESKEY_state}"
     fi
     return 0
 }
 
 stateful_monitor() {
     # for testing
     if [ -f "${OCF_RESKEY_state}.rc" ]; then
         rc=$(cat "${OCF_RESKEY_state}.rc")
         ocf_exit_reason "$rc GB redirected to /dev/null"
         exit $rc
     fi
 
     stateful_check_state Promoted
     if [ $? -eq 0 ]; then
         if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then
             # Restore the promotion score during probes
             set_promotion_score $SCORE_PROMOTED
         fi
         return $OCF_RUNNING_PROMOTED
     fi
 
     stateful_check_state Unpromoted
     if [ $? -eq 0 ]; then
         if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then
             # Restore the promotion score during probes
             set_promotion_score $SCORE_UNPROMOTED
         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
 }
 
 stateful_reload_agent() {
     return $OCF_SUCCESS
 }
 
 if [ -z "$OCF_RESKEY_state" ]; 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;;
 reload-agent)   stateful_reload_agent;;
 usage|help)     stateful_usage $OCF_SUCCESS;;
 *)              stateful_usage $OCF_ERR_UNIMPLEMENTED;;
 esac
 
 exit $?
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/SysInfo.in b/extra/resources/SysInfo.in
index a57443d2bb..7765bf2feb 100755
--- a/extra/resources/SysInfo.in
+++ b/extra/resources/SysInfo.in
@@ -1,407 +1,407 @@
 #!@BASH_PATH@
 #
 # ocf:pacemaker:SysInfo resource agent
 #
 # Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Br<E9>e
-# Later changes copyright 2008-2021 the Pacemaker project contributors
+# Later changes copyright 2008-2023 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 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"}
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
 : ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/SysInfo-${OCF_RESOURCE_INSTANCE}"}
 : ${OCF_RESKEY_disk_unit:="G"}
 : ${OCF_RESKEY_clone:="0"}
 : ${OCF_RESKEY_disks:=""}
 : ${OCF_RESKEY_delay:=""}
 : ${OCF_RESKEY_min_disk_free:=""}
 
 #######################################################################
 
 meta_data() {
     cat <<END
 <?xml version="1.0"?>
 <resource-agent name="SysInfo" version="1.0">
 <version>1.1</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-group="pidfile">
 <longdesc lang="en">PID file</longdesc>
 <shortdesc lang="en">PID file</shortdesc>
 <content type="string" default="$OCF_RESKEY_pidfile" />
 </parameter>
 
 <parameter name="delay">
 <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" reloadable="1">
 <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" reloadable="1">
 <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="select" default="G">
   <option value="B" />
   <option value="b" />
   <option value="K" />
   <option value="k" />
   <option value="M" />  
   <option value="m" />
   <option value="G" />
   <option value="g" />
   <option value="T" />
   <option value="t" />
   <option value="P" />
   <option value="p" />
 </content>
 </parameter>
 
 <parameter name="min_disk_free" reloadable="1">
 <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="reload-agent" timeout="20s" />
 <action name="meta-data"  timeout="5s" />
-<action name="validate-all"  timeout="30s" />
+<action name="validate-all"  timeout="30s" depth="0" />
 </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() {
     local DISK_STATUS="green"
 
     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 [ -n "$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 [ -n "$cpu_type" ]; then
         UpdateStat cpu_info "$cpu_type"
     fi
 
     if [ -n "$cpu_speed" ]; then
         UpdateStat cpu_speed "$cpu_speed"
     fi
 
     if [ -n "$cpu_cores" ]; then
         UpdateStat cpu_cores "$cpu_cores"
     fi
 
     if [ -n "$cpu_load" ]; then
         UpdateStat cpu_load "$cpu_load"
     fi
 
     if [ -n "$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 [ -n "$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" ] && [ $disk_free -le $MIN_FREE ]; then
                 DISK_STATUS="red"
             fi
         fi
     done
     UpdateStat "#health_disk" "$DISK_STATUS"
 }
 
 SysInfo_megabytes() {
     # Size in megabytes
     echo $1 | awk '{ n = $0;
         sub( /[0-9]+(.[0-9]+)?/, "" );
         if ( $0 == "" ) { $0 = "G" }; # Do not change previous behavior `if ($0 == "G" || $0 == "") { n *= 1024 };`
         split( n, a, $0 );
         n = a[1];
         if ( /^[pP]i?[bB]?/ ) { n *= 1024 * 1024 * 1024 };
         if ( /^[tT]i?[bB]?/ ) { n *= 1024 * 1024 };
         if ( /^[gG]i?[bB]?/ ) { n *= 1024 };
         if ( /^[mM]i?[bB]?/ ) { n *= 1 };
         if ( /^[kK]i?[bB]?/ ) { n /= 1024 };
         if ( /^[bB]i?/ )      { n /= 1024 * 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 -ne 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|reload-agent|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 [ -z "$clone" ]; 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_reload_agent() {
     # No action required
     :;
 }
 
 SysInfo_validate() {
     # If specified, is min_disk_free a non-negative integer followed by a disk unit?
 
     pat="[1-9][0-9]*[KkBbMmGgTtPp]?"
     if [[ ! $OCF_RESKEY_min_disk_free =~ $pat ]]; then
         return $OCF_ERR_CONFIGURED
     fi
 
 }
 
 if [ $# -ne 1 ]; then
     SysInfo_usage
     exit $OCF_ERR_ARGS
 fi
 
 if [ -n "${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
                 ;;
 reload-agent)   SysInfo_reload_agent
                 ;;
 validate-all)   SysInfo_validate
                 ;;
 usage|help)     SysInfo_usage
                 exit $OCF_SUCCESS
                 ;;
 *)              SysInfo_usage
                 exit $OCF_ERR_UNIMPLEMENTED
                 ;;
 esac
 
 exit $?
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/attribute b/extra/resources/attribute
index 586cbcbce1..7d8d7c6ea0 100755
--- a/extra/resources/attribute
+++ b/extra/resources/attribute
@@ -1,240 +1,240 @@
 #!/bin/sh
 #
 # ocf:pacemaker:attribute resource agent
 #
-# Copyright 2016-2022 the Pacemaker project contributors
+# Copyright 2016-2023 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.
 #
 
 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"}
 
 # If the user did not set a value, use the default. If the user explicitly set
 # a value to the empty string, use that (-z "${V+x}" tests whether $V was set).
 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"?>
 <resource-agent name="attribute" version="1.2">
   <version>1.1</version>
   <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>
   <shortdesc lang="en">Manages a node attribute</shortdesc>
   <parameters>
 
     <parameter name="state" unique-group="state">
       <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-group="name">
       <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">
       <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">
       <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="validate-all" timeout="20s" depth="0" />
     <action name="meta-data"    timeout="5s" />
   </actions>
 </resource-agent>
 END
     return $OCF_SUCCESS
 }
 
 validate() {
     # Host-specific checks
     if [ "$OCF_CHECK_LEVEL" = "10" ]; then
         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
     fi
 
     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
 
     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: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/controld.in b/extra/resources/controld.in
index 55ced1de85..9053f8d11c 100644
--- a/extra/resources/controld.in
+++ b/extra/resources/controld.in
@@ -1,303 +1,303 @@
 #!/bin/sh
 #
 # ocf:pacemaker:controld resource agent
 #
-# Copyright 2008-2022 the Pacemaker project contributors
+# Copyright 2008-2023 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.
 
 #
 # Manages the DLM controld process
 #
 
 #######################################################################
 # Initialization:
 
 : ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"}
 . "${OCF_FUNCTIONS}"
 : ${__OCF_ACTION:="$1"}
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${OCF_RESKEY_CRM_meta_globally_unique:="false"}
 : ${OCF_RESKEY_allow_stonith_disabled:="false"}
 : ${OCF_RESKEY_sctp:="false"}
 : ${OCF_RESOURCE_INSTANCE:=""}
 
 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
 
 
 #######################################################################
 
 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"?>
 <resource-agent name="controld" version="1.3">
 <version>1.1</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">
 <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-group="daemon">
 <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" />
+<action name="validate-all"   timeout="30s" depth="0" />
 </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 @runstatedir@/cluster exists
     [ -d "@runstatedir@/cluster" ] || mkdir "@runstatedir@/cluster"
 
     # 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
 
     # If no-quorum-policy not set, or not set as freeze, give a warning
     crm_attribute --type=crm_config --name=no-quorum-policy --query|grep value=freeze >/dev/null 2>/dev/null
     if [ $? -ne 0 ]; then
         ocf_log warn "The DLM cluster best practice suggests to set the cluster property \"no-quorum-policy=freeze\""
     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 -eq $OCF_NOT_RUNNING ]; then
         return $OCF_SUCCESS
     fi
 
     killall -TERM "${OCF_RESKEY_daemon}"; rc=$?
 
     if [ $rc -ne 0 ]; then
         return $OCF_ERR_GENERIC
     fi
 
     rc=$OCF_SUCCESS
     while [ $rc -eq $OCF_SUCCESS ]; do
         controld_monitor; rc=$?
         sleep 1
     done
 
     if [ $rc -eq $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 '*' --output-as xml | grep -q "extended-status=\"pending\""; 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() {
     case "${OCF_RESKEY_CRM_meta_globally_unique}" in
         [Tt][Rr][Uu][Ee] | [Oo][Nn] | [Yy][Ee][Ss] | [Yy] | 1)
             msg="The globally-unique meta attribute must not be enabled for"
             msg="$msg $OCF_RESOURCE_INSTANCE"
             ocf_log err "$msg"
             exit $OCF_ERR_CONFIGURED
             ;;
     esac
 
     # Host-specific checks
     if [ "$OCF_CHECK_LEVEL" = "10" ]; then
         check_binary killall
         check_binary "${OCF_RESKEY_daemon}"
     fi
 
     return $OCF_SUCCESS
 }
 
 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
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80:
diff --git a/extra/resources/ifspeed.in b/extra/resources/ifspeed.in
index 4f3c334125..06310eed4d 100755
--- a/extra/resources/ifspeed.in
+++ b/extra/resources/ifspeed.in
@@ -1,551 +1,553 @@
 #!@BASH_PATH@
 #
 # ocf:pacemaker:ifspeed resource agent
 #
-# Copyright 2011-2022 the Pacemaker project contributors
+# Copyright 2011-2023 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.
 #
 
 #
 # Record speed of a network interface as a node attribute, based on the sum of
 # speeds of its active (up, link detected, not blocked) underlying interfaces.
 #
 # Originally based on ocf:pacemaker:ping agent
 #
 
 : ${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
 
 # Explicitly list all environment variables used, to make static analysis happy
 : ${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}}
 : ${OCF_RESKEY_iface:=""}
 : ${OCF_RESKEY_ip:=""}
 : ${OCF_RESKEY_debug:="false"}
 
 meta_data() {
         cat <<END
 <?xml version="1.0"?>
 <resource-agent name="ifspeed" version="1.1">
 <version>1.1</version>
 
 <longdesc lang="en">
 This agent's monitor action records the speed of a specified network interface
 as a node attribute. The attribute can be used in rules to prefer nodes based
 on network speeds.
 
 This agent can monitor physical interfaces, bonded interfaces, bridges, VLANs,
 or any combination thereof. For example:
 
 *) 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 agent tries to determine the network topology, and
 by default looks only on ports which are connected to an upstream switch. This
 can be overridden by 'bridge_ports' parameter. Active interfaces in this case
 are those in "forwarding" state.
 
 For balancing bonded interfaces, this agent uses 80% of the sum of the speeds of
 underlying "up" ports.
 
 For non-balancing bonded interfaces ("active-backup" and probably "broadcast"),
 only the speed of the currently active port is considered.
 </longdesc>
 <shortdesc lang="en">Network interface speed monitor</shortdesc>
 
 <parameters>
 
 <parameter name="name" unique-group="name">
 <longdesc lang="en">
 Name of the node attribute to set
 </longdesc>
 <shortdesc lang="en">Attribute name</shortdesc>
 <content type="string" default="${OCF_RESKEY_name_default}"/>
 </parameter>
 
 <parameter name="iface" unique-group="iface">
 <longdesc lang="en">
 If this is set, monitor this network interface. One of iface or ip must be set.
 </longdesc>
 <shortdesc lang="en">Network interface</shortdesc>
 <content type="string" default=""/>
 </parameter>
 
 <parameter name="ip" unique-group="ip">
 <longdesc lang="en">
 If this is set instead of iface, monitor the interface that holds this IP
 address. The address may be specified in dotted-quad notation for IPv4 (for
 example, 192.168.1.1) or hexadecimal notation for IPv6 (for example,
 2001:db8:DC28:0:0:FC57:D4C8:1FFF). One of iface or ip must be set.
 </longdesc>
 <shortdesc lang="en">IPv4 or IPv6 address</shortdesc>
 <content type="string" default="" />
 </parameter>
 
 <parameter name="bridge_ports" unique-group="iface">
 <longdesc lang="en">
 If set and iface is a bridge, consider these bridge ports (by default, 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">
 <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">
 <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">
 <longdesc lang="en">
 Log 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" />
+<action name="validate-all"  timeout="30s" depth="0" />
 </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}
 }
 
 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() {
     if [ -z "${OCF_RESKEY_iface}" ]; then
         if [ -z "${OCF_RESKEY_ip}" ]; then
             ocf_log err "Must specify either an interface name or valid IP address"
             ocf_exit_reason "no interface or IP address specified"
             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 "'${OCF_RESKEY_ip}' is not a valid IP"
                   exit $OCF_ERR_CONFIGURED
                 fi
             fi
         fi
     fi
+
+    # Host-specific checks
     if [ "$1" = "10" ]; then
         if [ "$(uname)" != "Linux" ] ; then
             ocf_log err "This resource agent works only on Linux"
             ocf_exit_reason "not Linux"
             exit $OCF_ERR_INSTALLED
         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 /usr/include/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
 
     # At least as of 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_ports() {
     local iface="$1"
     local ports
 
     read ports < "/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=\${ports}"
     else # Expect sub-shell
         echo ${ports}
     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_ports
 
     if ! iface_is_bond "${iface}" ; then
         echo 0
         return
     fi
 
     bond_get_ports "${iface}" bond_ports
 
     if bond_is_balancing "${iface}" ; then
         for port in ${bond_ports} ; do
             : $(( aggregate_speed += $( iface_get_speed "${port}" ) ))
         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 determine network interface name from IP address (${OCF_RESKEY_ip})"
             ocf_exit_reason "unable to determine interface name"
             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
 
 : ${ha_pseudo_resource_name:="ifspeed-${OCF_RESOURCE_INSTANCE}"}
 
 attrd_options=''
 if ocf_is_true "${OCF_RESKEY_debug}" ; then
     attrd_options='-VV'
 fi
 
 case "$__OCF_ACTION" in
     start)
         validate 10
         start
         ;;
     stop)
         validate 10
         stop
         ;;
     monitor)
         validate 10
         monitor
         ;;
     validate-all)
         validate "$OCF_CHECK_LEVEL"
         ;;
     *)
         usage
         exit $OCF_ERR_UNIMPLEMENTED
         ;;
 esac
 
 exit $?
 
 # vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: