summaryrefslogtreecommitdiffstats
path: root/heartbeat/postfix
diff options
context:
space:
mode:
Diffstat (limited to 'heartbeat/postfix')
-rwxr-xr-xheartbeat/postfix429
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