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-Bre -# 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 < 1.1 This is a ClusterMon Resource Agent. It outputs current cluster status to the html. Runs crm_mon in the background, recording the cluster status to an HTML file The user we want to run crm_mon as The user we want to run crm_mon as How frequently should we update the cluster status (in milliseconds). For compatibility with old documentation, values less than 1000 will be treated as seconds. Update interval in milliseconds Additional options to pass to crm_mon. Eg. -n -r Extra options PID file location to ensure only one instance is running PID file Location to write HTML output to. HTML output - + END } ####################################################################### ClusterMon_usage() { cat </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-Bre -# 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 < 1.1 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. Example stateless resource agent Location to store the resource state in. State file Fake password field Password Fake attribute that can be changed to cause an agent reload Fake attribute that can be changed to cause an agent reload Number of seconds to sleep during operations. This can be used to test how the cluster reacts to operation timeouts. Operation sleep duration in seconds. 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. Report bogus start failure on specified host If this is set, the environment will be dumped to this file for every call. Environment dump file - + 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 <> "${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 < 1.1 System health agent that measures the CPU idling and updates the #health-cpu attribute. System health CPU usage Location to store the resource state in. State file 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%. Lower limit for yellow health attribute 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%. Lower limit for red health attribute - + END } ####################################################################### healthcpu_usage() { cat < 1.1 System health agent that measures the CPU iowait via top and updates the #health-iowait attribute. System health based on CPU iowait measurement Location to store the resource state in. State file 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%. Upper limit for yellow health attribute 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%. Upper limit for red health attribute - + END } ####################################################################### agent_usage() { cat < 1.1 System health agent that checks the S.M.A.R.T. status of the given drives and updates the #health-smart attribute. SMART health status Location to store the resource state in. State file The drive(s) to check as a SPACE separated list. Enter the full path to the device, e.g. "/dev/sda". Drives to check The device type(s) to assume for the drive(s) being tested as a SPACE separated list. Device types Lower limit of the temperature in deg C of the drive(s). Below this limit the status will be red. Lower limit for the red smart attribute 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. Upper limit for red smart attribute Number of deg C below/above the upper/lower temp limits at which point the status of #health-smart will change to yellow. Deg C below/above the upper limits for yellow smart attribute The path to the smartctl program, used for querying device health. The path to the smartctl program The time to wait (dampening) for further changes to occur Dampening interval - + 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 < 1.1 This is an example resource agent that implements Promoted and Unpromoted roles Example stateful resource agent Location to store the resource state in State file If this is set, the environment will be dumped to this file for every call. Environment dump file The notify action will sleep for this many seconds before returning, to simulate a long-running notify. Notify delay in seconds - + END exit $OCF_SUCCESS } ####################################################################### stateful_usage() { cat < where 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-Bre -# 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 < 1.1 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) SysInfo resource agent PID file PID file Interval to allow values to stabilize Dampening Delay 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' List of Filesytems/Paths to query for free disk space Unit to report disk free space in. Can be one of: B, K, M, G, T, P (case-insensitive) Unit to report disk free space in 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. minimum disk free space required - + 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 ' to the equivalent 'tail -'. 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 < "$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 < 1.1 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. Manages a node attribute Full path of a temporary file to store the resource state in State file Name of node attribute to manage Attribute name Value to use for node attribute when resource becomes active (empty string is discouraged, because monitor cannot distinguish it from a query error) Attribute value when active Value to use for node attribute when resource becomes inactive Attribute value when inactive - + 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 < 1.1 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. DLM Agent for cluster file systems Any additional options to start the dlm_controld service with DLM Options The daemon to start - supports gfs_controld and dlm_controld The daemon to start 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. Allow start-up even without STONITH/fencing - + END } ####################################################################### CONFIGFS_DIR="/sys/kernel/config" DLM_CONFIGFS_DIR="${CONFIGFS_DIR}/dlm" DLM_SYSFS_DIR="/sys/kernel/dlm" controld_usage() { cat <&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 < 1.1 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. Network interface speed monitor Name of the node attribute to set Attribute name If this is set, monitor this network interface. One of iface or ip must be set. Network interface 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. IPv4 or IPv6 address If set and iface is a bridge, consider these bridge ports (by default, all ports which have designated_bridge=root_id) Bridge ports Relative weight of 1Gbps in interface speed. Can be used to tune how big attribute value will be. Weight of 1Gbps The time to wait (dampening) for further changes to occur. Dampening interval Log more verbosely. Verbose logging - + END } usage() { cat <