diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:52:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:52:36 +0000 |
commit | 7de03e4e519705301265c0415b3c0af85263a7ac (patch) | |
tree | 29d819c5227e3619d18a67d2a5dde963b3229dbe /heartbeat/postfix | |
parent | Initial commit. (diff) | |
download | resource-agents-7de03e4e519705301265c0415b3c0af85263a7ac.tar.xz resource-agents-7de03e4e519705301265c0415b3c0af85263a7ac.zip |
Adding upstream version 1:4.13.0.upstream/1%4.13.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'heartbeat/postfix')
-rwxr-xr-x | heartbeat/postfix | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/heartbeat/postfix b/heartbeat/postfix new file mode 100755 index 0000000..6619360 --- /dev/null +++ b/heartbeat/postfix @@ -0,0 +1,429 @@ +#!/bin/sh +# +# Resource script for Postfix +# +# Description: Manages Postfix as an OCF resource in +# an high-availability setup. +# +# Author: Raoul Bhatia <r.bhatia@ipax.at> : Original Author +# License: GNU General Public License (GPL) +# Note: If you want to run multiple Postfix instances, please see +# http://amd.co.at/adminwiki/Postfix#Adding_a_Second_Postfix_Instance_on_one_Server +# http://www.postfix.org/postconf.5.html +# +# +# usage: $0 {start|stop|reload|monitor|validate-all|meta-data} +# +# The "start" arg starts a Postfix instance +# +# The "stop" arg stops it. +# +# OCF parameters: +# OCF_RESKEY_binary +# OCF_RESKEY_config_dir +# OCF_RESKEY_parameters +# +########################################################################## + +# Initialization: + +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +# Parameter defaults + +OCF_RESKEY_binary_default="/usr/sbin/postfix" +OCF_RESKEY_config_dir_default="" +OCF_RESKEY_parameters_default="" + +: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}} +: ${OCF_RESKEY_config_dir=${OCF_RESKEY_config_dir_default}} +: ${OCF_RESKEY_parameters=${OCF_RESKEY_parameters_default}} + +USAGE="Usage: $0 {start|stop|reload|monitor|validate-all|meta-data}"; + +########################################################################## + +# Check availability of the runuser command, otherwise use su +if [ -x /sbin/runuser ]; then + SU=runuser +else + SU=su +fi + +usage() { + echo $USAGE >&2 +} + +meta_data() { + cat <<END +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="postfix" version="0.1"> +<version>1.0</version> +<longdesc lang="en"> +This script manages Postfix as an OCF resource in a high-availability setup. +</longdesc> +<shortdesc lang="en">Manages a highly available Postfix mail server instance</shortdesc> + +<parameters> + +<parameter name="binary" unique="0" required="0"> +<longdesc lang="en"> +Full path to the Postfix binary. +For example, "/usr/sbin/postfix". +</longdesc> +<shortdesc lang="en">Full path to Postfix binary</shortdesc> +<content type="string" default="${OCF_RESKEY_binary_default}" /> +</parameter> + +<parameter name="config_dir" unique="1" required="0"> +<longdesc lang="en"> +Full path to a Postfix configuration directory. +For example, "/etc/postfix". +</longdesc> +<shortdesc lang="en">Full path to configuration directory</shortdesc> +<content type="string" default="${OCF_RESKEY_config_dir_default}" /> +</parameter> + +<parameter name="parameters" unique="0" required="0"> +<longdesc lang="en"> +The Postfix daemon may be called with additional parameters. +Specify any of them here. +</longdesc> +<shortdesc lang="en"></shortdesc> +<content type="string" default="${OCF_RESKEY_parameters_default}" /> +</parameter> + +</parameters> + +<actions> +<action name="start" timeout="20s" /> +<action name="stop" timeout="20s" /> +<action name="reload" timeout="20s" /> +<action name="monitor" depth="0" timeout="20s" interval="60s" /> +<action name="validate-all" timeout="20s" /> +<action name="meta-data" timeout="5s" /> +</actions> +</resource-agent> +END +} + +postfix_running() { + local loglevel + loglevel=${1:-err} + + # run Postfix status if available + if ocf_is_true $status_support; then + $binary $OPTION_CONFIG_DIR status 2>&1 + ret=$? + if [ $ret -ne 0 ]; then + ocf_log $loglevel "Postfix status: " $ret + fi + return $ret + fi + + # manually check Postfix's pid + PIDFILE=${queue_dir}/pid/master.pid + if [ -f $PIDFILE ]; then + PID=`head -n 1 $PIDFILE` + kill -s 0 $PID >/dev/null 2>&1 && [ `ps -p $PID | grep master | wc -l` -eq 1 ] + return $? + fi + + # Postfix is not running + false +} + +postfix_start() +{ + # if Postfix is running return success + if postfix_running info; then + ocf_log info "Postfix already running." + return $OCF_SUCCESS + fi + + # start Postfix + $binary $OPTIONS start >/dev/null 2>&1 + ret=$? + + if [ $ret -ne 0 ]; then + ocf_exit_reason "Postfix returned error: $ret" + return $OCF_ERR_GENERIC + fi + + # grant some time for startup/forking the sub processes + # and loop initial monitoring until success or timeout + while true; do + sleep 1 + # break if postfix is up and running; log failure otherwise + postfix_running info && break + ocf_log info "Postfix failed initial monitor action: " $ret + done + + ocf_log info "Postfix started." + return $OCF_SUCCESS +} + + +postfix_stop() +{ + # if Postfix is not running return success + if ! postfix_running info; then + ocf_log info "Postfix already stopped." + return $OCF_SUCCESS + fi + + # stop Postfix + $binary $OPTIONS stop >/dev/null 2>&1 + ret=$? + + if [ $ret -ne 0 ]; then + ocf_exit_reason "Postfix returned an error while stopping: $ret" + return $OCF_ERR_GENERIC + fi + + # grant some time for shutdown and recheck 5 times + for i in 1 2 3 4 5; do + if postfix_running info; then + sleep 1 + else + break + fi + done + + # escalate to abort if we did not stop by now + # @TODO shall we loop here too? + if postfix_running info; then + ocf_exit_reason "Postfix failed to stop. Escalating to 'abort'." + + $binary $OPTIONS abort >/dev/null 2>&1; ret=$? + sleep 5 + + # postfix abort did not succeed + if postfix_running; then + ocf_exit_reason "Postfix failed to abort." + return $OCF_ERR_GENERIC + fi + fi + + ocf_log info "Postfix stopped." + return $OCF_SUCCESS +} + +postfix_reload() +{ + if postfix_running; then + ocf_log info "Reloading Postfix." + $binary $OPTIONS reload + fi +} + +postfix_monitor() +{ + local status_loglevel="err" + + # Set loglevel to info during probe + if ocf_is_probe; then + status_loglevel="info" + fi + + if postfix_running $status_loglevel; then + return $OCF_SUCCESS + fi + + return $OCF_NOT_RUNNING +} + +postfix_validate_all() +{ + # check that the Postfix binaries exist and can be executed + check_binary "$binary" + check_binary "postconf" + + # if true, run in-depth directory checks + dir_check=true + + # check config_dir and alternate_config_directories parameter + if [ "x$config_dir" != "x" ]; then + if [ ! -d "$config_dir" ]; then + if ocf_is_probe; then + ocf_log info "Postfix configuration directory '$config_dir' not readable during probe." + # skip in-depth directory checks if config file isn't readable during probe + dir_check=false + else + ocf_exit_reason "Postfix configuration directory '$config_dir' does not exist or is not readable." + return $OCF_ERR_INSTALLED + fi + fi + + alternate_config_directories=`postconf -h alternate_config_directories 2>/dev/null | grep "$config_dir/\?"` + if [ "x$alternate_config_directories" = "x" ]; then + ocf_exit_reason "Postfix main configuration must contain correct 'alternate_config_directories' parameter." + return $OCF_ERR_INSTALLED + fi + fi + + # check spool/queue and data directories (if applicable) + # this is required because "postfix check" does not catch all errors + if ocf_is_true $dir_check; then + if [ ! -d "$queue_dir" ]; then + if ocf_is_probe; then + ocf_log info "Postfix queue directory '$queue_dir' not readable during probe." + else + ocf_exit_reason "Postfix queue directory '$queue_dir' does not exist or is not readable." + return $OCF_ERR_INSTALLED + fi + fi + + if ocf_is_true $status_support; then + data_dir=`postconf $OPTION_CONFIG_DIR -h data_directory 2>/dev/null` + data_dir_count=`echo "$data_dir" | tr ',' ' ' | wc -w` + if [ $data_dir_count -gt 1 ]; then + ocf_exit_reason "Postfix data directory '$orig_data_dir' cannot be set to multiple directories." + return $OCF_ERR_INSTALLED + fi + if [ ! -d "$data_dir" ]; then + if ocf_is_probe; then + ocf_log info "Postfix data directory '$data_dir' not readable during probe." + else + ocf_exit_reason "Postfix data directory '$data_dir' does not exist or is not readable." + return $OCF_ERR_INSTALLED + fi + fi + fi + + # check directory permissions + if ocf_is_true $status_support; then + user=`postconf $OPTION_CONFIG_DIR -h mail_owner 2>/dev/null` + for dir in $data_dir; do + if ! $SU -s /bin/sh - $user -c "test -w $dir"; then + if ocf_is_probe; then + ocf_log info "Directory '$dir' is not writable by user '$user' during probe." + else + ocf_exit_reason "Directory '$dir' is not writable by user '$user'." + return $OCF_ERR_PERM; + fi + fi + done + fi + fi + + # run Postfix internal check, if not probing + if ! ocf_is_probe; then + $binary $OPTIONS check >/dev/null 2>&1 + ret=$? + if [ $ret -ne 0 ]; then + ocf_exit_reason "Postfix 'check' failed: $ret" + return $OCF_ERR_GENERIC + fi + fi + + return $OCF_SUCCESS +} + +# +# Main +# + +if [ $# -ne 1 ]; then + usage + exit $OCF_ERR_ARGS +fi + +binary=$OCF_RESKEY_binary +config_dir=$OCF_RESKEY_config_dir +parameters=$OCF_RESKEY_parameters + + +# handle parameters +case $1 in + meta-data) meta_data + exit $OCF_SUCCESS + ;; + + usage|help) usage + exit $OCF_SUCCESS + ;; +esac + +# build Postfix options string *outside* to access from each method +OPTIONS='' +OPTION_CONFIG_DIR='' + +# check for Postfix's postconf binary +check_binary "postconf" + +# check if the Postfix config_dir exist +if [ "x$config_dir" != "x" ]; then + # remove all trailing slashes to ease "postconf alternate_config_directories" match + config_dir=`echo $config_dir | sed 's/\/*$//'` + + # reset config_dir if it equals Postfix's default config_directory + postconf -h config_directory 2>/dev/null | grep -q "^$config_dir/\?$" + if [ $? -eq 0 ]; then + config_dir="" + fi + + # set OPTIONS if config_dir is still set + # save OPTION_CONFIG_DIR seperatly + if [ "x$config_dir" != "x" ]; then + OPTION_CONFIG_DIR="-c $config_dir" + OPTIONS=$OPTION_CONFIG_DIR + fi +fi + +# add all additional parameters to options string +if [ "x$parameters" != "x" ]; then + OPTIONS="$OPTIONS $parameters" +fi + +# important directories, used in different methods +queue_dir=`postconf $OPTION_CONFIG_DIR -h queue_directory 2>/dev/null` + +# check Postfix version and status support +status_support=false +postfix_version=`postconf -h mail_version 2>/dev/null` +ocf_version_cmp "$postfix_version" "2.5.0" +ret=$? + +# we need Postfix 2.5.0 or greater for status/data_directory support +if [ $ret -eq 1 -o $ret -eq 2 ]; then + status_support=true +fi + + +postfix_validate_all +ret=$? + +LSB_STATUS_STOPPED=3 +if [ $ret -ne $OCF_SUCCESS ]; then + case $1 in + stop) exit $OCF_SUCCESS ;; + *) exit $ret;; + esac +fi + +case $1 in + monitor) postfix_monitor + exit $? + ;; + start) postfix_start + exit $? + ;; + + stop) postfix_stop + exit $? + ;; + + reload) postfix_reload + exit $? + ;; + + validate-all) exit $OCF_SUCCESS + ;; + + *) usage + exit $OCF_ERR_UNIMPLEMENTED + ;; +esac |