diff --git a/extra/resources/ClusterMon.in b/extra/resources/ClusterMon.in index f33cfd4cef..2f1f8bc1c4 100755 --- a/extra/resources/ClusterMon.in +++ b/extra/resources/ClusterMon.in @@ -1,274 +1,272 @@ #!@BASH_PATH@ # +# ocf:pacemaker:ClusterMon resource agent # -# ClusterMon OCF RA. -# Starts crm_mon in background which logs cluster status as -# html to the specified file. +# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Bre +# Later changes copyright 2008-2019 the Pacemaker project contributors # -# Copyright 2004-2018 SUSE LINUX AG, Lars Marowsky-Brée -# All Rights Reserved. +# The version control history for this file may have further details. # -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. +# This source code is licensed under the GNU General Public License version 2 +# (GPLv2) WITHOUT ANY WARRANTY. # -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + +# Starts crm_mon in background which logs cluster status as +# html to the specified file. # # OCF instance parameters: -# OCF_RESKEY_user -# OCF_RESKEY_pidfile -# OCF_RESKEY_update -# OCF_RESKEY_extra_options -# OCF_RESKEY_htmlfile +# OCF_RESKEY_user +# OCF_RESKEY_pidfile +# OCF_RESKEY_update +# OCF_RESKEY_extra_options +# OCF_RESKEY_htmlfile ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { - cat < 1.0 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}" - rc=$? - case $rc in - 0) exit $OCF_SUCCESS;; - 1) exit $OCF_NOT_RUNNING;; - *) exit $OCF_ERR_GENERIC;; - esac - fi + 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 + 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!";; + i) ocf_log warn "You should not have specified the -i option, since OCF_RESKEY_update is set already!";; + h) ocf_log warn "You should not have specified the -h option, since OCF_RESKEY_htmlfile is set already!";; + p) ocf_log warn "You should not have specified the -p option, since OCF_RESKEY_pidfile is set already!";; *) return $OCF_ERR_ARGS;; esac -done +done if [ $? -ne 0 ]; then return $OCF_ERR_ARGS fi # We should have eaten all options at this stage shift $(($OPTIND -1)) if [ $# -gt 0 ]; then false else true fi } ClusterMon_validate() { # Existence of the user - if [ ! -z $OCF_RESKEY_user ]; then - getent passwd "$OCF_RESKEY_user" >/dev/null - if [ $? -eq 0 ]; then - : Yes, user exists. We can further check his permission on crm_mon if necessary - else - ocf_log err "The user $OCF_RESKEY_user does not exist!" - exit $OCF_ERR_ARGS - fi + 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 # Pidfile better be an absolute path - case $OCF_RESKEY_pidfile in - /*) ;; - *) ocf_log warn "You should have pidfile($OCF_RESKEY_pidfile) of absolute path!" ;; + case "$OCF_RESKEY_pidfile" in + /*) ;; + *) ocf_log warn "You should have pidfile($OCF_RESKEY_pidfile) of absolute path!" ;; esac # Check the update interval if ocf_is_decimal "$OCF_RESKEY_update" && [ $OCF_RESKEY_update -gt 0 ]; then - : + : else - ocf_log err "Invalid update interval $OCF_RESKEY_update. It should be positive integer!" - exit $OCF_ERR_ARGS + 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 + ocf_log err "Invalid options $OCF_RESKEY_extra_options!" + exit $OCF_ERR_ARGS fi # Htmlfile better be an absolute path - case $OCF_RESKEY_htmlfile in - /*) ;; - *) ocf_log warn "You should have htmlfile($OCF_RESKEY_htmlfile) of absolute path!" ;; + case "$OCF_RESKEY_htmlfile" in + /*) ;; + *) ocf_log warn "You should have htmlfile($OCF_RESKEY_htmlfile) of absolute path!" ;; esac - echo "Validate OK" return $OCF_SUCCESS } if [ $# -ne 1 ]; then ClusterMon_usage exit $OCF_ERR_ARGS fi : ${OCF_RESKEY_update:="15000"} : ${OCF_RESKEY_pidfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid"} : ${OCF_RESKEY_htmlfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html"} if [ ${OCF_RESKEY_update} -ge 1000 ]; then - OCF_RESKEY_update=$(( $OCF_RESKEY_update / 1000 )) + OCF_RESKEY_update=$(( $OCF_RESKEY_update / 1000 )) fi -CMON_CMD="${HA_SBIN_DIR}/crm_mon -p $OCF_RESKEY_pidfile -d -i $OCF_RESKEY_update $OCF_RESKEY_extra_options -h $OCF_RESKEY_htmlfile" - -case $__OCF_ACTION in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -start) ClusterMon_start - ;; -stop) ClusterMon_stop - ;; -monitor) ClusterMon_monitor - ;; -validate-all) ClusterMon_validate - ;; -usage|help) ClusterMon_usage - exit $OCF_SUCCESS - ;; -*) ClusterMon_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; +CMON_CMD="${HA_SBIN_DIR}/crm_mon -p \"$OCF_RESKEY_pidfile\" -d -i $OCF_RESKEY_update $OCF_RESKEY_extra_options -h \"$OCF_RESKEY_htmlfile\"" + +case "$__OCF_ACTION" in +meta-data) meta_data + exit $OCF_SUCCESS + ;; +start) ClusterMon_start + ;; +stop) ClusterMon_stop + ;; +monitor) ClusterMon_monitor + ;; +validate-all) ClusterMon_validate + ;; +usage|help) ClusterMon_usage + exit $OCF_SUCCESS + ;; +*) ClusterMon_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac exit $? + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/Dummy b/extra/resources/Dummy index 75e4cf5b23..4d791ffd6b 100755 --- a/extra/resources/Dummy +++ b/extra/resources/Dummy @@ -1,274 +1,287 @@ #!/bin/sh # -# Dummy OCF RA. Does nothing but wait a few seconds, can be -# configured to fail occassionally. +# ocf:pacemaker:Dummy resource agent # -# Copyright 2004-2018 SUSE LINUX AG, Lars Marowsky-Brée -# All Rights Reserved. +# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Bre +# Later changes copyright 2008-2019 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} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { cat < 1.0 -This is a Dummy Resource Agent. It does absolutely nothing except -keep track of whether its running or not. -Its purpose in life is for testing and to serve as a template for RA writers. - -NB: Please pay attention to the timeouts specified in the actions -section below. They should be meaningful for the kind of resource -the agent manages. They should be the minimum advised timeouts, -but they shouldn't/cannot cover _all_ possible resource -instances. So, try to be neither overly generous nor too stingy, -but moderate. The minimum timeouts should never be below 10 seconds. +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 a reload Fake attribute that can be changed to cause a 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 actions will return failure if running on the host specified here, but the resource will start successfully anyway (future monitor calls will find it running). This can be used to test on-fail=ignore. 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} + rm "${OCF_RESKEY_state}" fi rm -f "${VERIFY_SERIALIZED_FILE}" return $OCF_SUCCESS } dummy_monitor() { - # Monitor _MUST!_ differentiate correctly between running - # (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING). - # That is THREE states, not just yes/no. - if [ $OCF_RESKEY_op_sleep -ne 0 ]; then if [ "$1" = "" ] && [ -f "${VERIFY_SERIALIZED_FILE}" ]; then # two monitor ops have occurred at the same time. # This verifies a condition in pacemaker-execd regression tests. ocf_log err "$VERIFY_SERIALIZED_FILE exists already" ocf_exit_reason "alternate universe collision" return $OCF_ERR_GENERIC fi touch "${VERIFY_SERIALIZED_FILE}" sleep ${OCF_RESKEY_op_sleep} rm "${VERIFY_SERIALIZED_FILE}" fi - + if [ -f "${OCF_RESKEY_state}" ]; then # Multiple monitor levels are defined to support various tests case "$OCF_CHECK_LEVEL" in 10) # monitor level with delay, useful for testing timeouts sleep 30 ;; 20) # monitor level that fails intermittently n=$(expr "$(dd if=/dev/urandom bs=1 count=1 2>/dev/null | od | head -1 | cut -f2 -d' ')" % 5) if [ $n -eq 1 ]; then ocf_exit_reason "smoke detected near CPU fan" return $OCF_ERR_GENERIC fi ;; 30) # monitor level that always fails ocf_exit_reason "hyperdrive quota reached" return $OCF_ERR_GENERIC ;; *) ;; esac return $OCF_SUCCESS fi return $OCF_NOT_RUNNING } dummy_validate() { - - # Is the state directory writable? - state_dir=`dirname "$OCF_RESKEY_state"` - touch "$state_dir/$$" + # 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 - rm "$state_dir/$$" - return $OCF_SUCCESS } -: ${OCF_RESKEY_fake=dummy} -: ${OCF_RESKEY_op_sleep=0} -: ${OCF_RESKEY_CRM_meta_interval=0} +: ${OCF_RESKEY_fake:="dummy"} +: ${OCF_RESKEY_op_sleep:=0} +: ${OCF_RESKEY_CRM_meta_interval:=0} : ${OCF_RESKEY_CRM_meta_globally_unique:="false"} if [ -z "$OCF_RESKEY_state" ]; then OCF_RESKEY_state="${HA_VARRUN%%/}/Dummy-${OCF_RESOURCE_INSTANCE}.state" - if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then + 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/` + 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 +case "$__OCF_ACTION" in meta-data) meta_data exit $OCF_SUCCESS ;; start) dummy_start;; stop) dummy_stop;; monitor) dummy_monitor;; migrate_to) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}." dummy_stop ;; migrate_from) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}." dummy_start ;; reload) ocf_log err "Reloading..." dummy_start ;; validate-all) dummy_validate;; usage|help) dummy_usage exit $OCF_SUCCESS ;; *) dummy_usage exit $OCF_ERR_UNIMPLEMENTED ;; esac rc=$? ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" exit $rc + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/HealthCPU b/extra/resources/HealthCPU index d860a718bb..55e81ae4b0 100755 --- a/extra/resources/HealthCPU +++ b/extra/resources/HealthCPU @@ -1,197 +1,188 @@ #!/bin/sh # -# HealthCPU OCF RA -# Measures CPUs idling and writes #health-cpu status into the CIB +# ocf:pacemaker:HealthCPU resource agent # -# Copyright 2004-2018 the Pacemaker project contributors +# Copyright 2004-2019 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 +# TODO: Enter default values +# Error handling in getting uptime # ################################## ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { - cat < 1.0 -Systhem health agent that measures the CPU idling and updates the #health-cpu attribute. +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 } ####################################################################### -dummy_usage() { - cat < 1.0 -Systhem health agent that measures the CPU iowait via top and updates the #health-iowait attribute. +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.0 -Systhem health agent that checks the S.M.A.R.T. status of the given drives and +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 END } ####################################################################### check_temperature() { - + if [ $1 -lt ${lower_red_limit} ] ; then - ocf_log info "Drive ${DRIVE} ${DEVICE} too cold: ${1} C" - $ATTRDUP -n "#health-smart" -U "red" -d "5s" - return 1 + ocf_log info "Drive ${DRIVE} ${DEVICE} too cold: ${1} C" + "$ATTRDUP" -n "#health-smart" -U "red" -d "5s" + return 1 fi if [ $1 -gt ${upper_red_limit} ] ; then - ocf_log info "Drive ${DRIVE} ${DEVICE} too hot: ${1} C" - $ATTRDUP -n "#health-smart" -U "red" -d "5s" - return 1 + ocf_log info "Drive ${DRIVE} ${DEVICE} too hot: ${1} C" + "$ATTRDUP" -n "#health-smart" -U "red" -d "5s" + return 1 fi - + if [ $1 -lt ${lower_yellow_limit} ] ; then - ocf_log info "Drive ${DRIVE} ${DEVICE} quite cold: ${1} C" - $ATTRDUP -n "#health-smart" -U "yellow" -d "5s" - return 1 + ocf_log info "Drive ${DRIVE} ${DEVICE} quite cold: ${1} C" + "$ATTRDUP" -n "#health-smart" -U "yellow" -d "5s" + return 1 fi - + if [ $1 -gt ${upper_yellow_limit} ] ; then - ocf_log info "Drive ${DRIVE} ${DEVICE} quite hot: ${1} C" - $ATTRDUP -n "#health-smart" -U "yellow" -d "5s" - return 1 + ocf_log info "Drive ${DRIVE} ${DEVICE} quite hot: ${1} C" + "$ATTRDUP" -n "#health-smart" -U "yellow" -d "5s" + return 1 fi } init_smart() { #Set temperature defaults - if [ -z ${OCF_RESKEY_temp_warning} ]; then - yellow_threshold=5 + 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 + 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 + if [ -z "${OCF_RESKEY_temp_upper_limit}" ] ; then upper_red_limit=60 else upper_red_limit=${OCF_RESKEY_temp_upper_limit} fi upper_yellow_limit=$((${upper_red_limit}-${yellow_threshold})) #Set disk defaults if [ -z "${OCF_RESKEY_drives}" ] ; then DRIVES="/dev/sda" else DRIVES=${OCF_RESKEY_drives} fi #Test for presence of smartctl - if [ ! -x $SMARTCTL ] ; then + if [ ! -x "$SMARTCTL" ] ; then ocf_log err "${SMARTCTL} not installed." exit $OCF_ERR_INSTALLED fi for DRIVE in $DRIVES; do - if [ "${OCF_RESKEY_devices}" ]; then - for DEVICE in ${OCF_RESKEY_devices}; do - $SMARTCTL -d $DEVICE -i ${DRIVE} | grep -q "SMART support is: Enabled" - if [ $? -ne "0" ] ; then - ocf_log err "S.M.A.R.T. not enabled for drive "${DRIVE} - exit $OCF_ERR_INSTALLED - fi - done - else - $SMARTCTL -i ${DRIVE} | grep -q "SMART support is: Enabled" - if [ $? -ne "0" ] ; then - ocf_log err "S.M.A.R.T. not enabled for drive "${DRIVE} - exit $OCF_ERR_INSTALLED - fi - fi + if [ -n "${OCF_RESKEY_devices}" ]; then + for DEVICE in ${OCF_RESKEY_devices}; do + "$SMARTCTL" -d "$DEVICE" -i "${DRIVE}" | grep -q "SMART support is: Enabled" + if [ $? -ne 0 ] ; then + ocf_log err "S.M.A.R.T. not enabled for drive "${DRIVE} + exit $OCF_ERR_INSTALLED + fi + done + else + "$SMARTCTL" -i "${DRIVE}" | grep -q "SMART support is: Enabled" + if [ $? -ne 0 ] ; then + ocf_log err "S.M.A.R.T. not enabled for drive "${DRIVE} + exit $OCF_ERR_INSTALLED + fi + fi done } HealthSMART_usage() { cat < 1.0 This is an example resource agent that implements two states 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 + exit $OCF_SUCCESS } ####################################################################### stateful_usage() { - cat < ${OCF_RESKEY_state} + echo $1 > "${OCF_RESKEY_state}" } stateful_check_state() { - target=$1 - if [ -f ${OCF_RESKEY_state} ]; then - state=`cat ${OCF_RESKEY_state}` - if [ "x$target" = "x$state" ]; then - return 0 - fi + target="$1" + if [ -f "${OCF_RESKEY_state}" ]; then + state=$(cat "${OCF_RESKEY_state}") + if [ "$target" = "$state" ]; then + return 0 + fi else - if [ "x$target" = "x" ]; then - return 0 - fi + 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_master_score() { + "${HA_SBIN_DIR}/crm_master" -l reboot -v "$1" +} + stateful_start() { stateful_check_state master - if [ $? = 0 ]; then - # CRM Error - Should never happen - return $OCF_RUNNING_MASTER + if [ $? -eq 0 ]; then + # CRM Error - Should never happen + return $OCF_RUNNING_MASTER fi stateful_update slave - $CRM_MASTER -v ${slave_score} + set_master_score "${slave_score}" return 0 } stateful_demote() { - stateful_check_state - if [ $? = 0 ]; then - # CRM Error - Should never happen - return $OCF_NOT_RUNNING + stateful_check_state + if [ $? -eq 0 ]; then + # CRM Error - Should never happen + return $OCF_NOT_RUNNING fi stateful_update slave - $CRM_MASTER -v ${slave_score} + set_master_score "${slave_score}" return 0 } stateful_promote() { - stateful_check_state - if [ $? = 0 ]; then - return $OCF_NOT_RUNNING + stateful_check_state + if [ $? -eq 0 ]; then + return $OCF_NOT_RUNNING fi stateful_update master - $CRM_MASTER -v ${master_score} + set_master_score "${master_score}" return 0 } stateful_stop() { - $CRM_MASTER -D + "${HA_SBIN_DIR}/crm_master" -l reboot -D stateful_check_state master - if [ $? = 0 ]; then - # CRM Error - Should never happen - return $OCF_RUNNING_MASTER + if [ $? -eq 0 ]; then + # CRM Error - Should never happen + return $OCF_RUNNING_MASTER fi - if [ -f ${OCF_RESKEY_state} ]; then - rm ${OCF_RESKEY_state} + if [ -f "${OCF_RESKEY_state}" ]; then + rm "${OCF_RESKEY_state}" fi return 0 } stateful_monitor() { stateful_check_state "master" - if [ $? = 0 ]; then - if [ $OCF_RESKEY_CRM_meta_interval = 0 ]; then - # Restore the master setting during probes - $CRM_MASTER -v ${master_score} - fi - return $OCF_RUNNING_MASTER + if [ $? -eq 0 ]; then + if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then + # Restore the master setting during probes + set_master_score "${master_score}" + fi + return $OCF_RUNNING_MASTER fi stateful_check_state "slave" - if [ $? = 0 ]; then - if [ $OCF_RESKEY_CRM_meta_interval = 0 ]; then - # Restore the master setting during probes - $CRM_MASTER -v ${slave_score} - fi - return $OCF_SUCCESS + if [ $? -eq 0 ]; then + if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then + # Restore the master setting during probes + set_master_score "${slave_score}" + fi + return $OCF_SUCCESS fi - if [ -f ${OCF_RESKEY_state} ]; then - echo "File '${OCF_RESKEY_state}' exists but contains unexpected contents" - cat ${OCF_RESKEY_state} - return $OCF_ERR_GENERIC + 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 + exit $OCF_SUCCESS } -: ${slave_score=5} -: ${master_score=10} +: ${slave_score:=5} +: ${master_score:=10} -: ${OCF_RESKEY_CRM_meta_interval=0} -: ${OCF_RESKEY_notify_delay=0} +: ${OCF_RESKEY_CRM_meta_interval:=0} +: ${OCF_RESKEY_notify_delay:=0} : ${OCF_RESKEY_CRM_meta_globally_unique:="false"} -if [ "x$OCF_RESKEY_state" = "x" ]; then - if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then - state="${HA_VARRUN%%/}/Stateful-${OCF_RESOURCE_INSTANCE}.state" - - # Strip off the trailing clone marker - OCF_RESKEY_state=`echo $state | sed s/:[0-9][0-9]*\.state/.state/` - else - OCF_RESKEY_state="${HA_VARRUN%%/}/Stateful-${OCF_RESOURCE_INSTANCE}.state" +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;; +case "$__OCF_ACTION" in +meta-data) meta_data;; +start) stateful_start;; +promote) stateful_promote;; +demote) stateful_demote;; notify) stateful_notify ;; -stop) stateful_stop;; -monitor) stateful_monitor;; -validate-all) stateful_validate;; -usage|help) stateful_usage $OCF_SUCCESS;; -*) stateful_usage $OCF_ERR_UNIMPLEMENTED;; +stop) stateful_stop;; +monitor) stateful_monitor;; +validate-all) stateful_validate;; +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 34eb848581..bc96f45d78 100755 --- a/extra/resources/SysInfo.in +++ b/extra/resources/SysInfo.in @@ -1,382 +1,370 @@ #!@BASH_PATH@ # +# ocf:pacemaker:SysInfo resource agent # -# SysInfo OCF Resource Agent -# It records (in the CIB) various attributes of a node +# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Bre +# Later changes copyright 2008-2019 the Pacemaker project contributors # -# Copyright 2004-2018 SUSE LINUX AG, Lars Marowsky-Brée -# All Rights Reserved. +# The version control history for this file may have further details. # -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. +# This source code is licensed under the GNU General Public License version 2 +# (GPLv2) WITHOUT ANY WARRANTY. # -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. + # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# This agent records (in the CIB) various attributes of a node # ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { - cat < 1.0 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 + 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" + "${HA_SBIN_DIR}/attrd_updater" ${OCF_RESKEY_delay} -S status -n $name -B "$value" + else + "${HA_SBIN_DIR}/attrd_updater" ${OCF_RESKEY_delay} -S status -n $name -v "$value" fi } SysInfoStats() { - - UpdateStat arch "`uname -m`" - UpdateStat os "`uname -s`-`uname -r`" - - case `uname -s` in - "Darwin") - mem=`top -l 1 | grep Mem: | awk '{print $10}'` - mem_used=`top -l 1 | grep Mem: | awk '{print $8}'` - mem=`SysInfo_mem_units $mem` - mem_used=`SysInfo_mem_units $mem_used` - mem_total=`expr $mem_used + $mem` - cpu_type=`system_profiler SPHardwareDataType | awk -F': ' '/^CPU Type/ {print $2; exit}'` - cpu_speed=`system_profiler SPHardwareDataType | awk -F': ' '/^CPU Speed/ {print $2; exit}'` - cpu_cores=`system_profiler SPHardwareDataType | awk -F': ' '/^Number Of/ {print $2; exit}'` - cpu_load=`uptime | awk '{ print $10 }'` - ;; - "FreeBSD") - cpu_type=`sysctl -in hw.model` - cpu_speed=`sysctl -in dev.cpu.0.freq` - cpu_cores=`sysctl -in hw.ncpu` - cpu_load=`sysctl -in vm.loadavg | awk '{ print $4 }'` - - free_pages=`sysctl -in vm.stats.vm.v_free_count` - page_count=`sysctl -in vm.stats.vm.v_page_count` - page_size=`sysctl -in vm.stats.vm.v_page_size` - - mem=`expr $free_pages \* $page_size / 1024 / 1024`M - mem_total=`expr $page_count \* $page_size / 1024 / 1024`M - ;; - "Linux") - if [ -f /proc/cpuinfo ]; then - cpu_type=`awk -F': ' '/model name/ {print $2; exit}' /proc/cpuinfo` - cpu_speed=`awk -F': ' '/bogomips/ {print $2; exit}' /proc/cpuinfo` - cpu_cores=`grep "^processor" /proc/cpuinfo | wc -l` - fi - cpu_load=`uptime | awk '{ print $10 }'` - - if [ -f /proc/meminfo ]; then - # meminfo results are in kB - mem=`grep "SwapFree" /proc/meminfo | awk '{print $2"k"}'` - if [ ! -z $mem ]; then - UpdateStat free_swap "$(SysInfo_mem_units "$mem")" - fi - mem=`grep "Inactive" /proc/meminfo | awk '{print $2"k"}'` - mem_total=`grep "MemTotal" /proc/meminfo | awk '{print $2"k"}'` - else - mem=`top -n 1 | grep Mem: | awk '{print $7}'` - fi - ;; - *) + 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 [ x != x"$cpu_type" ]; then - UpdateStat cpu_info "$cpu_type" + if [ -n "$cpu_type" ]; then + UpdateStat cpu_info "$cpu_type" fi - if [ x != x"$cpu_speed" ]; then - UpdateStat cpu_speed "$cpu_speed" + if [ -n "$cpu_speed" ]; then + UpdateStat cpu_speed "$cpu_speed" fi - if [ x != x"$cpu_cores" ]; then - UpdateStat cpu_cores "$cpu_cores" + if [ -n "$cpu_cores" ]; then + UpdateStat cpu_cores "$cpu_cores" fi - if [ x != x"$cpu_load" ]; then - UpdateStat cpu_load "$cpu_load" + if [ -n "$cpu_load" ]; then + UpdateStat cpu_load "$cpu_load" fi - if [ ! -z "$mem" ]; then + if [ -n "$mem" ]; then # Massage the memory values - UpdateStat ram_total "$(SysInfo_mem_units "$mem_total")" - UpdateStat ram_free "$(SysInfo_mem_units "$mem")" + 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 -'. + # '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 [ x != x"$disk_free" ]; then - disk_label=`echo $disk | sed -e 's#^/$#root#;s#^/*##;s#/#_#g'` - disk_free=`SysInfo_hdd_units $disk_free` - UpdateStat ${disk_label}_free $disk_free - if [ -n "$MIN_FREE" ]; then - if [ $disk_free -le $MIN_FREE ]; then - UpdateStat "#health_disk" "red" - else - UpdateStat "#health_disk" "green" - fi - fi - fi + 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]+)?/, ""); - split(n, a, $0); + sub(/[0-9]+(.[0-9]+)?/, ""); + split(n, a, $0); n=a[1]; if ($0 == "G" || $0 == "") { n *= 1024 }; if (/^kB?/) { n /= 1024 }; printf "%d\n", n }' # Intentionally round to an integer } SysInfo_mem_units() { - mem=$1 + mem="$1" - if [ -z $1 ]; then - return + if [ -z "$1" ]; then + return fi mem=$(SysInfo_megabytes "$1") # Round to the next multiple of 50 r=$(($mem % 50)) - if [ $r != 0 ]; then - mem=$(($mem + 50 - $r)) + if [ $r -ne 0 ]; then + mem=$(($mem + 50 - $r)) fi - echo $mem + 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));; + 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 + echo $OCF_RESKEY_clone > "$OCF_RESKEY_pidfile" SysInfoStats exit $OCF_SUCCESS } SysInfo_stop() { - rm $OCF_RESKEY_pidfile + rm "$OCF_RESKEY_pidfile" exit $OCF_SUCCESS } SysInfo_monitor() { - if [ -f $OCF_RESKEY_pidfile ]; then - clone=`cat $OCF_RESKEY_pidfile` + if [ -f "$OCF_RESKEY_pidfile" ]; then + clone=$(cat "$OCF_RESKEY_pidfile") fi - if [ x$clone = x ]; then - rm $OCF_RESKEY_pidfile - exit $OCF_NOT_RUNNING + if [ -z "$clone" ]; then + rm "$OCF_RESKEY_pidfile" + exit $OCF_NOT_RUNNING - elif [ $clone = $OCF_RESKEY_clone ]; then - SysInfoStats - exit $OCF_SUCCESS + 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 + SysInfoStats + exit $OCF_SUCCESS fi exit $OCF_NOT_RUNNING } SysInfo_validate() { return $OCF_SUCCESS } if [ $# -ne 1 ]; then SysInfo_usage exit $OCF_ERR_ARGS fi : ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/SysInfo-${OCF_RESOURCE_INSTANCE}"} : ${OCF_RESKEY_disk_unit:="G"} : ${OCF_RESKEY_clone:="0"} -if [ x != x${OCF_RESKEY_delay} ]; then +if [ -n "${OCF_RESKEY_delay}" ]; then OCF_RESKEY_delay="-d ${OCF_RESKEY_delay}" -else +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` + ocf_is_decimal "$OCF_RESKEY_min_disk_free" && + OCF_RESKEY_min_disk_free="$OCF_RESKEY_min_disk_free$OCF_RESKEY_disk_unit" + MIN_FREE=$(SysInfo_hdd_units $OCF_RESKEY_min_disk_free) fi -case $__OCF_ACTION in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -start) SysInfo_start - ;; -stop) SysInfo_stop - ;; -monitor) SysInfo_monitor - ;; -validate-all) SysInfo_validate - ;; -usage|help) SysInfo_usage - exit $OCF_SUCCESS - ;; -*) SysInfo_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; +case "$__OCF_ACTION" in +meta-data) meta_data + exit $OCF_SUCCESS + ;; +start) SysInfo_start + ;; +stop) SysInfo_stop + ;; +monitor) SysInfo_monitor + ;; +validate-all) SysInfo_validate + ;; +usage|help) SysInfo_usage + exit $OCF_SUCCESS + ;; +*) SysInfo_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac exit $? + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/SystemHealth b/extra/resources/SystemHealth index a7785c2267..480fa79c10 100755 --- a/extra/resources/SystemHealth +++ b/extra/resources/SystemHealth @@ -1,253 +1,239 @@ #!/bin/sh # -# SystemHealth OCF RA. +# ocf:pacemaker:SystemHealth resource agent # -# Copyright 2009-2018 the Pacemaker project contributors +# Copyright 2009-2019 the Pacemaker project contributors # # The version control history for this file may have further details. # -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# This source code is licensed under the GNU General Public License version 2 +# (GPLv2) WITHOUT ANY WARRANTY. # ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { - cat < 1.0 This is a SystemHealth Resource Agent. It is used to monitor the health of a system via IPMI. SystemHealth resource agent - - - - - - + + + + + + END } ####################################################################### SystemHealth_usage() { - cat < /dev/null 2>&1 RC=$? - if [ $RC != 0 ]; then - ocf_log err "servicelog_notify not found!" - return $OCF_ERR_INSTALLED + if [ $RC -ne 0 ]; then + ocf_log err "servicelog_notify not found!" + return $OCF_ERR_INSTALLED fi which ipmiservicelogd > /dev/null 2>&1 RC=$? - if [ $RC != 0 ]; then - ocf_log err "ipmiservicelogd not found!" - return $OCF_ERR_INSTALLED + if [ $RC -ne 0 ]; then + ocf_log err "ipmiservicelogd not found!" + return $OCF_ERR_INSTALLED fi - test -x $OCF_RESKEY_program + test -x "$OCF_RESKEY_program" RC=$? - if [ $RC != 0 ]; then - ocf_log err "$OCF_RESKEY_program not found!" - return $OCF_ERR_INSTALLED + if [ $RC -ne 0 ]; then + ocf_log err "$OCF_RESKEY_program not found!" + return $OCF_ERR_INSTALLED fi } SystemHealth_start() { SystemHealth_monitor RC=$? - if [ $RC = $OCF_ERR_GENERIC ]; then - return $OCF_ERR_GENERIC - elif [ $RC = $OCF_SUCCESS ]; then - ocf_log warn "starting an already started SystemHealth" - return $OCF_SUCCESS + if [ $RC -eq $OCF_ERR_GENERIC ]; then + return $OCF_ERR_GENERIC + elif [ $RC -eq $OCF_SUCCESS ]; then + ocf_log warn "starting an already started SystemHealth" + return $OCF_SUCCESS fi service ipmi start > /dev/null 2>&1 RC=$? - if [ $RC != 0 ]; then - ocf_log err "Could not start service IPMI!" - return $OCF_ERR_GENERIC + if [ $RC -ne 0 ]; then + ocf_log err "Could not start service IPMI!" + return $OCF_ERR_GENERIC fi ipmiservicelogd smi 0 > /dev/null 2>&1 & RC=$? - if [ $RC != 0 ]; then - ocf_log err "Could not start ipmiservicelogd!" - return $OCF_ERR_GENERIC + if [ $RC -ne 0 ]; then + ocf_log err "Could not start ipmiservicelogd!" + return $OCF_ERR_GENERIC fi servicelog_notify --add --type=EVENT --command="$OCF_RESKEY_program" --method=num_arg --match='type=4' > /dev/null 2>&1 RC=$? - if [ $RC != 0 ]; then - ocf_log err "servicelog_notify register handler failed!" - return $OCF_ERR_GENERIC + if [ $RC -ne 0 ]; then + ocf_log err "servicelog_notify register handler failed!" + return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } SystemHealth_stop() { SystemHealth_monitor RC=$? - if [ $RC = $OCF_ERR_GENERIC ]; then - return $OCF_ERR_GENERIC - elif [ $RC = $OCF_SUCCESS ]; then - killall ipmiservicelogd - RC1=$? - - if [ $RC1 != 0 ]; then - ocf_log err "Could not stop ipmiservicelogd!" - fi - - servicelog_notify --remove --command="$OCF_RESKEY_program" > /dev/null 2>&1 - RC2=$? - - if [ $RC2 != 0 ]; then - ocf_log err "servicelog_notify remove handler failed!" - fi - - if [ $RC1 -eq 0 ] && [ $RC2 -eq 0 ]; then - return $OCF_SUCCESS - else - return $OCF_ERR_GENERIC - fi - elif [ $RC = $OCF_NOT_RUNNING ]; then - ocf_log warn "stopping an already stopped SystemHealth" - return $OCF_SUCCESS + if [ $RC -eq $OCF_ERR_GENERIC ]; then + return $OCF_ERR_GENERIC + elif [ $RC -eq $OCF_SUCCESS ]; then + killall ipmiservicelogd + RC1=$? + + if [ $RC1 -ne 0 ]; then + ocf_log err "Could not stop ipmiservicelogd!" + fi + + servicelog_notify --remove --command="$OCF_RESKEY_program" > /dev/null 2>&1 + RC2=$? + + if [ $RC2 -ne 0 ]; then + ocf_log err "servicelog_notify remove handler failed!" + fi + + if [ $RC1 -eq 0 ] && [ $RC2 -eq 0 ]; then + return $OCF_SUCCESS + else + return $OCF_ERR_GENERIC + fi + elif [ $RC -eq $OCF_NOT_RUNNING ]; then + ocf_log warn "stopping an already stopped SystemHealth" + return $OCF_SUCCESS else - ocf_log err "SystemHealth_stop: should not be here!" - return $OCF_ERR_GENERIC + ocf_log err "SystemHealth_stop: should not be here!" + return $OCF_ERR_GENERIC fi } SystemHealth_monitor() { # Monitor _MUST!_ differentiate correctly between running # (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING). # That is THREE states, not just yes/no. if [ ! -f /var/run/ipmiservicelogd.pid0 ]; then - ocf_log debug "ipmiservicelogd is not running!" - return $OCF_NOT_RUNNING + ocf_log debug "ipmiservicelogd is not running!" + return $OCF_NOT_RUNNING fi ps -p "$(cat /var/run/ipmiservicelogd.pid0)" >/dev/null 2>&1 RC=$? - if [ $RC != 0 ]; then - ocf_log debug "ipmiservicelogd's pid `cat /var/run/ipmiservicelogd.pid0` is not running!" + if [ $RC -ne 0 ]; then + ocf_log debug "ipmiservicelogd's pid $(cat /var/run/ipmiservicelogd.pid0) is not running!" - rm /var/run/ipmiservicelogd.pid0 + rm /var/run/ipmiservicelogd.pid0 - return $OCF_ERR_GENERIC + return $OCF_ERR_GENERIC fi servicelog_notify --list --command="$OCF_RESKEY_program" > /dev/null 2>&1 RC=$? - if [ $RC = 0 ]; then - return $OCF_SUCCESS + if [ $RC -eq 0 ]; then + return $OCF_SUCCESS else - return $OCF_NOT_RUNNING + return $OCF_NOT_RUNNING fi } SystemHealth_validate() { - + SystemHealth_check_tools RC=$? - if [ $RC != 0 ]; then - return $RC + if [ $RC -ne 0 ]; then + return $RC fi return $OCF_SUCCESS } -: ${OCF_RESKEY_program=/usr/sbin/notifyServicelogEvent} +: ${OCF_RESKEY_program:=/usr/sbin/notifyServicelogEvent} case $__OCF_ACTION in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -usage|help) SystemHealth_usage - exit $OCF_SUCCESS - ;; +meta-data) meta_data + exit $OCF_SUCCESS + ;; +usage|help) SystemHealth_usage + exit $OCF_SUCCESS + ;; esac SystemHealth_check_tools RC=$? -if [ $RC != 0 ]; then - case $__OCF_ACTION in - stop) exit $OCF_SUCCESS;; - *) exit $RC;; - esac +if [ $RC -ne 0 ]; then + case "$__OCF_ACTION" in + stop) exit $OCF_SUCCESS;; + *) exit $RC;; + esac fi -case $__OCF_ACTION in -start) SystemHealth_start;; -stop) SystemHealth_stop;; -monitor) SystemHealth_monitor;; -reload) ocf_log info "Reloading..." - SystemHealth_start - ;; -validate-all) ;; -*) SystemHealth_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; +case "$__OCF_ACTION" in +start) SystemHealth_start;; +stop) SystemHealth_stop;; +monitor) SystemHealth_monitor;; +reload) ocf_log info "Reloading..." + SystemHealth_start + ;; +validate-all) ;; +*) SystemHealth_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac rc=$? ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" exit $rc + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/attribute b/extra/resources/attribute index d8b392cd01..8b3ed80acd 100755 --- a/extra/resources/attribute +++ b/extra/resources/attribute @@ -1,235 +1,236 @@ #!/bin/sh # # ocf:pacemaker:attribute resource agent # -# Copyright 2016-2018 the Pacemaker project contributors +# Copyright 2016-2019 the Pacemaker project contributors # # The version control history for this file may have further details. # -# This source code is licensed under GNU General Public License version 2 or -# later (GPLv2+) WITHOUT ANY WARRANTY. +# This source code is licensed under the GNU General Public License version 2 +# or later (GPLv2+) WITHOUT ANY WARRANTY. # USAGE="Usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data} Expects to have a fully populated OCF RA-compliant environment set." # Load OCF helper functions -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${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 +if [ "${OCF_RESKEY_CRM_meta_globally_unique}" = "false" ]; then # Strip off any trailing clone marker (note + is not portable in sed) DEFAULT_STATE_FILE=$(echo "$DEFAULT_STATE_FILE" | sed s/:[0-9][0-9]*\.state/.state/) fi DEFAULT_ATTR_NAME="opa-${OCF_RESOURCE_INSTANCE}" DEFAULT_ACTIVE_VALUE="1" DEFAULT_INACTIVE_VALUE="0" : ${OCF_RESKEY_state:="$DEFAULT_STATE_FILE"} : ${OCF_RESKEY_name:="$DEFAULT_ATTR_NAME"} -# Values may be empty string -if [ -z ${OCF_RESKEY_active_value+x} ]; then +# 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 +if [ -z "${OCF_RESKEY_inactive_value+x}" ]; then OCF_RESKEY_inactive_value="$DEFAULT_INACTIVE_VALUE" fi usage() { USAGE_RC=$1 cat < 1.0 Manages a node attribute 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. 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() { if [ "$OCF_RESKEY_active_value" = "$OCF_RESKEY_inactive_value" ]; then ocf_exit_reason "active value '%s' must be different from inactive value '%s'" \ "$OCF_RESKEY_active_value" "$OCF_RESKEY_inactive_value" return $OCF_ERR_CONFIGURED fi VALIDATE_DIR=$(dirname "${OCF_RESKEY_state}") if [ ! -d "$VALIDATE_DIR" ]; then ocf_exit_reason "state file '$OCF_RESKEY_state' does not have a valid directory" return $OCF_ERR_PERM fi if [ ! -w "$VALIDATE_DIR" ] || [ ! -x "$VALIDATE_DIR" ]; then ocf_exit_reason "insufficient privileges on directory of state file '$OCF_RESKEY_state'" return $OCF_ERR_PERM fi return $OCF_SUCCESS } get_attribute() { GET_LINE=$(attrd_updater -n "$OCF_RESKEY_name" -Q 2>/dev/null) if [ $? -ne 0 ]; then echo "" else echo "$GET_LINE" | sed -e "s/.* value=\"\(.*\)\"$/\1/" fi } set_attribute() { attrd_updater -n "$OCF_RESKEY_name" -U "$1" 2>/dev/null # TODO if above call is async, loop until get_attribute returns expected value } check_attribute() { CHECK_VALUE=$(get_attribute) CHECK_REASON="" if [ ! -f "$OCF_RESKEY_state" ]; then if [ "$CHECK_VALUE" != "" ] && [ "$CHECK_VALUE" != "$OCF_RESKEY_inactive_value" ]; then CHECK_REASON="Node attribute $OCF_RESKEY_name='$CHECK_VALUE' differs from expected value '$OCF_RESKEY_inactive_value'" return $OCF_ERR_GENERIC fi return $OCF_NOT_RUNNING fi if [ "$CHECK_VALUE" != "$OCF_RESKEY_active_value" ]; then CHECK_REASON="Node attribute $OCF_RESKEY_name='$CHECK_VALUE' differs from expected value '$OCF_RESKEY_active_value'" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } monitor() { check_attribute MONITOR_RC=$? if [ $MONITOR_RC -eq $OCF_ERR_GENERIC ]; then ocf_exit_reason "$CHECK_REASON" fi return $MONITOR_RC } start() { check_attribute if [ $? -eq $OCF_SUCCESS ]; then return $OCF_SUCCESS fi touch "${OCF_RESKEY_state}" 2>/dev/null if [ $? -ne 0 ]; then ocf_exit_reason "Unable to manage state file $OCF_RESKEY_state" return $OCF_ERR_GENERIC fi set_attribute "${OCF_RESKEY_active_value}" if [ $? -ne 0 ]; then rm -f "${OCF_RESKEY_state}" ocf_exit_reason "Unable to set node attribute $OCF_RESKEY_name='$OCF_RESKEY_active_value'" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } stop() { check_attribute if [ $? -eq $OCF_NOT_RUNNING ]; then return $OCF_SUCCESS fi rm -f ${OCF_RESKEY_state} set_attribute "${OCF_RESKEY_inactive_value}" if [ $? -ne 0 ]; then ocf_exit_reason "Unable to set node attribute $OCF_RESKEY_name='$OCF_RESKEY_inactive_value'" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } case $__OCF_ACTION in meta-data) meta_data ;; start) start ;; stop) stop ;; monitor) monitor ;; # We don't do anything special for live migration, but we support it so that # other resources that live migrate can depend on this one. migrate_to) stop ;; migrate_from) start ;; reload) start ;; validate-all) validate ;; usage|help) usage $OCF_SUCCESS ;; *) usage $OCF_ERR_UNIMPLEMENTED ;; esac exit $? -# vim: expandtab:tabstop=4:softtabstop=4:shiftwidth=4:textwidth=80 +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/controld b/extra/resources/controld index 5f8b0beee5..ea74e80699 100755 --- a/extra/resources/controld +++ b/extra/resources/controld @@ -1,300 +1,288 @@ #!/bin/sh # -# OCF resource agent for managing the DLM controld process +# ocf:pacemaker:controld resource agent # -# Copyright 2008-2018 the Pacemaker project contributors +# Copyright 2008-2019 the Pacemaker project contributors # # The version control history for this file may have further details. -# All Rights Reserved. # -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. +# This source code is licensed under the GNU General Public License version 2 +# (GPLv2) WITHOUT ANY WARRANTY. + # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# Manages the DLM controld process # ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### if [ -e "$OCF_ROOT/resource.d/heartbeat/controld" ]; then ocf_log info "Using heartbeat controld agent" - $OCF_ROOT/resource.d/heartbeat/controld $1 + "$OCF_ROOT/resource.d/heartbeat/controld" "$1" exit $? fi meta_data() { cat < 1.0 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) + CUL_TMP=$(ls "$DLM_SYSFS_DIR" 2>&1) if [ $? -eq 0 ]; then if [ -n "$CUL_TMP" ]; then ocf_log err "Uncontrolled lockspace exists, system must reboot. Executing suicide fencing" stonith_admin --reboot="$(crm_node -n)" --tag controld exit $OCF_ERR_GENERIC fi fi } controld_start() { controld_monitor; rc=$? case $rc in $OCF_SUCCESS) return $OCF_SUCCESS;; $OCF_NOT_RUNNING) ;; *) return $OCF_ERR_GENERIC;; esac # Ensure configfs is mounted if [ ! -e "$CONFIGFS_DIR" ]; then modprobe configfs if [ ! -e "$CONFIGFS_DIR" ]; then ocf_log err "$CONFIGFS_DIR not available" return $OCF_ERR_INSTALLED fi fi mount -t configfs | grep " $CONFIGFS_DIR " >/dev/null 2>/dev/null if [ $? -ne 0 ]; then mount -t configfs none "$CONFIGFS_DIR" fi # Ensure DLM is available if [ ! -e "$DLM_CONFIGFS_DIR" ]; then modprobe dlm if [ ! -e "$DLM_CONFIGFS_DIR" ]; then ocf_log err "$DLM_CONFIGFS_DIR not available" return $OCF_ERR_INSTALLED fi fi if ! ocf_is_true "$OCF_RESKEY_allow_stonith_disabled" && \ - ! ocf_is_true "`crm_attribute --type=crm_config --name=stonith-enabled --query --quiet --default=true`"; then + ! ocf_is_true "$(crm_attribute --type=crm_config --name=stonith-enabled --query --quiet --default=true)"; then ocf_log err "The cluster property stonith-enabled may not be deactivated to use the DLM" return $OCF_ERR_CONFIGURED fi - ${OCF_RESKEY_daemon} $OCF_RESKEY_args + "${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) + $OCF_NOT_RUNNING) return $OCF_NOT_RUNNING ;; - *) + *) return $OCF_ERR_GENERIC ;; esac ocf_log debug "Waiting for ${OCF_RESKEY_daemon} to be ready" done } controld_stop() { controld_monitor; rc=$? - if [ $rc = $OCF_NOT_RUNNING ]; then + if [ $rc -eq $OCF_NOT_RUNNING ]; then return $OCF_SUCCESS fi - killall -TERM ${OCF_RESKEY_daemon}; rc=$? + killall -TERM "${OCF_RESKEY_daemon}"; rc=$? - if [ $rc != 0 ]; then + if [ $rc -ne 0 ]; then return $OCF_ERR_GENERIC fi rc=$OCF_SUCCESS - while [ $rc = $OCF_SUCCESS ]; do + while [ $rc -eq $OCF_SUCCESS ]; do controld_monitor; rc=$? sleep 1 done - if [ $rc = $OCF_NOT_RUNNING ]; then + 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() { check_binary killall - check_binary ${OCF_RESKEY_daemon} + check_binary "${OCF_RESKEY_daemon}" - case ${OCF_RESKEY_CRM_meta_globally_unique} in - yes|Yes|true|True|1) + case "${OCF_RESKEY_CRM_meta_globally_unique}" in + yes|Yes|true|True|1) ocf_log err "$OCF_RESOURCE_INSTANCE must be configured with the globally_unique=false meta attribute" exit $OCF_ERR_CONFIGURED ;; esac [ -d /var/run/cluster ] || mkdir /var/run/cluster return $OCF_SUCCESS } -: ${OCF_RESKEY_sctp=false} +: ${OCF_RESKEY_sctp:="false"} : ${OCF_RESKEY_CRM_meta_globally_unique:="false"} case "$OCF_RESOURCE_INSTANCE" in - *[gG][fF][sS]*) + *[gG][fF][sS]*) : ${OCF_RESKEY_args=-g 0} - : ${OCF_RESKEY_daemon=gfs_controld} + : ${OCF_RESKEY_daemon:=gfs_controld} ;; *[dD][lL][mM]*) : ${OCF_RESKEY_args=-s 0} - : ${OCF_RESKEY_daemon=dlm_controld} + : ${OCF_RESKEY_daemon:=dlm_controld} ;; *) : ${OCF_RESKEY_args=-s 0} - : ${OCF_RESKEY_daemon=dlm_controld} + : ${OCF_RESKEY_daemon:=dlm_controld} esac -case $__OCF_ACTION in +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 676578e978..4d8f93e1a9 100755 --- a/extra/resources/ifspeed.in +++ b/extra/resources/ifspeed.in @@ -1,540 +1,550 @@ #!@BASH_PATH@ +# +# ocf:pacemaker:ifspeed resource agent +# +# Copyright 2011-2019 the Pacemaker project contributors +# +# The version control history for this file may have further details. +# +# This source code is licensed under the GNU General Public License version 2 +# or later (GPLv2+) WITHOUT ANY WARRANTY. +# + # # OCF resource agent which monitors state of network interface and records it # as a node attribute in the CIB based on the sum of speeds of its active (up, # link detected, not blocked) underlying interfaces. # -# Copyright 2011-2018 the Pacemaker project contributors -# -# The version control history for this file may have further details. # Partially based on 'ping' RA by Andrew Beekhof # # Change on 2017 by Tomer Azran : # Add "ip" parameter to detect network interface name by ip address: # http://lists.clusterlabs.org/pipermail/users/2017-August/006224.html # # OCF instance parameters: # OCF_RESKEY_name: name of attribute to set in CIB # OCF_RESKEY_ip ip address to check # OCF_RESKEY_iface: network interface to monitor # OCF_RESKEY_bridge_ports: if not null and OCF_RESKEY_iface is a bridge, list of # bridge ports to consider. -# Default is all ports which have designated_bridge=root_id +# Default is all ports which have designated_bridge=root_id # OCF_RESKEY_weight_base: Relative weight of 1Gbps. This can be used to tune # value of resulting CIB attribute. # # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} +: ${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_SUCCESS:=0} -: ${__OCF_ACTION=$1} +: ${__OCF_ACTION:=$1} FINDIF=findif # Defaults OCF_RESKEY_name_default="ifspeed" OCF_RESKEY_bridge_ports_default="detect" OCF_RESKEY_weight_base_default=1000 OCF_RESKEY_dampen_default=5 -: ${OCF_RESKEY_name=${OCF_RESKEY_name_default}} -: ${OCF_RESKEY_bridge_ports=${OCF_RESKEY_bridge_ports_default}} -: ${OCF_RESKEY_weight_base=${OCF_RESKEY_weight_base_default}} -: ${OCF_RESKEY_dampen=${OCF_RESKEY_dampen_default}} +: ${OCF_RESKEY_name:=${OCF_RESKEY_name_default}} +: ${OCF_RESKEY_bridge_ports:=${OCF_RESKEY_bridge_ports_default}} +: ${OCF_RESKEY_weight_base:=${OCF_RESKEY_weight_base_default}} +: ${OCF_RESKEY_dampen:=${OCF_RESKEY_dampen_default}} meta_data() { cat < 1.0 Every time the monitor action is run, this resource agent records (in the CIB) (relative) speed of network interface it monitors. This RA can monitor physical interfaces, bonds, bridges, vlans and (hopefully) any combination of them. Examples: *) Bridge on top of one 10Gbps interface (eth2) and 802.3ad bonding (bond0) built on two 1Gbps interfaces (eth0 and eth1). *) Active-backup bonding built on top of one physical interface and one vlan on another interface. For STP-enabled bridges this RA tries to some-how guess network topology and by default looks only on ports which are connected to upstream switch. This can be overridden by 'bridge_ports' parameter. Active interfaces in this case are those in "forwarding" state. For balancing bonds this RA summs speeds of underlying "up" slave interfaces (and applies coefficient 0.8 to result). For non-balancing bonds ('active-backup' and probably 'broadcast'), only the -speed of the currently active slave is used. +speed of the currently active slave is used. Network interface speed monitor The name of the attribute to set. This is the name to be used in the constraints. Attribute name Network interface to monitor. Network interface Try to detect interface name by detecting the interface that holds the IP address. The IPv4 (dotted quad notation) or IPv6 address (colon hexadecimal notation) example IPv4 "192.168.1.1". example IPv6 "2001:db8:DC28:0:0:FC57:D4C8:1FFF". IPv4 or IPv6 address If not null and OCF_RESKEY_iface is a bridge, list of bridge ports to consider. Default is all ports which have designated_bridge=root_id. 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 what have been done more verbosely. Verbose logging END } usage() { cat </dev/null) test -n "$MOUNTOUT" return $? } # -# Unload a filesystem driver. +# Unload a filesystem driver. # Be careful to notice if the driver is built-in and do nothing. # # 0 is success, 1 is error, 2 is already unloaded. # unload_filesystem() { - if [ "$#" != "1" -o -z "$1" ] + if [ $# -ne 1 -o -z "$1" ] then ocf_log err "unload_filesystem(): Missing an argument" return 1 fi FSNAME="$1" driver_filesystem "$FSNAME" || return 2 - MODOUT="`awk '$1 ~ /^'$FSNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null`" + MODOUT=$(awk '$1 ~ /^'$FSNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null) if [ -z "$MODOUT" ]; then # The driver is built in, we can't unload it. return 0 fi case "$MODOUT" in $FSNAME\ 0) ;; $FSNAME\ *) # The driver is busy, leave it alone ocf_log err "Module $FSNAME is still in use" return 1 ;; *) ocf_log err "Invalid module parsing! " return 1 ;; esac modprobe -rs "$FSNAME" - if [ "$?" != 0 ]; then + if [ $? -ne 0 ]; then ocf_log err "Unable to unload module: $FSNAME" return 1 fi return 0 } status_daemon() { - PID=`pidof "$DAEMON"` + PID=$(pidof "$DAEMON") if [ -n "$PID" ]; then - return $OCF_SUCCESS + return $OCF_SUCCESS fi return $OCF_NOT_RUNNING } bringup_daemon() { if [ ! -e "$DAEMON" ]; then - ocf_log err "Required binary not found: $DAEMON" - return $OCF_ERR_INSTALLED + ocf_log err "Required binary not found: $DAEMON" + return $OCF_ERR_INSTALLED fi "$DAEMON"; rc=$? - if [ $rc != 0 ]; then - ocf_log err "Could not start $DAEMON" - return $OCF_ERR_GENERIC + if [ $rc -ne 0 ]; then + ocf_log err "Could not start $DAEMON" + return $OCF_ERR_GENERIC fi sleep 1 COUNT=0 rc=$OCF_NOT_RUNNING - while [ $rc = $OCF_NOT_RUNNING ]; do - COUNT=`expr $COUNT + 1` + while [ $rc -eq $OCF_NOT_RUNNING ]; do + COUNT=$(expr $COUNT + 1) if [ $COUNT -gt $OCF_RESKEY_daemon_timeout ]; then - ocf_log err "`basename $DAEMON` did not come up" - return $OCF_ERR_GENERIC + ocf_log err "$(basename $DAEMON) did not come up" + return $OCF_ERR_GENERIC fi - status_daemon; rc=$? + status_daemon; rc=$? sleep 1 done return $rc } kill_daemon() { status_daemon; rc=$? - if [ $rc != $OCF_SUCCESS ]; then - return $rc + if [ $rc -ne $OCF_SUCCESS ]; then + return $rc fi - ocf_log info "Stopping `basename "$DAEMON"`" + ocf_log info "Stopping $(basename "$DAEMON")" killproc "$DAEMON" - while [ $rc = $OCF_NOT_RUNNING ]; do + while [ $rc -eq $OCF_NOT_RUNNING ]; do sleep 1 - status_daemon; rc=$? + status_daemon; rc=$? done return $OCF_SUCCESS } # # Unload a module # 0 is success, 1 is error, 2 is not loaded # unload_module() { - if [ "$#" -lt "1" -o -z "$1" ] + if [ $# -lt 1 -o -z "$1" ] then - ocf_log err "unload_module(): Requires an argument" + ocf_log err "unload_module(): Requires an argument" return 1 fi MODNAME="$1" - MODOUT="`awk '$1 ~ /^'$MODNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null`" + MODOUT=$(awk '$1 ~ /^'$MODNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null) if [ -z "$MODOUT" ] then return 2 fi case "$MODOUT" in $MODNAME\ 0) ;; $MODNAME\ *) return 2 ;; *) - ocf_log err "Invalid module parsing!" + ocf_log err "Invalid module parsing!" return 1 ;; esac modprobe -rs "$MODNAME" - if [ "$?" != 0 ]; then - ocf_log err "Unable to unload module \"$MODNAME\"" + if [ $? -ne 0 ]; then + ocf_log err "Unable to unload module \"$MODNAME\"" return 1 fi return 0 } o2cb_start() { o2cb_monitor; rc=$? - if [ $rc != $OCF_NOT_RUNNING ]; then - return $rc + if [ $rc -ne $OCF_NOT_RUNNING ]; then + return $rc fi ocf_log info "Starting $OCF_RESOURCE_INSTANCE" if [ ! -e "$CLUSTER_STACK_FILE" ]; then - modprobe -s ocfs2_stackglue - if [ $? != 0 ]; then - ocf_log err "Could not load ocfs2_stackglue" - return $OCF_ERR_INSTALLED - fi + modprobe -s ocfs2_stackglue + if [ $? -ne 0 ]; then + ocf_log err "Could not load ocfs2_stackglue" + return $OCF_ERR_INSTALLED + fi fi SP_OUT="$(awk '/^'user'$/{print; exit}' "$LOADED_PLUGINS_FILE" 2>/dev/null)" if [ -z "$SP_OUT" ] then modprobe -s ocfs2_stack_user - if [ $? != 0 ]; then - ocf_log err "Could not load ocfs2_stack_user" - return $OCF_ERR_INSTALLED - fi + if [ $? -ne 0 ]; then + ocf_log err "Could not load ocfs2_stack_user" + return $OCF_ERR_INSTALLED + fi fi SP_OUT="$(awk '/^'user'$/{print; exit}' "$LOADED_PLUGINS_FILE" 2>/dev/null)" if [ -z "$SP_OUT" ]; then - ocf_log err "Switch to userspace stack unsuccessful" - return $OCF_ERR_INSTALLED + ocf_log err "Switch to userspace stack unsuccessful" + return $OCF_ERR_INSTALLED fi if [ -f "$CLUSTER_STACK_FILE" ]; then echo "$OCF_RESKEY_stack" >"$CLUSTER_STACK_FILE" - if [ $? != 0 ]; then - ocf_log err "Userspace stack '$OCF_RESKEY_stack' not supported" - return $OCF_ERR_INSTALLED - fi + if [ $? -ne 0 ]; then + ocf_log err "Userspace stack '$OCF_RESKEY_stack' not supported" + return $OCF_ERR_INSTALLED + fi else - ocf_log err "Switch to userspace stack not supported" - return $OCF_ERR_INSTALLED + ocf_log err "Switch to userspace stack not supported" + return $OCF_ERR_INSTALLED fi driver_filesystem ocfs2; rc=$? - if [ $rc != 0 ]; then - modprobe -s ocfs2 - if [ "$?" != 0 ]; then + if [ $rc -ne 0 ]; then + modprobe -s ocfs2 + if [ $? -ne 0 ]; then ocf_log err "Unable to load ocfs2 module" return $OCF_ERR_INSTALLED - fi + fi fi bringup_daemon return $? } o2cb_stop() { o2cb_monitor; rc=$? case $rc in - $OCF_NOT_RUNNING) return $OCF_SUCCESS;; + $OCF_NOT_RUNNING) return $OCF_SUCCESS;; esac ocf_log info "Stopping $OCF_RESOURCE_INSTANCE" kill_daemon - if [ $? != 0 ]; then + if [ $? -ne 0 ]; then ocf_log err "Unable to unload modules: the cluster is still online" - return $OCF_ERR_GENERIC + return $OCF_ERR_GENERIC fi unload_filesystem ocfs2 - if [ $? = 1 ]; then - ocf_log err "Unable to unload ocfs2 module" - return $OCF_ERR_GENERIC + if [ $? -eq 1 ]; then + ocf_log err "Unable to unload ocfs2 module" + return $OCF_ERR_GENERIC fi # If we can't find the stack glue, we have nothing to do. [ ! -e "$LOADED_PLUGINS_FILE" ] && return $OCF_SUCCESS while read plugin do unload_module "ocfs2_stack_${plugin}" - if [ $? = 1 ]; then - ocf_log err "Unable to unload ocfs2_stack_${plugin}" - return $OCF_ERR_GENERIC - fi + if [ $? -eq 1 ]; then + ocf_log err "Unable to unload ocfs2_stack_${plugin}" + return $OCF_ERR_GENERIC + fi done <"$LOADED_PLUGINS_FILE" unload_module "ocfs2_stackglue" - if [ $? = 1 ]; then - ocf_log err "Unable to unload ocfs2_stackglue" - return $OCF_ERR_GENERIC + if [ $? -eq 1 ]; then + ocf_log err "Unable to unload ocfs2_stackglue" + return $OCF_ERR_GENERIC fi # Don't unmount configfs - it's always in use by libdlm } o2cb_monitor() { o2cb_validate # Assume that ocfs2_controld will terminate if any of the conditions below are met driver_filesystem configfs; rc=$? - if [ $rc != 0 ]; then - ocf_log info "configfs not loaded" - return $OCF_NOT_RUNNING + if [ $rc -ne 0 ]; then + ocf_log info "configfs not loaded" + return $OCF_NOT_RUNNING fi check_filesystem configfs "${OCF_RESKEY_configfs}"; rc=$? - if [ $rc != 0 ]; then - ocf_log info "configfs not mounted" - return $OCF_NOT_RUNNING + if [ $rc -ne 0 ]; then + ocf_log info "configfs not mounted" + return $OCF_NOT_RUNNING fi if [ ! -e "$LOADED_PLUGINS_FILE" ]; then - ocf_log info "Stack glue driver not loaded" - return $OCF_NOT_RUNNING + ocf_log info "Stack glue driver not loaded" + return $OCF_NOT_RUNNING fi grep user "$LOADED_PLUGINS_FILE" >/dev/null 2>&1; rc=$? - if [ $rc != 0 ]; then - ocf_log err "Wrong stack `cat $LOADED_PLUGINS_FILE`" - return $OCF_ERR_INSTALLED + if [ $rc -ne 0 ]; then + ocf_log err "Wrong stack $(cat $LOADED_PLUGINS_FILE)" + return $OCF_ERR_INSTALLED fi driver_filesystem ocfs2; rc=$? - if [ $rc != 0 ]; then - ocf_log info "ocfs2 not loaded" - return $OCF_NOT_RUNNING + if [ $rc -ne 0 ]; then + ocf_log info "ocfs2 not loaded" + return $OCF_NOT_RUNNING fi status_daemon return $? } o2cb_usage() { echo "usage: $0 {start|stop|monitor|validate-all|meta-data}" echo " Expects to have a fully populated OCF RA-compliant environment set." echo " In particualr, a value for OCF_ROOT" } o2cb_validate() { check_binary ${DAEMON} - case ${OCF_RESKEY_CRM_meta_globally_unique} in - yes|Yes|true|True|1) - ocf_log err "$OCF_RESOURCE_INSTANCE must be configured with the globally_unique=false meta attribute" - exit $OCF_ERR_CONFIGURED - ;; + case "${OCF_RESKEY_CRM_meta_globally_unique}" in + yes|Yes|true|True|1) + ocf_log err "$OCF_RESOURCE_INSTANCE must be configured with the globally_unique=false meta attribute" + exit $OCF_ERR_CONFIGURED + ;; esac return $OCF_SUCCESS } meta_data() { - cat < 1.0 OCFS2 daemon resource agent This Resource Agent controls the userspace daemon needed by OCFS2. Location where sysfs is mounted Sysfs location Location where configfs is mounted Configfs location Which userspace stack to use. Known values: pcmk Userspace stack Number of seconds to allow the control daemon to come up Daemon Timeout END } -case $__OCF_ACTION in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -start) o2cb_start - ;; -stop) o2cb_stop - ;; -monitor) o2cb_monitor - ;; -validate-all) o2cb_validate - ;; -usage|help) o2cb_usage - exit $OCF_SUCCESS - ;; -*) o2cb_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; +case "$__OCF_ACTION" in +meta-data) meta_data + exit $OCF_SUCCESS + ;; +start) o2cb_start + ;; +stop) o2cb_stop + ;; +monitor) o2cb_monitor + ;; +validate-all) o2cb_validate + ;; +usage|help) o2cb_usage + exit $OCF_SUCCESS + ;; +*) o2cb_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac exit $? + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/ping b/extra/resources/ping index 1210540e6e..ab22e795e3 100755 --- a/extra/resources/ping +++ b/extra/resources/ping @@ -1,416 +1,418 @@ #!/bin/sh # -# Ping OCF RA that utilizes the system ping +# ocf:pacemaker:ping resource agent # -# Copyright 2009-2018 the Pacemaker project contributors +# Copyright 2009-2019 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # + ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { - cat < 1.0 Every time the monitor action is run, this resource agent records (in the CIB) the current number of nodes the host can connect to using the system fping (preferred) or ping tool. node connectivity PID file PID file The time to wait (dampening) further changes occur Dampening interval The name of the attributes to set. This is the name to be used in the constraints. Attribute name The number by which to multiply the number of connected ping nodes by Value multiplier A space separated list of ping nodes to count. Host list Number of ping attempts, per host, before declaring it dead no. of ping attempts How long, in seconds, to wait before declaring a ping lost ping timeout in seconds A catch all for any other options that need to be passed to ping. Extra Options Resource is failed if the score is less than failure_score. Default never fails. failure_score Use fping rather than ping, if found. If set to 0, fping will not be used even if present. Use fping if available Enables to use default attrd_updater verbose logging on every call. Verbose logging END } ####################################################################### ping_conditional_log() { - level=$1; shift - if [ ${OCF_RESKEY_debug} = "true" ]; then - ocf_log $level "$*" + level="$1"; shift + if [ "${OCF_RESKEY_debug}" = "true" ]; then + ocf_log "$level" "$*" fi } ping_usage() { - cat <&1`; rc=$? - active=`echo "$output" | grep "is alive" | wc -l` + output=$($cmd 2>&1); rc=$? + active=$(echo "$output" | grep "is alive" | wc -l) case $rc in - 0) - ;; - 1) - for h in `echo "$output" | grep "is unreachable" | awk '{print $1}'`; do - ping_conditional_log warn "$h is inactive" - done - ;; - *) - ocf_log err "Unexpected result for '$cmd' $rc: `echo "$output" | tr '\n' ';'`" - ;; + 0) + ;; + 1) + for h in $(echo "$output" | grep "is unreachable" | awk '{print $1}'); do + ping_conditional_log warn "$h is inactive" + done + ;; + *) + ocf_log err "Unexpected result for '$cmd' $rc: $(echo "$output" | tr '\n' ';')" + ;; esac return $active } ping_check() { active=0 for host in $OCF_RESKEY_host_list; do - p_exe=ping - - case `uname` in - Linux) p_args="-n -q -W $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts";; - Darwin) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";; - FreeBSD) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";; - *) ocf_log err "Unknown host type: `uname`"; exit $OCF_ERR_INSTALLED;; - esac - - case $host in - *:*) p_exe=ping6 - esac - - p_out=`$p_exe $p_args $OCF_RESKEY_options $host 2>&1`; rc=$? - - case $rc in - 0) active=`expr $active + 1`;; - 1) ping_conditional_log warn "$host is inactive: $p_out";; - *) ocf_log err "Unexpected result for '$p_exe $p_args $OCF_RESKEY_options $host' $rc: $p_out";; - esac + p_exe=ping + + case $(uname) in + Linux) p_args="-n -q -W $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts";; + Darwin) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";; + FreeBSD) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";; + *) ocf_log err "Unknown host type: $(uname)"; exit $OCF_ERR_INSTALLED;; + esac + + case "$host" in + *:*) p_exe=ping6 + esac + + p_out=$($p_exe $p_args $OCF_RESKEY_options $host 2>&1); rc=$? + + case $rc in + 0) active=$(expr $active + 1);; + 1) ping_conditional_log warn "$host is inactive: $p_out";; + *) ocf_log err "Unexpected result for '$p_exe $p_args $OCF_RESKEY_options $host' $rc: $p_out";; + esac done return $active } ping_update() { - + if use_fping; then - fping_check - active=$? + fping_check + active=$? else - ping_check - active=$? + ping_check + active=$? fi - score=`expr $active \* $OCF_RESKEY_multiplier` + score=$(expr $active \* $OCF_RESKEY_multiplier) if [ "$__OCF_ACTION" = "start" ] ; then - attrd_updater -n $OCF_RESKEY_name -B $score -d $OCF_RESKEY_dampen $attrd_options + 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 + attrd_updater -n "$OCF_RESKEY_name" -v "$score" -d "$OCF_RESKEY_dampen" $attrd_options fi rc=$? - case $rc in - 0) ping_conditional_log debug "Updated $OCF_RESKEY_name = $score" ;; - *) ocf_log warn "Could not update $OCF_RESKEY_name = $score: rc=$rc";; + case $rc in + 0) ping_conditional_log debug "Updated $OCF_RESKEY_name = $score" ;; + *) ocf_log warn "Could not update $OCF_RESKEY_name = $score: rc=$rc";; esac if [ $rc -ne 0 ]; then return $rc fi if [ -n "$OCF_RESKEY_failure_score" ] && [ "$score" -lt "$OCF_RESKEY_failure_score" ]; then ocf_log warn "$OCF_RESKEY_name is less than failure_score($OCF_RESKEY_failure_score)" return 1 fi return 0 } use_fping() { ocf_is_true "$OCF_RESKEY_use_fping" && have_binary fping; } # return values: # 4 IPv4 # 6 IPv6 # 0 indefinite (i.e. hostname) host_family() { case $1 in - *[0-9].*[0-9].*[0-9].*[0-9]) return 4 ;; - *:*) return 6 ;; - *) return 0 ;; + *[0-9].*[0-9].*[0-9].*[0-9]) return 4 ;; + *:*) return 6 ;; + *) return 0 ;; esac } # return values same as host_family plus # 99 ambiguous families hosts_family() { # For fping allow only same IP versions or hostnames family=0 for host in $OCF_RESKEY_host_list; do - host_family $host - f=$? + host_family "$host" + f=$? if [ $family -ne 0 ] && [ $f -ne 0 ] && [ $f -ne $family ] ; then family=99 break fi [ $f -ne 0 ] && family=$f done return $family } : ${OCF_RESKEY_name:="pingd"} : ${OCF_RESKEY_dampen:="5s"} : ${OCF_RESKEY_attempts:="3"} : ${OCF_RESKEY_multiplier:="1"} : ${OCF_RESKEY_debug:="false"} : ${OCF_RESKEY_failure_score:="0"} : ${OCF_RESKEY_use_fping:="1"} : ${OCF_RESKEY_CRM_meta_timeout:="20000"} : ${OCF_RESKEY_CRM_meta_globally_unique:="false"} -integer=`echo ${OCF_RESKEY_timeout} | egrep -o '[0-9]*'` -case ${OCF_RESKEY_timeout} in - *[0-9]ms|*[0-9]msec) OCF_RESKEY_timeout=`expr $integer / 1000`;; - *[0-9]m|*[0-9]min) OCF_RESKEY_timeout=`expr $integer \* 60`;; - *[0-9]h|*[0-9]hr) OCF_RESKEY_timeout=`expr $integer \* 60 \* 60`;; +integer=$(echo ${OCF_RESKEY_timeout} | egrep -o '[0-9]*') +case "${OCF_RESKEY_timeout}" in + *[0-9]ms|*[0-9]msec) OCF_RESKEY_timeout=$(expr $integer / 1000);; + *[0-9]m|*[0-9]min) OCF_RESKEY_timeout=$(expr $integer \* 60);; + *[0-9]h|*[0-9]hr) OCF_RESKEY_timeout=$(expr $integer \* 60 \* 60);; *) OCF_RESKEY_timeout=$integer;; esac -if [ -z ${OCF_RESKEY_timeout} ]; then - if [ x"$OCF_RESKEY_host_list" != x ]; then - host_count=`echo $OCF_RESKEY_host_list | awk '{print NF}'` - OCF_RESKEY_timeout=`expr $OCF_RESKEY_CRM_meta_timeout / $host_count / $OCF_RESKEY_attempts` - OCF_RESKEY_timeout=`expr $OCF_RESKEY_timeout / 1100` # Convert to seconds and finish 10% early +if [ -z "${OCF_RESKEY_timeout}" ]; then + if [ -n "$OCF_RESKEY_host_list" ]; then + host_count=$(echo $OCF_RESKEY_host_list | awk '{print NF}') + OCF_RESKEY_timeout=$(expr $OCF_RESKEY_CRM_meta_timeout / $host_count / $OCF_RESKEY_attempts) + OCF_RESKEY_timeout=$(expr $OCF_RESKEY_timeout / 1100) # Convert to seconds and finish 10% early else - OCF_RESKEY_timeout=5 + OCF_RESKEY_timeout=5 fi fi if [ ${OCF_RESKEY_timeout} -lt 1 ]; then OCF_RESKEY_timeout=5 elif [ ${OCF_RESKEY_timeout} -gt 1000 ]; then # ping actually complains if this value is too high, 5 minutes is plenty OCF_RESKEY_timeout=300 fi -if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then +if [ "${OCF_RESKEY_CRM_meta_globally_unique}" = "false" ]; then : ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/ping-${OCF_RESKEY_name}"} -else +else : ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/ping-${OCF_RESOURCE_INSTANCE}"} fi # Check the debug option case "${OCF_RESKEY_debug}" in true|True|TRUE|1) OCF_RESKEY_debug=true;; false|False|FALSE|0) OCF_RESKEY_debug=false;; *) ocf_log warn "Value for 'debug' is incorrect. Please specify 'true' or 'false' not: ${OCF_RESKEY_debug}" OCF_RESKEY_debug=false ;; esac attrd_options='-q' -if [ ${OCF_RESKEY_debug} = "true" ]; then +if [ "${OCF_RESKEY_debug}" = "true" ]; then attrd_options='' fi -case $__OCF_ACTION in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -start) ping_start;; -stop) ping_stop;; -monitor) ping_monitor;; -validate-all) ping_validate;; -usage|help) ping_usage - exit $OCF_SUCCESS - ;; -*) ping_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; +case "$__OCF_ACTION" in +meta-data) meta_data + exit $OCF_SUCCESS + ;; +start) ping_start;; +stop) ping_stop;; +monitor) ping_monitor;; +validate-all) ping_validate;; +usage|help) ping_usage + exit $OCF_SUCCESS + ;; +*) ping_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac exit $? +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/pingd b/extra/resources/pingd index 58e3d0888a..6e50e906b4 100755 --- a/extra/resources/pingd +++ b/extra/resources/pingd @@ -1,202 +1,185 @@ #!/bin/sh # +# ocf:pacemaker:pingd resource agent # -# pingd OCF Resource Agent -# Records (in the CIB) the current number of ping nodes a -# cluster node can connect to. -# -# Copyright 2006-2018 the Pacemaker project contributors +# Copyright 2006-2019 the Pacemaker project contributors # # The version control history for this file may have further details. -# All Rights Reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. # -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# This source code is licensed under the GNU General Public License version 2 +# (GPLv2) WITHOUT ANY WARRANTY. # -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. + # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# Records (in the CIB) the current number of ping nodes a cluster node can +# connect to. # ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} : ${OCF_RESKEY_name:="pingd"} : ${OCF_RESKEY_interval:="1"} : ${OCF_RESKEY_CRM_meta_interval:=0} -upgrade1="This agent (ocf:pacemaker:pingd) has been replaced by the more reliable ocf:pacemaker:ping." -upgrade2="Attempting automated conversion, run 'crm ra info ocf:pacemaker:ping' for all configuration options" -upgrade3="You will need to remove the existing resource and replace it with one that uses 'ocf:pacemaker:ping' directly" +ocf_log err "This agent (ocf:pacemaker:pingd) is deprecated, does not work, and" +ocf_log err "will be removed in a future release (use ocf:pacemaker:ping instead)" -case $__OCF_ACTION in +case "$__OCF_ACTION" in start|monitor) - if [ "x" != "x$OCF_RESKEY_host_list" ]; then - ocf_log err "$upgrade1" - ocf_log err "$upgrade2" - ocf_log err "Automatic conversion to ocf:pacemaker:ping failed: no hosts were configured to check for connectivity" - ocf_log err "$upgrade3" - exit $OCF_ERR_ARGS - fi - - recurring=`crm configure show $OCF_RESOURCE_INSTANCE | grep "op monitor.*interval=\"[1-9]" | sed s/.*interval=// | awk -F\" '{print $2}' | sed s/.*interval=// | awk -F\" '{print $2}' | sort | head -n 1` - - if [ -z $recurring ]; then - ocf_log err "$upgrade1" - ocf_log err "$upgrade2" - ocf_log err "Automatic conversion to ocf:pacemaker:ping failed: no monitor operation configured" - ocf_log err "Without an explicit monitor operation for '$OCF_RESOURCE_INSTANCE', connectivity changes will not be noticed" - ocf_log err "Preventing startup to ensure the issue is addressed before it matters" - exit $OCF_ERR_ARGS - fi - - if [ $OCF_RESKEY_CRM_meta_interval = 0 ]; then - ocf_log warn "$upgrade1" - ocf_log warn "$upgrade2" - if [ $recurring != $OCF_RESKEY_interval ]; then - ocf_log warn "Your monitor operation happens every $recurring, which means that the $OCF_RESKEY_name attribute will be updated with a different frequency than the previously configured ( $OCF_RESKEY_interval )" - ocf_log warn "Either change the monitor interval to match or, ideally, switch to the ocf:pacemaker:ping agent and avoid all this compatibility nonsense." - fi - fi - ;; + # BUG: The sense of this test is reversed. Rather than fix it now, we + # will formally deprecate the agent and remove it in a future release. + if [ -n "$OCF_RESKEY_host_list" ]; then + ocf_log err "Automatic conversion to ocf:pacemaker:ping failed: no hosts were configured to check for connectivity" + exit $OCF_ERR_ARGS + fi + + recurring=$(crm configure show "$OCF_RESOURCE_INSTANCE" | grep "op monitor.*interval=\"[1-9]" | sed s/.*interval=// | awk -F\" '{print $2}' | sed s/.*interval=// | awk -F\" '{print $2}' | sort | head -n 1) + + if [ -z "$recurring" ]; then + ocf_log err "Automatic conversion to ocf:pacemaker:ping failed: no monitor operation configured" + ocf_log err "Without an explicit monitor operation for '$OCF_RESOURCE_INSTANCE', connectivity changes will not be noticed" + ocf_log err "Preventing startup to ensure the issue is addressed before it matters" + exit $OCF_ERR_ARGS + fi + + if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then + if [ $recurring -ne $OCF_RESKEY_interval ]; then + ocf_log warn "Your monitor operation happens every $recurring, which means that the $OCF_RESKEY_name attribute will be updated with a different frequency than the previously configured ( $OCF_RESKEY_interval )" + ocf_log warn "Either change the monitor interval to match or, ideally, switch to the ocf:pacemaker:ping agent and avoid all this compatibility nonsense." + fi + fi + ;; meta-data) - cat < 1.0 -This agent (ocf:pacemaker:pingd) has been replaced by the more reliable ocf:pacemaker:ping. -It records (in the CIB) the current number of ping nodes (specified in the 'host_list' parameter) a cluster node can connect to. +This agent (ocf:pacemaker:pingd) is deprecated and broken, and has been +replaced by the more reliable ocf:pacemaker:ping. It records (in the CIB) +the current number of ping nodes (specified in the 'host_list' parameter) +a cluster node can connect to. pingd resource agent PID file PID file The user we want to run pingd as The user we want to run pingd as The time to wait (dampening) further changes occur Dampening interval The name of the instance_attributes set to place the value in. Rarely needs to be specified. Set name The name of the attributes to set. This is the name to be used in the constraints. Attribute name The section place the value in. Rarely needs to be specified. Section name The number by which to multiply the number of connected ping nodes by Value multiplier The list of ping nodes to count. Defaults to all configured ping nodes. Rarely needs to be specified. Host list How often, in seconds, to check for node liveliness ping interval in seconds Number of ping attempts, per host, before declaring it dead no. of ping attempts How long, in seconds, to wait before declaring a ping lost ping timeout in seconds A catch all for any other options that need to be passed to pingd. Extra Options END - exit $OCF_SUCCESS - ;; + exit $OCF_SUCCESS + ;; esac -${OCF_ROOT}/resource.d/pacemaker/ping $1 +"${OCF_ROOT}/resource.d/pacemaker/ping" "$1" exit $? + +# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/extra/resources/remote b/extra/resources/remote index 2828b0aadc..e571d820ef 100755 --- a/extra/resources/remote +++ b/extra/resources/remote @@ -1,111 +1,113 @@ #!/bin/sh # -# ocf:pacmaker:remote OCF resource agent +# ocf:pacemaker:remote OCF resource agent # -# This script provides metadata for Pacemaker's internal remote agent. -# Outside of acting as a placeholder so the agent can be indexed, and -# providing metadata, this script should never be invoked. The actual -# functionality behind the remote connection lives within Pacemaker's -# controller daemon. -# -# Copyright 2013-2018 the Pacemaker project contributors +# Copyright 2013-2019 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # (GPLv2) WITHOUT ANY WARRANTY. # +# This script provides metadata for Pacemaker's internal remote agent. +# Outside of acting as a placeholder so the agent can be indexed, and +# providing metadata, this script should never be invoked. The actual +# functionality behind the remote connection lives within Pacemaker's +# controller daemon. +# ####################################################################### # Initialization: -: ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} -. ${OCF_FUNCTIONS} -: ${__OCF_ACTION=$1} +: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} +. "${OCF_FUNCTIONS}" +: ${__OCF_ACTION:="$1"} ####################################################################### meta_data() { - cat < 1.0 remote resource agent Server location to connect to. This can be an ip address or hostname. Server location tcp port to connect to. tcp port Interval in seconds at which Pacemaker will attempt to reconnect to a remote node after an active connection to the remote node has been severed. When this value is nonzero, Pacemaker will retry the connection indefinitely, at the specified interval. As with any time-based actions, this is not guaranteed to be checked more frequently than the value of the cluster-recheck-interval cluster option. reconnect interval END } ####################################################################### remote_usage() { - cat <