1#!/usr/local/bin/bash
2
3# Authors:
4#  Andrew Beekhof <abeekhof@redhat.com>
5#  Fabio M. Di Nitto <fdinitto@redhat.com>
6#
7# License: Revised BSD
8
9# chkconfig: - 99 01
10# description: Pacemaker Cluster Manager
11# processname: pacemakerd
12#
13### BEGIN INIT INFO
14# Provides:		pacemaker
15# Required-Start:	$network $remote_fs corosync
16# Should-Start:		$syslog
17# Required-Stop:	$network $remote_fs corosync
18# Default-Start:
19# Default-Stop:
20# Short-Description:	Starts and stops Pacemaker Cluster Manager.
21# Description:		Starts and stops Pacemaker Cluster Manager.
22### END INIT INFO
23
24desc="Pacemaker Cluster Manager"
25prog="pacemakerd"
26
27# set secure PATH
28PATH="/sbin:/bin:/usr/sbin:/usr/bin:@sbindir@"
29
30checkrc() {
31    if [ $? = 0 ]; then
32	success
33    else
34	failure
35    fi
36}
37
38success()
39{
40	echo -ne "[  OK  ]\r"
41}
42
43failure()
44{
45	echo -ne "[FAILED]\r"
46}
47
48log()
49{
50    logger -t pacemaker -p daemon.notice "$*"
51}
52
53notify()
54{
55    log "$*"
56    echo -n "$*"
57}
58
59status()
60{
61	pid=$(pidof $1 2>/dev/null)
62	local rtrn=$?
63	if [ $rtrn -ne 0 ]; then
64		echo "$1 is stopped"
65		if [ -f "@localstatedir@/run/$prog.pid" ]; then
66			rtrn=1
67		else
68			rtrn=3
69		fi
70	else
71		echo "$1 (pid $pid) is running..."
72	fi
73	return $rtrn
74}
75
76if [ -d @CONFIGDIR@ ]; then
77	[ -f @INITDIR@/functions ] && . @INITDIR@/functions
78set -a
79	[ -f @CONFIGDIR@/pacemaker ] && . @CONFIGDIR@/pacemaker
80	[ -f @CONFIGDIR@/sbd ] && . @CONFIGDIR@/sbd
81set +a
82fi
83
84LOCK_DIR="."
85if [ -d "@localstatedir@/lock/subsys" ]; then
86	LOCK_DIR="@localstatedir@/lock/subsys"
87elif [ -d "@localstatedir@/lock" ]; then
88	LOCK_DIR="@localstatedir@/lock"
89fi
90[ -z "$LOCK_FILE" ] && LOCK_FILE="$LOCK_DIR/pacemaker"
91
92# Unless specified otherwise, assume cman is in use if cluster.conf exists
93if [ x = "x$PCMK_STACK" -a -f "@sysconfdir@/cluster/cluster.conf" ]; then
94    PCMK_STACK=cman
95fi
96
97# Check if there is a valid watchdog-device configured in sbd config
98if [ x != "x$SBD_WATCHDOG_DEV" -a "/dev/null" != "$SBD_WATCHDOG_DEV" -a -c "$SBD_WATCHDOG_DEV" ]; then
99	# enhance for unavailable chkconfig - don't touch sbd for now
100	if chkconfig --list sbd_helper 2>/dev/null | grep -q ":on"; then
101		SBD_SERVICE=sbd_helper
102	fi
103fi
104
105start()
106{
107	notify "Starting $desc"
108
109	# most recent distributions use tmpfs for $@localstatedir@/run
110	# to avoid to clean it up on every boot.
111	# they also assume that init scripts will create
112	# required subdirectories for proper operations
113	mkdir -p "@localstatedir@/run"
114
115	if status $prog > /dev/null 2>&1; then
116		success
117	else
118		$prog > /dev/null 2>&1 &
119
120		# Time to connect to corosync and fail
121		sleep 5
122
123		if status $prog > /dev/null 2>&1; then
124			touch "$LOCK_FILE"
125			pidof $prog > "@localstatedir@/run/$prog.pid"
126			success
127		else
128			failure
129			rtrn=1
130		fi
131	fi
132	echo
133}
134
135cman_pre_start()
136{
137    # start cman if it's not running
138    service cman status >/dev/null 2>&1
139    if [ $? -ne 0 ]; then
140	service cman start
141	if [ $? -ne 0 ]; then
142	    notify "Aborting startup of $desc"
143	    echo
144	    exit 1
145	fi
146    fi
147
148    # start cman's friends if they're not running but were configured to start automatically
149    for cservice in cmirrord clvmd gfs2 $SBD_SERVICE; do
150	chkconfig --list $cservice 2>/dev/null | grep -q ":on"
151	if [ $? -eq 0 ]; then
152	    service $cservice status >/dev/null 2>&1
153	    if [ $? -ne 0 ]; then
154		log "Attempting to start $cservice"
155		service $cservice start
156	    fi
157	fi
158    done
159}
160
161cman_pre_stop()
162{
163    # if cman is not running there is nothing we need to do here
164    service cman status >/dev/null 2>&1
165    if [ $? -ne 0 ]; then
166	return
167    fi
168
169    has_lvm=`crm_resource -c | grep Resource: | grep LVM`
170
171    # migrate resources to another node or shut them down
172    cname=`crm_node --name`
173    crm_attribute -N $cname -n standby -v true -l reboot
174    notify "Waiting for shutdown of managed resources"
175
176
177    while [ 1 = 1 ]; do
178	# 0x0000000000000002 means managed
179	active=`crm_resource -c | grep Resource: | grep 0x...............[2367] | awk '{print $9}' | grep "^${cname}$" | wc -l`
180	if [ $active = 0 ]; then
181	    break;
182	fi
183	sleep 2
184	echo -n "."
185    done
186    success
187    echo
188
189    if [ -d /sys/kernel/dlm/ ]; then
190	lockspace="$(ls -1 /sys/kernel/dlm/)"
191	if [ -n "$lockspace" ]; then
192	    notify "DLM lockspace still in use"
193	    echo ""
194
195	    for cservice in gfs2 clvmd cmirrord; do
196		service $cservice status >/dev/null 2>&1
197		if [ $? -eq 0 ]; then
198		    if [ -n "$has_lvm" ] && [ "$cservice" = "clvmd" ]; then
199			# allow HA-LVM to take a lock on vg/lv before clvmd can exit
200			notify "Waiting for LVM services to start somewhere else"
201			sleep 15
202			success
203		    fi
204		    log "Attempting to shutdown $cservice"
205		    service $cservice stop
206		fi
207	    done
208	fi
209    fi
210
211    notify "Leaving fence domain"
212    fence_tool leave -w 10
213    checkrc
214
215    fenced=$(pidof fenced)
216    notify "Stopping fenced $fenced"
217    kill -KILL $fenced > /dev/null 2>&1
218    checkrc
219}
220
221stop()
222{
223	shutdown_prog=$prog
224	if ! status $prog > /dev/null 2>&1; then
225	    shutdown_prog="crmd"
226	fi
227
228	if status $shutdown_prog > /dev/null 2>&1; then
229	    notify "Signaling $desc to terminate"
230	    kill -TERM $(pidof $prog) > /dev/null 2>&1
231	    checkrc
232	    echo
233
234	    notify "Waiting for cluster services to unload"
235	    while status $prog > /dev/null 2>&1; do
236		sleep 1
237		echo -n "."
238	    done
239	else
240	    echo -n "$desc is already stopped"
241	fi
242
243	rm -f "$LOCK_FILE"
244	rm -f "@localstatedir@/run/$prog.pid"
245	killall -q -9 'crmd stonithd attrd cib lrmd pacemakerd'
246	success
247	echo
248}
249
250rtrn=0
251
252case "$1" in
253start)
254	# For consistency with stop
255	[ "$PCMK_STACK" = cman ] && cman_pre_start
256	start
257;;
258restart|reload|force-reload)
259	stop
260	start
261;;
262condrestart|try-restart)
263	if status $prog > /dev/null 2>&1; then
264	    stop
265	    start
266	fi
267;;
268status)
269	status $prog
270	rtrn=$?
271;;
272stop)
273	#
274	# stonithd needs to be around until fenced is stopped
275	# fenced can't be stopped until any resource using dlm is active
276	#
277	# So:
278	# 1. put the node into standby
279	# 2. wait for all resources to be stopped
280	# 3. stop fenced and anything that needs it (borrowed from the cman script)
281	# 4. stop pacemaker
282	# 5. stop the rest of cman (so it doesn't end up half up/down)
283	#
284	[ "$PCMK_STACK" = cman ] && cman_pre_stop
285	stop
286	[ "x$SBD_SERVICE" != x ] && service $SBD_SERVICE stop
287
288	# Stop cman if needed, unless --skip-cman is specified (which allows
289	# higher-level tooling to stop pacemaker on all nodes, then stop cman
290	# on all nodes, to maintain quorum for DLM-based resources while
291	# pacemaker shuts down).
292	[ "$PCMK_STACK" = cman ] && [ "$2" != "--skip-cman" ] && service cman stop
293;;
294*)
295	echo "usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}"
296	rtrn=2
297;;
298esac
299
300exit $rtrn
301