summaryrefslogtreecommitdiffstats
path: root/agents/alerts
diff options
context:
space:
mode:
Diffstat (limited to 'agents/alerts')
-rw-r--r--agents/alerts/Makefile.am15
-rw-r--r--agents/alerts/alert_file.sh.sample122
-rw-r--r--agents/alerts/alert_smtp.sh.sample118
-rw-r--r--agents/alerts/alert_snmp.sh.sample193
4 files changed, 448 insertions, 0 deletions
diff --git a/agents/alerts/Makefile.am b/agents/alerts/Makefile.am
new file mode 100644
index 0000000..fdb294f
--- /dev/null
+++ b/agents/alerts/Makefile.am
@@ -0,0 +1,15 @@
+#
+# Copyright 2016-2023 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+
+include $(top_srcdir)/mk/common.mk
+
+samplesdir = $(datadir)/$(PACKAGE)/alerts/
+dist_samples_DATA = alert_file.sh.sample \
+ alert_smtp.sh.sample \
+ alert_snmp.sh.sample
diff --git a/agents/alerts/alert_file.sh.sample b/agents/alerts/alert_file.sh.sample
new file mode 100644
index 0000000..f6c2211
--- /dev/null
+++ b/agents/alerts/alert_file.sh.sample
@@ -0,0 +1,122 @@
+#!/bin/sh
+#
+# Copyright 2015-2021 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.
+#
+##############################################################################
+# Sample configuration (cib fragment in xml notation)
+# ================================
+# <configuration>
+# <alerts>
+# <alert id="alert_sample" path="/path/to/alert_file.sh">
+# <instance_attributes id="config_for_alert_file">
+# <nvpair id="debug_option_1" name="debug_exec_order" value="false"/>
+# </instance_attributes>
+# <meta_attributes id="config_for_timestamp">
+# <nvpair id="ts_fmt" name="timestamp-format" value="%H:%M:%S.%06N"/>
+# </meta_attributes>
+# <recipient id="logfile_destination" value="/path/to/logfile"/>
+# </alert>
+# </alerts>
+# </configuration>
+
+# Explicitly list all environment variables used, to make static analysis happy
+: ${CRM_alert_version:=""}
+: ${CRM_alert_recipient:=""}
+: ${CRM_alert_node_sequence:=""}
+: ${CRM_alert_timestamp:=""}
+: ${CRM_alert_kind:=""}
+: ${CRM_alert_node:=""}
+: ${CRM_alert_desc:=""}
+: ${CRM_alert_task:=""}
+: ${CRM_alert_rsc:=""}
+: ${CRM_alert_attribute_name:=""}
+: ${CRM_alert_attribute_value:=""}
+
+# No one will probably ever see this echo, unless they run the script manually.
+# An alternative would be to log to the system log, or similar. (We can't send
+# this to the configured recipient, because that variable won't be defined in
+# this case either.)
+if [ -z $CRM_alert_version ]; then
+ echo "$0 must be run by Pacemaker version 1.1.15 or later"
+ exit 0
+fi
+
+# Alert agents must always handle the case where no recipients are defined,
+# even if it's a no-op (a recipient might be added to the configuration later).
+if [ -z "${CRM_alert_recipient}" ]; then
+ echo "$0 requires a recipient configured with a full filename path"
+ exit 0
+fi
+
+debug_exec_order_default="false"
+
+# Pacemaker passes instance attributes to alert agents as environment variables.
+# It is completely up to the agent what instance attributes to support.
+# Here, we define an instance attribute "debug_exec_order".
+: ${debug_exec_order=${debug_exec_order_default}}
+
+if [ "${debug_exec_order}" = "true" ]; then
+ tstamp=`printf "%04d. " "$CRM_alert_node_sequence"`
+ if [ ! -z "$CRM_alert_timestamp" ]; then
+ tstamp="${tstamp} $CRM_alert_timestamp (`date "+%H:%M:%S.%06N"`): "
+ fi
+else
+ if [ ! -z "$CRM_alert_timestamp" ]; then
+ tstamp="$CRM_alert_timestamp: "
+ fi
+fi
+
+case $CRM_alert_kind in
+ node)
+ echo "${tstamp}Node '${CRM_alert_node}' is now '${CRM_alert_desc}'" >> "${CRM_alert_recipient}"
+ ;;
+ fencing)
+ # Other keys:
+ #
+ # CRM_alert_node
+ # CRM_alert_task
+ # CRM_alert_rc
+ #
+ echo "${tstamp}Fencing ${CRM_alert_desc}" >> "${CRM_alert_recipient}"
+ ;;
+ resource)
+ # Other keys:
+ #
+ # CRM_alert_target_rc
+ # CRM_alert_status
+ # CRM_alert_rc
+ #
+ if [ ${CRM_alert_interval} = "0" ]; then
+ CRM_alert_interval=""
+ else
+ CRM_alert_interval=" (${CRM_alert_interval})"
+ fi
+
+ if [ ${CRM_alert_target_rc} = "0" ]; then
+ CRM_alert_target_rc=""
+ else
+ CRM_alert_target_rc=" (target: ${CRM_alert_target_rc})"
+ fi
+
+ case ${CRM_alert_desc} in
+ Cancelled) ;;
+ *)
+ echo "${tstamp}Resource operation '${CRM_alert_task}${CRM_alert_interval}' for '${CRM_alert_rsc}' on '${CRM_alert_node}': ${CRM_alert_desc}${CRM_alert_target_rc}" >> "${CRM_alert_recipient}"
+ ;;
+ esac
+ ;;
+ attribute)
+ #
+ echo "${tstamp}Attribute '${CRM_alert_attribute_name}' on node '${CRM_alert_node}' was updated to '${CRM_alert_attribute_value}'" >> "${CRM_alert_recipient}"
+ ;;
+
+ *)
+ echo "${tstamp}Unhandled $CRM_alert_kind alert" >> "${CRM_alert_recipient}"
+ env | grep CRM_alert >> "${CRM_alert_recipient}"
+ ;;
+esac
diff --git a/agents/alerts/alert_smtp.sh.sample b/agents/alerts/alert_smtp.sh.sample
new file mode 100644
index 0000000..62bfc41
--- /dev/null
+++ b/agents/alerts/alert_smtp.sh.sample
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# Copyright 2016-2021 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.
+#
+##############################################################################
+#
+# Sample configuration (cib fragment in xml notation)
+# ================================
+# <configuration>
+# <alerts>
+# <alert id="smtp_alert" path="/path/to/alert_smtp">
+# <instance_attributes id="config_for_alert_smtp">
+# <nvpair id="cluster_name" name="cluster_name" value=""/>
+# <nvpair id="email_client" name="email_client" value=""/>
+# <nvpair id="email_sender" name="email_sender" value=""/>
+# </instance_attributes>
+# <recipient id="smtp_destination" value="admin@example.com"/>
+# </alert>
+# </alerts>
+# </configuration>
+
+# Explicitly list all environment variables used, to make static analysis happy
+: ${CRM_alert_version:=""}
+: ${CRM_alert_recipient:=""}
+: ${CRM_alert_timestamp:=""}
+: ${CRM_alert_kind:=""}
+: ${CRM_alert_node:=""}
+: ${CRM_alert_desc:=""}
+: ${CRM_alert_task:=""}
+: ${CRM_alert_rsc:=""}
+: ${CRM_alert_attribute_name:=""}
+: ${CRM_alert_attribute_value:=""}
+
+email_client_default="sendmail"
+email_sender_default="hacluster"
+email_recipient_default="root"
+
+: ${email_client=${email_client_default}}
+: ${email_sender=${email_sender_default}}
+email_recipient="${CRM_alert_recipient-${email_recipient_default}}"
+
+node_name=`uname -n`
+cluster_name=`crm_attribute --query -n cluster-name -q`
+email_body=`env | grep CRM_alert_`
+
+if [ ! -z "${email_sender##*@*}" ]; then
+ email_sender="${email_sender}@${node_name}"
+fi
+
+if [ ! -z "${email_recipient##*@*}" ]; then
+ email_recipient="${email_recipient}@${node_name}"
+fi
+
+if [ -z ${CRM_alert_version} ]; then
+ email_subject="Pacemaker version 1.1.15 or later is required for alerts"
+else
+ case ${CRM_alert_kind} in
+ node)
+ email_subject="${CRM_alert_timestamp} ${cluster_name}: Node '${CRM_alert_node}' is now '${CRM_alert_desc}'"
+ ;;
+ fencing)
+ email_subject="${CRM_alert_timestamp} ${cluster_name}: Fencing ${CRM_alert_desc}"
+ ;;
+ resource)
+ if [ ${CRM_alert_interval} = "0" ]; then
+ CRM_alert_interval=""
+ else
+ CRM_alert_interval=" (${CRM_alert_interval})"
+ fi
+
+ if [ ${CRM_alert_target_rc} = "0" ]; then
+ CRM_alert_target_rc=""
+ else
+ CRM_alert_target_rc=" (target: ${CRM_alert_target_rc})"
+ fi
+
+ case ${CRM_alert_desc} in
+ Cancelled) ;;
+ *)
+ email_subject="${CRM_alert_timestamp} ${cluster_name}: Resource operation '${CRM_alert_task}${CRM_alert_interval}' for '${CRM_alert_rsc}' on '${CRM_alert_node}': ${CRM_alert_desc}${CRM_alert_target_rc}"
+ ;;
+ esac
+ ;;
+ attribute)
+ #
+ email_subject="${CRM_alert_timestamp} ${cluster_name}: The '${CRM_alert_attribute_name}' attribute of the '${CRM_alert_node}' node was updated in '${CRM_alert_attribute_value}'"
+ ;;
+ *)
+ email_subject="${CRM_alert_timestamp} ${cluster_name}: Unhandled $CRM_alert_kind alert"
+ ;;
+
+ esac
+fi
+
+if [ ! -z "${email_subject}" ]; then
+ case $email_client in
+ # This sample script supports only sendmail for sending the email.
+ # Support for additional senders can easily be added by adding
+ # new cases here.
+ sendmail)
+ sendmail -t -r "${email_sender}" <<__EOF__
+From: ${email_sender}
+To: ${email_recipient}
+Return-Path: ${email_sender}
+Subject: ${email_subject}
+
+${email_body}
+__EOF__
+ ;;
+ *)
+ ;;
+ esac
+fi
diff --git a/agents/alerts/alert_snmp.sh.sample b/agents/alerts/alert_snmp.sh.sample
new file mode 100644
index 0000000..a140828
--- /dev/null
+++ b/agents/alerts/alert_snmp.sh.sample
@@ -0,0 +1,193 @@
+#!/bin/sh
+#
+# Copyright 2013 Florian CROUZAT <gentoo@floriancrouzat.net>
+# Later changes copyright 2013-2023 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+# Description: Manages a SNMP trap, provided by NTT OSSC as a
+# script under Pacemaker control
+#
+##############################################################################
+# This sample script assumes that only users who already have
+# hacluster-equivalent access to the cluster nodes can edit the CIB. Otherwise,
+# a malicious user could run commands as hacluster by inserting shell code into
+# the trap_options or timestamp-format parameters.
+#
+# Sample configuration (cib fragment in xml notation)
+# ================================
+# <configuration>
+# <alerts>
+# <alert id="snmp_alert" path="/path/to/alert_snmp.sh">
+# <instance_attributes id="config_for_alert_snmp">
+# <nvpair id="trap_node_states" name="trap_node_states" value="all"/>
+# </instance_attributes>
+# <meta_attributes id="config_for_timestamp">
+# <nvpair id="ts_fmt" name="timestamp-format" value="%Y-%m-%d,%H:%M:%S.%01N"/>
+# </meta_attributes>
+# <recipient id="snmp_destination" value="192.168.1.2"/>
+# </alert>
+# </alerts>
+# </configuration>
+# ================================
+#
+# This uses the official Pacemaker MIB.
+# 1.3.6.1.4.1.32723 has been assigned to the project by IANA:
+# http://www.iana.org/assignments/enterprise-numbers
+
+# Defaults for user-configurable values
+trap_binary_default="/usr/bin/snmptrap"
+trap_version_default="2c"
+trap_options_default=""
+trap_community_default="public"
+trap_node_states_default="all"
+trap_fencing_tasks_default="all"
+trap_resource_tasks_default="all"
+trap_monitor_success_default="false"
+trap_add_hires_timestamp_oid_default="true"
+trap_snmp_persistent_dir_default="/var/lib/pacemaker/snmp"
+trap_ignore_int32_default=2147483647 # maximum Integer32 value
+trap_ignore_string_default="n/a" # doesn't conflict with valid XML IDs
+
+# Ensure all user-provided variables have values.
+: ${trap_binary=${trap_binary_default}}
+: ${trap_version=${trap_version_default}}
+: ${trap_options=${trap_options_default}}
+: ${trap_community=${trap_community_default}}
+: ${trap_node_states=${trap_node_states_default}}
+: ${trap_fencing_tasks=${trap_fencing_tasks_default}}
+: ${trap_resource_tasks=${trap_resource_tasks_default}}
+: ${trap_monitor_success=${trap_monitor_success_default}}
+: ${trap_add_hires_timestamp_oid=${trap_add_hires_timestamp_oid_default}}
+: ${trap_snmp_persistent_dir=${trap_snmp_persistent_dir_default}}
+: ${trap_ignore_int32=${trap_ignore_int32_default}}
+: ${trap_ignore_string=${trap_ignore_string_default}}
+
+# Ensure all cluster-provided variables have values, regardless of alert type.
+: ${CRM_alert_node=${trap_ignore_string}}
+: ${CRM_alert_rsc=${trap_ignore_string}}
+: ${CRM_alert_task=${trap_ignore_string}}
+: ${CRM_alert_desc=${trap_ignore_string}}
+: ${CRM_alert_status=${trap_ignore_int32}}
+: ${CRM_alert_rc=${trap_ignore_int32}}
+: ${CRM_alert_target_rc=${trap_ignore_int32}}
+: ${CRM_alert_attribute_name=${trap_ignore_string}}
+: ${CRM_alert_attribute_value=${trap_ignore_string}}
+: ${CRM_alert_version:=""}
+: ${CRM_alert_recipient:=""}
+: ${CRM_alert_kind:=""}
+
+if [ -z "$CRM_alert_version" ]; then
+ echo "$0 must be run by Pacemaker version 1.1.15 or later"
+ exit 0
+fi
+
+# SNMP v3 and above do not use community, which must be empty
+case "$trap_version" in
+ 1|2c) ;;
+ *) trap_community="" ;;
+esac
+
+if [ -z "$CRM_alert_recipient" ]; then
+ echo "$0 requires a recipient configured with the SNMP server IP address"
+ exit 0
+fi
+
+# Echo a high-resolution equivalent of the Pacemaker-provided time values
+# using NetSNMP's DateAndTime specification ("%Y-%m-%d,%H:%M:%S.%01N").
+get_system_date() {
+ : ${CRM_alert_timestamp_epoch=$(date +%s)}
+ : ${CRM_alert_timestamp_usec=0}
+
+ YMDHMS=$(date --date="@${CRM_alert_timestamp_epoch}" +"%Y-%m-%d,%H:%M:%S")
+ USEC=$(echo ${CRM_alert_timestamp_usec} | cut -b 1)
+ echo "${YMDHMS}.${USEC}"
+}
+
+is_in_list() {
+ item_list=`echo "$1" | tr ',' ' '`
+
+ if [ "${item_list}" = "all" ]; then
+ return 0
+ else
+ for act in $item_list
+ do
+ act=`echo "$act" | tr A-Z a-z`
+ [ "$act" != "$2" ] && continue
+ return 0
+ done
+ fi
+ return 1
+}
+
+send_pacemaker_trap() {
+ PREFIX="PACEMAKER-MIB::pacemakerNotification"
+
+ OUTPUT=$("${trap_binary}" -v "${trap_version}" ${trap_options} \
+ ${trap_community:+-c "${trap_community}"} \
+ "${CRM_alert_recipient}" "" \
+ "${PREFIX}Trap" \
+ "${PREFIX}Node" s "${CRM_alert_node}" \
+ "${PREFIX}Resource" s "${CRM_alert_rsc}" \
+ "${PREFIX}Operation" s "${CRM_alert_task}" \
+ "${PREFIX}Description" s "${CRM_alert_desc}" \
+ "${PREFIX}Status" i "${CRM_alert_status}" \
+ "${PREFIX}ReturnCode" i "${CRM_alert_rc}" \
+ "${PREFIX}TargetReturnCode" i "${CRM_alert_target_rc}" \
+ "${PREFIX}AttributeName" s "${CRM_alert_attribute_name}" \
+ "${PREFIX}AttributeValue" s "${CRM_alert_attribute_value}" \
+ ${hires_timestamp} 2>&1)
+
+ if [ $? -ne 0 ]; then
+ echo "${trap_binary} returned error : rc=$? $OUTPUT"
+ fi
+}
+
+if [ "${trap_add_hires_timestamp_oid}" = "true" ]; then
+ hires_timestamp="HOST-RESOURCES-MIB::hrSystemDate s $(get_system_date)"
+fi
+
+if [ -z ${SNMP_PERSISTENT_DIR} ]; then
+ export SNMP_PERSISTENT_DIR="${trap_snmp_persistent_dir}"
+ # mkdir for snmp trap tools.
+ if [ ! -d ${SNMP_PERSISTENT_DIR} ]; then
+ mkdir -p ${SNMP_PERSISTENT_DIR}
+ fi
+fi
+
+case "$CRM_alert_kind" in
+ node)
+ if is_in_list "${trap_node_states}" "${CRM_alert_desc}"; then
+ send_pacemaker_trap
+ fi
+ ;;
+
+ fencing)
+ if is_in_list "${trap_fencing_tasks}" "${CRM_alert_task}"; then
+ send_pacemaker_trap
+ fi
+ ;;
+
+ resource)
+ if is_in_list "${trap_resource_tasks}" "${CRM_alert_task}" && \
+ [ "${CRM_alert_desc}" != "Cancelled" ] ; then
+
+ if [ "${trap_monitor_success}" = "false" ] && \
+ [ "${CRM_alert_rc}" = "${CRM_alert_target_rc}" ] && \
+ [ "${CRM_alert_task}" = "monitor" ]; then
+ exit 0
+ fi
+ send_pacemaker_trap
+ fi
+ ;;
+
+ attribute)
+ send_pacemaker_trap
+ ;;
+
+ *)
+ ;;
+esac