summaryrefslogtreecommitdiffstats
path: root/heartbeat/slapd.in
diff options
context:
space:
mode:
Diffstat (limited to 'heartbeat/slapd.in')
-rw-r--r--heartbeat/slapd.in594
1 files changed, 594 insertions, 0 deletions
diff --git a/heartbeat/slapd.in b/heartbeat/slapd.in
new file mode 100644
index 0000000..ffccd1d
--- /dev/null
+++ b/heartbeat/slapd.in
@@ -0,0 +1,594 @@
+#!@BASH_SHELL@
+#
+# Stand-alone LDAP Daemon (slapd)
+#
+# Description: Manages Stand-alone LDAP Daemon (slapd) as an OCF resource in
+# an high-availability setup.
+#
+# Authors: Jeroen Koekkoek
+# nozawat@gmail.com
+# John Keith Hohm
+#
+# License: GNU General Public License (GPL)
+# Copyright: (C) 2011 Pagelink B.V.
+#
+# The OCF code was inspired by the Postfix resource script written by
+# Raoul Bhatia <r.bhatia@ipax.at>.
+#
+# The code for managing the slapd instance is based on the the slapd init
+# script found in Debian GNU/Linux 6.0.
+#
+# OCF parameters:
+# OCF_RESKEY_slapd
+# OCF_RESKEY_ldapsearch
+# OCF_RESKEY_config
+# OCF_RESKEY_pidfile
+# OCF_RESKEY_user
+# OCF_RESKEY_group
+# OCF_RESKEY_services
+# OCF_RESKEY_watch_suffix
+# OCF_RESKEY_ignore_suffix
+# OCF_RESKEY_bind_dn
+# OCF_RESKEY_password
+# OCF_RESKEY_parameters
+# OCF_RESKEY_stop_escalate
+# OCF_RESKEY_maxfiles
+#
+################################################################################
+
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Parameter defaults
+
+OCF_RESKEY_slapd_default="/usr/sbin/slapd"
+OCF_RESKEY_ldapsearch_default="ldapsearch"
+OCF_RESKEY_config_default=""
+OCF_RESKEY_pidfile_default=""
+OCF_RESKEY_user_default=""
+OCF_RESKEY_group_default=""
+OCF_RESKEY_services_default="ldap:///"
+OCF_RESKEY_watch_suffix_default=""
+OCF_RESKEY_ignore_suffix_default=""
+OCF_RESKEY_bind_dn_default=""
+OCF_RESKEY_password_default=""
+OCF_RESKEY_parameters_default=""
+OCF_RESKEY_stop_escalate_default="15"
+OCF_RESKEY_maxfiles_default=""
+
+: ${OCF_RESKEY_slapd=${OCF_RESKEY_slapd_default}}
+: ${OCF_RESKEY_ldapsearch=${OCF_RESKEY_ldapsearch_default}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+: ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}}
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
+: ${OCF_RESKEY_services=${OCF_RESKEY_services_default}}
+: ${OCF_RESKEY_watch_suffix=${OCF_RESKEY_watch_suffix_default}}
+: ${OCF_RESKEY_ignore_suffix=${OCF_RESKEY_ignore_suffix_default}}
+: ${OCF_RESKEY_bind_dn=${OCF_RESKEY_bind_dn_default}}
+: ${OCF_RESKEY_password=${OCF_RESKEY_password_default}}
+: ${OCF_RESKEY_parameters=${OCF_RESKEY_parameters_default}}
+: ${OCF_RESKEY_stop_escalate=${OCF_RESKEY_stop_escalate_default}}
+: ${OCF_RESKEY_maxfiles=${OCF_RESKEY_maxfiles_default}}
+
+USAGE="Usage: $0 {start|stop|status|monitor|validate-all|meta-data}"
+ORIG_IFS=$IFS
+NEWLINE='
+'
+
+################################################################################
+
+usage() {
+ echo $USAGE >&2
+}
+
+meta_data()
+{
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="slapd" version="0.1">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for Stand-alone LDAP Daemon (slapd). It manages a slapd instance as an OCF resource.
+</longdesc>
+<shortdesc lang="en">Manages a Stand-alone LDAP Daemon (slapd) instance</shortdesc>
+
+<parameters>
+
+<parameter name="slapd" unique="0" required="0">
+<longdesc lang="en">
+Full path to the slapd binary.
+For example, "/usr/sbin/slapd".
+</longdesc>
+<shortdesc lang="en">Full path to slapd binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_slapd_default}" />
+</parameter>
+
+<parameter name="ldapsearch" unique="0" required="0">
+<longdesc lang="en">
+Full path to the ldapsearch binary.
+For example, "/usr/bin/ldapsearch".
+</longdesc>
+<shortdesc lang="en">Full path to ldapsearch binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_ldapsearch_default}" />
+</parameter>
+
+<parameter name="config" required="0" unique="1">
+<longdesc lang="en">
+Full path to a slapd configuration directory or a slapd configuration file.
+For example, "/etc/ldap/slapd.d" or "/etc/ldap/slapd.conf".
+</longdesc>
+<shortdesc lang="en">Full path to configuration directory or file</shortdesc>
+<content type="string" default="${OCF_RESKEY_config_default}"/>
+</parameter>
+
+<parameter name="pidfile" required="0" unique="0">
+<longdesc lang="en">
+File to read the PID from; read from olcPidFile/pidfile in config if not set.
+</longdesc>
+<shortdesc lang="en">File to read PID from</shortdesc>
+<content type="string" default="${OCF_RESKEY_pidfile_default}" />
+</parameter>
+
+<parameter name="user" unique="0" required="0">
+<longdesc lang="en">
+User name or id slapd will run with. The group id is also changed to this
+user's gid, unless the group parameter is used to override.
+</longdesc>
+<shortdesc lang="en">User name or id slapd will run with</shortdesc>
+<content type="string" default="${OCF_RESKEY_user_default}" />
+</parameter>
+
+<parameter name="group" unique="0" required="0">
+<longdesc lang="en">
+Group name or id slapd will run with.
+</longdesc>
+<shortdesc lang="en">Group name or id slapd will run with</shortdesc>
+<content type="string" default="${OCF_RESKEY_group_default}" />
+</parameter>
+
+<parameter name="services" required="0" unique="1">
+<longdesc lang="en">
+LDAP (and other scheme) URLs slapd will serve.
+For example, "ldap://127.0.0.1:389 ldaps:/// ldapi:///"
+</longdesc>
+<shortdesc lang="en">LDAP (and other scheme) URLs to serve</shortdesc>
+<content type="string" default="${OCF_RESKEY_services_default}"/>
+</parameter>
+
+<parameter name="watch_suffix" required="0" unique="0">
+<longdesc lang="en">
+Suffix (database backend) that will be monitored for availability. Multiple
+suffixes can be specified by providing a space separated list. By providing one
+or more suffixes here, the ignore_suffix parameter is discarded. All suffixes
+will be monitored if left blank.
+</longdesc>
+<shortdesc lang="en">Suffix that will be monitored for availability.</shortdesc>
+<content type="string" default="${OCF_RESKEY_watch_suffix_default}"/>
+</parameter>
+
+<parameter name="ignore_suffix" required="0" unique="0">
+<longdesc lang="en">
+Suffix (database backend) that will not be monitored for availability. Multiple
+suffixes can be specified by providing a space separated list. No suffix will
+be excluded if left blank.
+</longdesc>
+<shortdesc lang="en">Suffix that will not be monitored for availability.</shortdesc>
+<content type="string" default="${OCF_RESKEY_ignore_suffix_default}"/>
+</parameter>
+
+<parameter name="bind_dn" required="0" unique="0">
+<longdesc lang="en">
+Distinguished Name used to bind to the LDAP directory for testing. Leave blank
+to bind to the LDAP directory anonymously.
+</longdesc>
+<shortdesc lang="en">Distinguished Name used to bind to the LDAP directory for testing.</shortdesc>
+<content type="string" default="${OCF_RESKEY_bind_dn_default}"/>
+</parameter>
+
+<parameter name="password" required="0" unique="0">
+<longdesc lang="en">
+Password used to bind to the LDAP directory for testing.
+</longdesc>
+<shortdesc lang="en">Password used to bind to the LDAP directory for testing.</shortdesc>
+<content type="string" default="${OCF_RESKEY_password_default}"/>
+</parameter>
+
+<parameter name="parameters" unique="0" required="0">
+<longdesc lang="en">
+slapd may be called with additional parameters.
+Specify any of them here.
+</longdesc>
+<shortdesc lang="en">Any additional parameters to slapd.</shortdesc>
+<content type="string" default="${OCF_RESKEY_parameters_default}" />
+</parameter>
+
+<parameter name="stop_escalate" unique="0" required="0">
+<longdesc lang="en">
+Number of seconds to wait for shutdown (using SIGTERM) before resorting to
+SIGKILL
+</longdesc>
+<shortdesc lang="en">Seconds before stop escalation to KILL</shortdesc>
+<content type="integer" default="${OCF_RESKEY_stop_escalate_default}" />
+</parameter>
+
+<parameter name="maxfiles">
+<longdesc lang="en">
+Maximum number of open files (for ulimit -n)
+</longdesc>
+<shortdesc lang="en">Max open files</shortdesc>
+<content type="string" default="${OCF_RESKEY_maxfiles_default}" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" 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
+}
+
+watch_suffix()
+{
+ local rc
+
+ if [ -n "$OCF_RESKEY_watch_suffix" ]; then
+ if echo "'$OCF_RESKEY_watch_suffix'" | grep "'$1'" >/dev/null 2>&1; then
+ rc=0
+ else
+ rc=1
+ fi
+ else
+ if echo "'$OCF_RESKEY_ignore_suffix'" | grep "'$1'" >/dev/null 2>&1; then
+ rc=1
+ else
+ rc=0
+ fi
+ fi
+
+ return $rc
+}
+
+slapd_pid()
+{
+ local pid
+
+ if [ -f "$pid_file" ]; then
+ pid=`head -n 1 "$pid_file" 2>/dev/null`
+
+ if [ "X$pid" != "X" ]; then
+ echo "$pid"
+ return $OCF_SUCCESS
+ fi
+
+ ocf_exit_reason "slapd pid file '$pid_file' empty."
+ return $OCF_ERR_GENERIC
+ fi
+
+ ocf_log info "slapd pid file '$pid_file' does not exist."
+ return $OCF_NOT_RUNNING
+}
+
+slapd_status()
+{
+ local pid=$1
+
+ if ! kill -0 $pid >/dev/null 2>&1; then
+ return $OCF_NOT_RUNNING
+ else
+ return $OCF_SUCCESS
+ fi
+}
+
+slapd_start()
+{
+ local options
+ local reason
+ local rc
+ local state
+
+ slapd_status `slapd_pid`; state=$?
+
+ if [ $state -eq $OCF_SUCCESS ]; then
+ ocf_log info "slapd already running."
+ return $state
+ elif [ $state -eq $OCF_ERR_GENERIC ]; then
+ return $state
+ fi
+
+ options="-u $user -g $group"
+
+ if [ -d "$config" ]; then
+ options="$options -F $config"
+ elif [ -f "$config" ]; then
+ options="$options -f $config"
+ else
+ ocf_exit_reason "slapd configuration '$config' does not exist."
+ return $OCF_ERR_INSTALLED
+ fi
+
+ if [ -n "$parameters" ]; then
+ options="$options $parameters"
+ fi
+
+ if [ -n "$OCF_RESKEY_maxfiles" ]; then
+ ulimit -n $OCF_RESKEY_maxfiles
+ u_rc=$?
+ if [ "$u_rc" -ne 0 ]; then
+ ocf_log warn "Could not set ulimit for open files for slapd to '$OCF_RESKEY_maxfiles'"
+ fi
+ fi
+
+ if [ -n "$services" ]; then
+ $slapd -h "$services" $options 2>&1; rc=$?
+ else
+ $slapd $options 2>&1; rc=$?
+ fi
+
+ if [ $rc -ne 0 ]; then
+ ocf_exit_reason "slapd returned error."
+
+ return $OCF_ERR_GENERIC
+ fi
+
+ while true; do
+ slapd_monitor start
+ if [ $? = "$OCF_SUCCESS" ]; then
+ break
+ fi
+ sleep 1
+ done
+
+ ocf_log info "slapd started."
+
+ return $OCF_SUCCESS
+}
+
+slapd_stop()
+{
+ local pid
+ local rc
+ local state
+
+ pid=`slapd_pid`; slapd_status $pid; state=$?
+
+ if [ $state -eq $OCF_NOT_RUNNING ]; then
+ ocf_log info "slapd already stopped."
+ return $OCF_SUCCESS
+ elif [ $state -eq $OCF_ERR_GENERIC ]; then
+ return $state
+ fi
+
+ ocf_stop_processes TERM $OCF_RESKEY_stop_escalate $pid; rc=$?
+ if [ $rc -eq 1 ]; then
+ ocf_log err "cannot stop slapd."
+ return $OCF_ERR_GENERIC
+ fi
+
+ if [ -f "$pid_file" ]; then
+ rm -f "$pid_file" >/dev/null 2>&1
+ fi
+
+ ocf_log info "slapd stopped."
+ return $OCF_SUCCESS
+}
+
+slapd_monitor()
+{
+ local options
+ local rc
+ local state
+ local suffix
+ local suffixes
+ local err_option="-info"
+
+ slapd_status `slapd_pid`; state=$?
+ if [ $state -eq $OCF_NOT_RUNNING ]; then
+ if [ -z "$1" ];then
+ if ! ocf_is_probe; then
+ ocf_exit_reason "slapd process not found."
+ fi
+ fi
+ return $state
+ elif [ $state -ne $OCF_SUCCESS ]; then
+ ocf_exit_reason "slapd returned error."
+ return $state
+ fi
+
+ if [ -d "$config" ]; then
+ for suffix in `find "$config"/'cn=config' -type f -name olcDatabase* -exec \
+ sed -ne 's/^[[:space:]]*olcSuffix:[[:space:]]\+\(.\+\)/\1/p' {} \;`
+ do
+ suffix=${suffix#\"*}
+ suffix=${suffix%\"*}
+
+ if watch_suffix $suffix; then
+ suffixes="$suffixes $suffix"
+ fi
+ done
+
+ elif [ -f "$config" ]; then
+ for suffix in `sed -ne 's/^[[:space:]]*suffix[[:space:]]\+\(.\+\)/\1/p' "$config"`
+ do
+ suffix=${suffix#\"*}
+ suffix=${suffix%\"*}
+
+ if watch_suffix $suffix; then
+ suffixes="$suffixes $suffix"
+ fi
+ done
+
+ else
+ if ocf_is_probe; then
+ ocf_log info "slapd configuration '$config' does not exist during probe."
+ else
+ ocf_exit_reason "slapd configuration '$config' does not exist."
+ return $OCF_ERR_INSTALLED
+ fi
+ fi
+
+ options="-LLL -s base -x"
+
+ if [ -n "$bind_dn" ]; then
+ options="$options -D $bind_dn -w $password"
+ fi
+
+ [ -z "$1" ] && err_option=""
+ for suffix in $suffixes; do
+ ocf_run -q $err_option "$ldapsearch" -H "$services" -b "$suffix" $options >/dev/null 2>&1; rc=$?
+
+ case "$rc" in
+ "0")
+ ocf_log debug "slapd database with suffix '$suffix' reachable"
+ ;;
+ "49")
+ ocf_exit_reason "slapd database with suffix '$suffix' unreachable. Invalid credentials."
+ return $OCF_ERR_CONFIGURED
+ ;;
+ *)
+ if [ -z "$1" ] || [ -n "$1" -a $rc -ne 1 ]; then
+ ocf_exit_reason "slapd database with suffix '$suffix' unreachable. exit code ($rc)"
+ fi
+ state=$OCF_ERR_GENERIC
+ ;;
+ esac
+ done
+
+ return $state
+}
+
+slapd_validate_all()
+{
+ check_binary "$slapd"
+ check_binary "$ldapsearch"
+
+ if [ -z "$pid_file" ]; then
+ if [ -d "$config" ]; then
+ pid_file=`sed -ne \
+ 's/^olcPidFile:[[:space:]]\+\(.\+\)[[:space:]]*/\1/p' \
+ "$config"/'cn=config.ldif' 2>/dev/null`
+ elif [ -f "$config" ]; then
+ pid_file=`sed -ne \
+ 's/^pidfile[[:space:]]\+\(.\+\)/\1/p' \
+ "$config" 2>/dev/null`
+ else
+ if ocf_is_probe; then
+ ocf_log info "slapd configuration '$config' does not exist during probe."
+ else
+ ocf_exit_reason "slapd configuration '$config' does not exist."
+ return $OCF_ERR_INSTALLED
+ fi
+ fi
+ fi
+
+ if [ -z "$user" ]; then
+ user=`id -nu 2>/dev/null`
+ elif ! id "$user" >/dev/null 2>&1; then
+ ocf_exit_reason "slapd user '$user' does not exist"
+ return $OCF_ERR_INSTALLED
+ fi
+
+ if [ -z "$group" ]; then
+ group=`id -ng 2>/dev/null`
+ elif ! grep "^$group:" /etc/group >/dev/null 2>&1; then
+ ocf_exit_reason "slapd group '$group' does not exist"
+ return $OCF_ERR_INSTALLED
+ fi
+
+ pid_dir=`dirname "$pid_file"`
+ if [ ! -d "$pid_dir" ]; then
+ mkdir -p "$pid_dir"
+ chown -R "$user" "$pid_dir"
+ chgrp -R "$group" "$pid_dir"
+ fi
+
+ return $OCF_SUCCESS
+}
+
+#
+# Main
+#
+
+slapd=$OCF_RESKEY_slapd
+ldapsearch=$OCF_RESKEY_ldapsearch
+config=$OCF_RESKEY_config
+user=$OCF_RESKEY_user
+group=$OCF_RESKEY_group
+services=$OCF_RESKEY_services
+bind_dn=$OCF_RESKEY_bind_dn
+password=$OCF_RESKEY_password
+parameters=$OCF_RESKEY_parameters
+pid_file=$OCF_RESKEY_pidfile
+
+if [ -z "$config" ]; then
+ config_dirname="/etc/ldap"
+ if [ -e "/etc/openldap" ]; then
+ config_dirname="/etc/openldap"
+ fi
+
+ config="$config_dirname/slapd.conf"
+ if [ -e "$config_dirname/slapd.d" ]; then
+ config="$config_dirname/slapd.d"
+ fi
+fi
+
+if [ $# -ne 1 ]; then
+ usage
+ exit $OCF_ERR_ARGS
+fi
+
+case $1 in
+ meta-data)
+ meta_data
+ exit $OCF_SUCCESS
+ ;;
+ usage|help)
+ usage
+ exit $OCF_SUCCESS
+ ;;
+esac
+
+slapd_validate_all
+rc=$?
+[ $rc -eq $OCF_SUCCESS ] || exit $rc
+
+case $1 in
+ status)
+ slapd_status `slapd_pid`; state=$?
+
+ if [ $state -eq $OCF_SUCCESS ]; then
+ ocf_log debug "slapd is running."
+ elif [ $state -eq $OCF_NOT_RUNNING ]; then
+ ocf_log debug "slapd is stopped."
+ fi
+
+ exit $state
+ ;;
+ start)
+ slapd_start
+ exit $?
+ ;;
+ stop)
+ slapd_stop
+ exit $?
+ ;;
+ monitor)
+ slapd_monitor; state=$?
+ exit $state
+ ;;
+ validate-all)
+ exit $OCF_SUCCESS
+ ;;
+ *)
+ usage
+ exit $OCF_ERR_UNIMPLEMENTED
+ ;;
+esac