File: cman.in

package info (click to toggle)
redhat-cluster 3.1.8-1.2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 4,608 kB
  • ctags: 6,306
  • sloc: ansic: 62,895; sh: 1,626; makefile: 1,143; perl: 765
file content (970 lines) | stat: -rw-r--r-- 20,815 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
#!/bin/bash
#
# cman - Cluster Manager init script
#
# chkconfig: - 21 79
# description: Starts and stops cman
#
#
### BEGIN INIT INFO
# Provides:		cman
# Required-Start:	$network $time $remote_fs
# Required-Stop:	$network $time $remote_fs
# Default-Start:	S
# Default-Stop: 	0 6
# Short-Description:	Starts and stops cman
# Description:		Starts and stops the Cluster Manager set of daemons
### END INIT INFO

# set secure PATH
PATH="/bin:/usr/bin:/sbin:/usr/sbin:@SBINDIR@"

chkconfig2()
{
	case "$1" in
	--levels)
		ls /etc/rc${2}.d/S*${3} > /dev/null 2>/dev/null
		return $?
	;;
	*)
		ls /etc/rc*.d/S*${1} > /dev/null 2>/dev/null
		return $?
	;;
	esac
}

success()
{
	echo -ne "[  OK  ]\r"
}

failure()
{
	echo -ne "[FAILED]\r"
}

status()
{
	pid=$(pidof $1 2>/dev/null)
	statusrtrn=$?
	if [ $statusrtrn -ne 0 ]; then
		echo "$1 is stopped"
	else
		echo "$1 (pid $pid) is running..."
	fi
	return $statusrtrn
}

# rpm based distros
if [ -d /etc/sysconfig ]; then
	[ -f @INITDDIR@/functions ] && . @INITDDIR@/functions
	[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
	[ -f /etc/sysconfig/cman ] && . /etc/sysconfig/cman
	[ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/subsys/cman"
	netmanager=NetworkManager
fi

# deb based distros
if [ ! -d /etc/sysconfig ]; then
	[ -f /etc/default/cluster ] && . /etc/default/cluster
	[ -f /etc/default/cman ] && . /etc/default/cman
	[ -z "$LOCK_FILE" ] && LOCK_FILE="/var/lock/cman"
	netmanager=network-manager
fi

# CMAN_CLUSTER_TIMEOUT -- amount of time to wait for joinging a cluster
#     before giving up.  If CMAN_CLUSTER_TIMEOUT is positive, then we will
#     wait CMAN_CLUSTER_TIMEOUT seconds before giving up and failing when
#     a cluster is not joined.  If CMAN_CLUSTER_TIMEOUT is zero, then
#     wait indefinately for a cluster join.  If CMAN_CLUSTER_TIMEOUT is
#     negative, do not check to see that the cluster has been joined
[ -z "$CMAN_CLUSTER_TIMEOUT" ] && CMAN_CLUSTER_TIMEOUT=60

# CMAN_QUORUM_TIMEOUT -- amount of time to wait for a quorate cluster on
#     startup quorum is needed by many other applications, so we may as
#     well wait here.  If CMAN_QUORUM_TIMEOUT is zero, quorum will
#     be ignored.
[ -z "$CMAN_QUORUM_TIMEOUT" ] && CMAN_QUORUM_TIMEOUT=45

# CMAN_SHUTDOWN_TIMEOUT -- amount of time to wait for cman to become a
#     cluster member before calling cman_tool leave during shutdown.
#     The default is 60 seconds
[ -z "$CMAN_SHUTDOWN_TIMEOUT" ] && CMAN_SHUTDOWN_TIMEOUT=60

# CMAN_NOTIFYD_START - control the startup behaviour for cmannotifyd
# the variable can take 3 values:
# yes                   | will always start cmannotifyd
# no                    | will never start cmannotifyd
# conditional (default) | will start cmannotifyd only if scriptlets
#                         are found in @NOTIFYDDIR@
[ -z "$CMAN_NOTIFYD_START" ] && CMAN_NOTIFYD_START=conditional

# CMAN_SSHD_START - control sshd startup behaviour
# the variable can take 2 values:
# yes                   | cman will start sshd as early as possible
# no (default)          | cman will not start sshd
[ -z "$CMAN_SSHD_START" ] && CMAN_SSHD_START=no

# CMAN_DAEMONS_START -- Set to "no" to disable {dlm,gfs,ocfs2}-controld daemons
# execution from within cman init script
# (Can be useful for some pacemaker-based setups).
# values:
# no                                 | cman init will NOT start the daemons
# empty or any other value (default) | cman init will start the daemons
#CMAN_DAEMONS_START=

# FENCE_JOIN_TIMEOUT -- seconds to wait for fence domain join to
#     complete.  If the join hasn't completed in this time, fence_tool join
#     exits with an error, and this script exits with an error.  To wait
#     indefinitely set the value to -1.
[ -z "$FENCE_JOIN_TIMEOUT" ] && FENCE_JOIN_TIMEOUT=20

# FENCED_MEMBER_DELAY -- amount of time to delay fence_tool join to allow
#     all nodes in cluster.conf to become cluster members.  In seconds.
[ -z "$FENCED_MEMBER_DELAY" ] && FENCED_MEMBER_DELAY=45

# FENCE_JOIN -- boolean value used to control whether or not this node
#     should join the fence domain. If FENCE_JOIN is set to "no", then
#     the script will not attempt to the fence domain. If FENCE_JOIN is
#     set to "yes", then the script will attempt to join the fence domain.
#     If FENCE_JOIN is set to any other value, the default behavior is
#     to join the fence domain (equivalent to "yes").
[ -z "$FENCE_JOIN" ] && FENCE_JOIN="yes"

# FENCED_OPTS -- allow extra options to be passed to fence daemon.
[ -z "$FENCED_OPTS" ] && FENCED_OPTS=""

# NETWORK_BRIDGE_SCRIPT -- script to use for xen network bridging.
#     This script must exist in the /etc/xen/scripts directory.
#     The default script is "network-bridge".
[ -z "$NETWORK_BRIDGE_SCRIPT" ] && NETWORK_BRIDGE_SCRIPT="network-bridge"

# CMAN_JOIN_OPTS -- allows extra options to be passed to cman_tool when join
#     operation is performed.
#     NOTES:
#	$CLUSTERNAME   automatically appends "-c $CLUSTERNAME"
#	$NODENAME      automatically appends "-n $NODENAME"
#	$CONFIG_LOADER automatically appends "-C $CONFIG_LOADER"

[ -n "$CMAN_JOIN_OPTS" ] && cman_join_opts="$CMAN_JOIN_OPTS"

[ -n "$CLUSTERNAME" ] && cman_join_opts+="-c $CLUSTERNAME"

[ -n "$NODENAME" ] && cman_join_opts+=" -n $NODENAME"

# CONFIG_LOADER -- select default config parser.
# This can be:
# xmlconfig       - read directly from cluster.conf and use ricci as default
#                   config propagation method. (default)
# ldapconfig      - read configuration from an ldap server.
#                   Requires: COROSYNC_LDAP_URL or/and COROSYNC_LDAP_BASEDN 
#                   envvar to be set.
#                   LDAP_BINDDN and LDAP_BINDPWD have to be either both set
#                   or both unset.
# corosync_parser - use internal corosync config file parser.
# openaisparser   - use internal openais config file parser.
[ -n "$CONFIG_LOADER" ] && cman_join_opts+=" -C $CONFIG_LOADER"

# CONFIG_VALIDATION -- select default config validation behaviour
# This can be:
# FAIL - Use a very strict checking. The config will not be loaded if there
#        for any kind of warnings/errors.
# WARN - Same as FAIL, but will allow the config to load (this is temporary
#        the default behaviour)
# NONE - Disable config validation. Highly discouraged.
[ -z "$CONFIG_VALIDATION" ] && CONFIG_VALIDATION=WARN
cman_join_opts+=" -D$CONFIG_VALIDATION"

# CMAN_LEAVE_OPTS -- allows extra options to be passed to cman_tool when leave
#     operation is performed.
[ -n "$CMAN_LEAVE_OPTS" ] && cman_leave_opts="$CMAN_LEAVE_OPTS"

# INITLOGLEVEL -- select how verbose the init script should be
# possible values:
# quiet           - only one line notification for start/stop operations
# terse (default) - show only required activity
# full            - show everything
[ -z "$INITLOGLEVEL" ] && INITLOGLEVEL=terse

### generic wrapper functions

ok() {
	if [ "$INITLOGLEVEL" != "quiet" ]; then
		success
		echo
	fi
}

nok() {
	echo -e "$errmsg"
	failure
	echo
	exit 1
}

none()
{
	return 0
}

runwrap()
{
	function=$1
	shift
	conditional=$1
	shift
	message="$@"

	if ! $conditional; then
		if [ "$INITLOGLEVEL" = "full" ]; then
			echo "   $message... action not required"
		fi
		return 0
	fi

	if [ "$INITLOGLEVEL" != "quiet" ]; then
		echo -n "   $message... "
	fi
	if $function; then
		ok
	else
		nok
	fi
}

check_exec()
{
	exec=$1

	realexec="$(type -p $exec)"
	if [ -z "$realexec" ]; then
		errmsg="Unable to find $exec in PATH"
		return 1
	fi
	if [ ! -x "$realexec" ]; then
		errmsg="$realexec not executable"
		return 1
	fi
	return 0
}

start_daemon()
{
	daemon=$1
	shift
	args="$@"

	check_exec $daemon || return $?
	status $daemon > /dev/null 2>&1 && return 0
	errmsg=$( $daemon $args 2>&1 )
}

check_sleep()
{
	if ! sleep 0.01 > /dev/null 2>&1; then
		return 1
	fi
}

stop_daemon()
{
	daemon=$1
	shift
	retryforsec=$1

	[ -z "$retryforsec" ] && retryforsec=1
	retries=0

	if check_sleep; then
		sleepfor=0.25
		retryforsec=$(($retryforsec * 4))
	else
		sleepfor=1
	fi

	while status $daemon > /dev/null 2>&1 && \
		[ $retries -lt $retryforsec ]; do

		errmsg=$( pkill -TERM $daemon ) || return 1
		sleep $sleepfor
		((retries++))
	done

	! status $daemon > /dev/null 2>&1
}

### check functions (enable/disable) (on/off)

sshd_enabled()
{
	case "$CMAN_SSHD_START" in
	yes)
		return 0
	;;
	esac
	return 1
}

control_daemons_enabled()
{
	[ "$CMAN_DAEMONS_START" = "no" ] && return 1
	return 0
}

dlm_controld_enabled()
{
	control_daemons_enabled
	return $?
}

gfs_controld_enabled()
{
	! control_daemons_enabled && return 1

	if [ -f @INITDDIR@/gfs2-cluster ] && ! chkconfig2 gfs2-cluster; then
		return 0
	fi
	return 1
}

cluster_disabled_at_boot()
{
	if grep -q nocluster /proc/cmdline && \
	   [ "$(tty)" = "/dev/console" ]; then
		errmsg="not configured to run at boot"
		return 1
	fi
	return 0
}

network_manager_enabled()
{
	if status $netmanager > /dev/null 2>&1 || \
	   chkconfig2 $netmanager; then
		errmsg="\nNetwork Manager is either running or configured to run. Please disable it in the cluster."
		return 1
	fi
	return 0
}

mtab_configfs()
{
	awk '{ print $2 }' /etc/mtab | \
		grep '^/sys/kernel/config$' > /dev/null 2>&1 && \
	awk '{ print $3 }' /etc/mtab | \
		grep '^configfs$' > /dev/null 2>&1
}

cman_running()
{
	cman_tool status > /dev/null 2>&1
}

# NOTE: this could probably grow a bit to do config sanity checks
cman_checkconfig()
{
	case "$CONFIG_LOADER" in
	ldapconfig)
		if [ -n "$COROSYNC_LDAP_URL" ] || [ -n "$COROSYNC_LDAP_BASEDN" ]; then
			if [ -n "$COROSYNC_LDAP_BINDDN" ]; then
				if [ -z "$LDAP_BINDPWD" ]; then
					errmsg="ldapconfig has been selected \
						but LDAP_BINDPWD is not set"
					return 1
				fi
			fi
			if [ -n "$LDAP_BINDPWD" ]; then
				if [ -z "$COROSYNC_LDAP_BINDDN" ]; then
					errmsg="ldapconfig has been selected \
						but LDAP_BINDDN is not set"
					return 1
				fi
			fi
		else
			errmsg="ldapconfig has been selected but neither \
				COROSYNC_LDAP_URL or COROSYNC_LDAP_BASEDN have been set"
			return 1
		fi
	;;
	xmlconfig|"")
		configfile=@CONFDIR@/@CONFFILE@
		[ -n "$COROSYNC_CLUSTER_CONFIG_FILE" ] && \
			configfile=$COROSYNC_CLUSTER_CONFIG_FILE

		if [ ! -f $configfile ]; then
			errmsg="xmlconfig cannot find $configfile"
			return 1
		fi
	;;
	esac
}

xend_bridged_net_enabled() {
	# Not a xen kernel
	[ -d /proc/xen ] || return 1

	# uanble to determine current runlevel
	current_runlevel=$( runlevel 2>/dev/null | \
				awk '{ print $2 }' 2>/dev/null )
	[ -z "$current_runlevel" ] && return 1

	# xend doesn't start at this runlevel.
	! chkconfig2 --levels "$current_runlevel" xend 2>/dev/null && return 1

	# xend isn't configured to use bridged networking.
	[ ! -f /etc/xen/xend-config.sxp ] && return 1

	# xend isn't configured to use bridged networking.
	! egrep \
		"^[[:blank:]]*\([[:blank:]]*network-script[[:blank:]]+(')?[[:blank:]]*${NETWORK_BRIDGE_SCRIPT}([[:blank:]]*\)|[[:blank:]]+)" \
		/etc/xen/xend-config.sxp >&/dev/null && return 1
}

qdiskd_enabled()
{
	ccs_tool query /cluster/quorumd >/dev/null 2>&1
}

groupd_enabled()
{
	groupd_compat="$(ccs_tool query /cluster/group/@groupd_compat \
			2>/dev/null || true)"

	[ -z "$groupd_compat" ] && return 1
	[ "$groupd_compat" = 0 ] && return 1
	return 0
}

ocfs2_enabled()
{
	! control_daemons_enabled && return 1
	ocfs2_cluster="$(cat /sys/fs/ocfs2/cluster_stack 2>/dev/null || true)"
	[ "$ocfs2_cluster" != cman ] && return 1
	return 0
}

cmannotifyd_enabled()
{
	case "$CMAN_NOTIFYD_START" in
	yes)
		return 0
	;;
	conditional)
		if [ -n "$(ls -1 @NOTIFYDDIR@ 2>/dev/null)" ]; then
			return 0
		fi
	;;
	esac
	return 1
}

fence_join_enabled()
{
	#
	# Check the value of FENCE_JOIN.
	# If FENCE_JOIN is set to "no", we will not attempt to join
	# the fence domain. If FENCE_JOIN is set to any other value,
	# we will attempt to join the fence domain (default).
	#
	if [ "$FENCE_JOIN" = "no" ]; then
		return 1
	fi
}

### the real stuff starts here

start_global()
{
	## global bits
	# guarantee enough limits
	ulimit -c unlimited
	# required for distributions that use tmpfs for /var/run
	mkdir -p /var/run/cluster
}

xend_bridged_net_start() {
	if [ ! -x /etc/xen/scripts/${NETWORK_BRIDGE_SCRIPT} ]; then
		if [ -f /etc/xen/scripts/${NETWORK_BRIDGE_SCRIPT} ]; then
			errmsg="The xend bridged network script cannot be run"
		else
			errmsg="The xend bridged network script is missing"
		fi
		return 1
	fi

	modprobe netbk >& /dev/null || true
	modprobe netloop >& /dev/null || true

	bridge_parms=$( egrep -m 1 \
			"^[[:blank:]]*\([[:blank:]]*network-script[[:blank:]]+(')?[[:blank:]]*${NETWORK_BRIDGE_SCRIPT}([[:blank:]]*\)|[[:blank:]]+)" \
			/etc/xen/xend-config.sxp | \
			sed -r \
			"s/^[[:blank:]]*\([[:blank:]]*network-script[[:blank:]]+'?[[:blank:]]*${NETWORK_BRIDGE_SCRIPT}[[:blank:]]*//; s/'?[[:blank:]]*\).*//" )

	errmsg=$( /etc/xen/scripts/${NETWORK_BRIDGE_SCRIPT} \
		start $bridge_parms 2>&1 )
}

load_kernel_modules()
{
	errmsg=$( modprobe configfs 2>&1 ) || return 1
	errmsg=$( modprobe dlm 2>&1 ) || return 1
}

unload_kernel_modules()
{
	modprobe -r dlm > /dev/null 2>&1 || true
}

start_configfs()
{
	mtab_configfs && return 0
	errmsg=$( mount -t configfs none /sys/kernel/config 2>&1 )
}

stop_configfs()
{
	if mtab_configfs && [ -z "$(ls -1 /sys/kernel/config)" ]; then
		errmsg=$( umount /sys/kernel/config 2>&1 ) || return 1
		modprobe -r configfs > /dev/null 2>&1 || true
	fi
}

corosync_running()
{
	[ -f /var/run/corosync.pid ] || return 1

	read corosync_pid foo < /var/run/corosync.pid
	if [ "$(pidof corosync)" == "$corosync_pid" ];then
		errmsg="Corosync Cluster Engine is already running"
		return 0
	fi

	return 1
}

start_cman()
{
	check_exec cman_tool || return $?
	cman_running && return 0
	cman_checkconfig || return 1
	corosync_running && return 1

	tmpfile=$(mktemp -t cmanstartup.XXXXXXXXXX)
	if [ -z "$tmpfile" ]; then
		errmsg="Unable to create temporary file"
		return 1
	fi

	cman_tool -z -t $CMAN_CLUSTER_TIMEOUT -w join $cman_join_opts > $tmpfile 2>&1 &

	while status cman_tool >/dev/null 2>&1; do
		sleep 0.2
	done

	sleep 2

	if ! cman_running; then
		errmsg="$(cat $tmpfile) Check cluster logs for details"
		ret=1
	else
		if [ "$CONFIG_VALIDATION" = "WARN" ] && \
		   [ -s $tmpfile ] && \
		   grep -q Relax-NG $tmpfile ; then
			cat $tmpfile >&2
		fi
		pidof /usr/sbin/corosync > /var/run/cman.pid
		ret=0
	fi

	rm -f $tmpfile
	return $ret
}

wait_for_quorum()
{
	if [ $CMAN_QUORUM_TIMEOUT -gt 0 ]; then
		errmsg=$( cman_tool -t $CMAN_QUORUM_TIMEOUT \
			 -q wait 2>&1 ) || return 1
	fi
}

stop_cman()
{
	if cman_running; then
		errmsg=$( cman_tool $cman_leave_opts -t $CMAN_SHUTDOWN_TIMEOUT \
			-w leave $cmanremove 2>&1 ) || return 1
		ok
		echo -n "   Waiting for corosync to shutdown:"
		while status corosync > /dev/null 2>&1; do
			sleep 1
			echo -n "."
		done
		rm -f /var/run/cman.pid
	fi
	return 0
}

start_qdiskd()
{
	start_daemon qdiskd "-Q" || return 1

	if [ "$INITLOGLEVEL" = "full" ]; then
		ok
		echo -n "   Waiting for qdiskd to be active: "
	fi
	retries=0
	while ! cman_tool status |grep -q "Quorum device" && \
		status qdiskd > /dev/null 2>&1 && \
		[ $retries -lt 10 ]; do
		sleep 2
		if [ "$INITLOGLEVEL" = "full" ]; then
			echo -n "$retries "
		fi
		((retries++))
	done
	status qdiskd > /dev/null 2>&1
}

stop_qdiskd()
{
	stop_daemon qdiskd 5
}

start_groupd()
{
	start_daemon groupd || return 1

	if [ "$INITLOGLEVEL" = "full" ]; then
		ok
		echo -n "   Waiting groupd protocol negotiation: "
	fi
	retries=0
	while group_tool ls | \
		grep -q pending && [ $retries -lt 10 ]; do
		sleep 1
		if [ "$INITLOGLEVEL" = "full" ]; then
			echo -n "$retries "
		fi
		((retries++))
	done
	return 0
}

stop_groupd()
{
	stop_daemon groupd
}

start_fenced()
{
	start_daemon fenced "$FENCED_OPTS"
}

stop_fenced()
{
	stop_daemon fenced
}

start_dlm_controld()
{
	start_daemon dlm_controld || return 1

	if [ "$INITLOGLEVEL" = "full" ]; then
		ok
		echo -n "   Waiting dlm_controld to complete initialization: "
	fi

	retries=0
	while ! dlm_tool ls >/dev/null 2>&1 && [ $retries -lt 10 ]; do
		sleep 1
		if [ "$INITLOGLEVEL" = "full" ]; then
			echo -n "$retries "
		fi
		((retries++))
	done

	return 0
}

stop_dlm_controld()
{
	stop_daemon dlm_controld
}

start_ocfs2_controld()
{
	start_daemon ocfs2_controld.cman
}

start_cmannotifyd()
{
	start_daemon cmannotifyd
}

stop_cmannotifyd()
{
	stop_daemon cmannotifyd
}

unfence_self()
{
	# fence_node returns 0 on success, 1 on failure, 2 if unconfigured
	# 0 and 2 are ok. Everything else should report error.
	fence_err=$(fence_node -U 2>&1)
	case $? in
	0|2)
		return 0
	;;
	esac
	errmsg="$fence_err"
	return 1
}

join_fence_domain()
{
	if ! cman_tool status | grep Flags | grep 2node \
		> /dev/null 2>&1; then
		errmsg=$( fence_tool join -w $FENCE_JOIN_TIMEOUT \
			2>&1 ) || return 1
	else
		errmsg=$( fence_tool join -w $FENCE_JOIN_TIMEOUT \
			-m $FENCED_MEMBER_DELAY join \
			2>&1 ) || return 1
	fi
}

leave_fence_domain()
{
	if status fenced > /dev/null 2>&1; then
		errmsg=$( fence_tool leave -w 10 2>&1 )
		return $?
	fi
}

start()
{
	breakpoint="$1"

	sshd_enabled && cd @INITDDIR@ && ./sshd start

	if [ "$INITLOGLEVEL" = "quiet" ]; then
		echoarg="-n"
	fi

	echo $echoarg "Starting cluster: "

	runwrap cluster_disabled_at_boot \
		none \
		"Checking if cluster has been disabled at boot"

	runwrap network_manager_enabled \
		none \
		"Checking Network Manager"

	runwrap start_global \
		none \
		"Global setup"

	runwrap xend_bridged_net_start \
		xend_bridged_net_enabled \
		"Enable Xend bridge net workaround"

	runwrap load_kernel_modules \
		none \
		"Loading kernel modules"

	runwrap start_configfs \
		none \
		"Mounting configfs"

	[ "$breakpoint" = "setup" ] && exit 0

	runwrap start_cman \
		none \
		"Starting cman"

	[ "$breakpoint" = "join" ] && exit 0

	runwrap start_qdiskd \
		qdiskd_enabled \
		"Starting qdiskd"

	runwrap wait_for_quorum \
		none \
		"Waiting for quorum"

	[ "$breakpoint" = "quorum" ] && exit 0

	runwrap start_groupd \
		groupd_enabled \
		"Starting groupd"

	runwrap start_fenced \
		none \
		"Starting fenced"

	runwrap start_dlm_controld \
		dlm_controld_enabled \
		"Starting dlm_controld"

	gfs_controld_enabled && cd @INITDDIR@ && ./gfs2-cluster start

	runwrap start_ocfs2_controld \
		ocfs2_enabled \
		"Starting ocfs2_controld"

	runwrap start_cmannotifyd \
		cmannotifyd_enabled \
		"Starting cmannotifyd"

	[ "$breakpoint" = "daemons" ] && exit 0

	runwrap unfence_self \
		none \
		"Unfencing self"

	runwrap join_fence_domain \
		fence_join_enabled \
		"Joining fence domain"
}

stop()
{
	if [ "$INITLOGLEVEL" = "quiet" ]; then
		echoarg="-n"
	fi

	echo $echoarg "Stopping cluster: "

	runwrap leave_fence_domain \
		fence_join_enabled \
		"Leaving fence domain"

	gfs_controld_enabled && cd @INITDDIR@ && ./gfs2-cluster stop

	runwrap stop_dlm_controld \
		dlm_controld_enabled \
		"Stopping dlm_controld"

	runwrap stop_fenced \
		none \
		"Stopping fenced"

	runwrap stop_groupd \
		groupd_enabled \
		"Stopping groupd"

	runwrap stop_qdiskd \
		qdiskd_enabled \
		"Stopping qdiskd"

	runwrap stop_cman \
		none \
		"Stopping cman"

	runwrap stop_cmannotifyd \
		cmannotifyd_enabled \
		"Stopping cmannotifyd"

	runwrap unload_kernel_modules \
		none \
		"Unloading kernel modules"

	runwrap stop_configfs \
		none \
		"Unmounting configfs"
}

cmanstatus()
{
	errmsg=$( status corosync 2>&1 )
	ret=$?
	if [ "$ret" != "0" ]; then
		if [ -f /var/run/cman.pid ]; then
			errmsg="Found stale pid file"
			return 1
		fi
		if [ -f $LOCK_FILE ]; then
			errmsg="Found stale lock file"
			return 2
		fi
		return $ret
	fi

	if ! cman_running; then
		errmsg="cman is not running"
		return 3
	fi

	if qdiskd_enabled; then
		errmsg=$( status qdiskd 2>&1 ) || return $?
	fi

	if groupd_enabled; then
		errmsg=$( status groupd 2>&1 ) || return $?
	fi

	errmsg=$( status fenced 2>&1 ) || return $?
	errmsg=$( status dlm_controld 2>&1 ) || return $?

	if cmannotifyd_enabled; then
		errmsg=$( status cmannotifyd 2>&1 ) || return $?
	fi
}

rtrn=0

if [ "$EUID" != "0" ]; then
	echo "Only root can execute $0 script"
	exit 4
fi

# See how we were called.
case "$1" in
start)
	start "$2" && touch $LOCK_FILE
	if [ "$INITLOGLEVEL" = "quiet" ]; then
		success
		echo
	fi
;;
stop)
	cmanremove=""
	if [ -n "$2" ] && [ "$2" = "remove" ]; then
		cmanremove=remove
	fi
	stop && rm -f $LOCK_FILE
	if [ "$INITLOGLEVEL" = "quiet" ]; then
		success
		echo
	fi
;;
restart|reload|force-reload)
	cmanremove=remove
	stop
	start
;;
condrestart|try-restart)
	if cmanstatus; then
		cmanremove=remove
		stop
		start
	fi
;;
status)
	cmanstatus
	rtrn=$?
	if [ "$rtrn" = 0 ]; then
		echo "cluster is running."
	else
		echo -e "$errmsg"
	fi
;;
*)
	echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}"
	rtrn=2
;;
esac

exit $rtrn