File: drbd

package info (click to toggle)
drbd-utils 8.9.10-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 4,272 kB
  • ctags: 7,630
  • sloc: ansic: 42,744; xml: 11,087; cpp: 7,121; sh: 2,461; makefile: 1,079; perl: 352
file content (292 lines) | stat: -rwxr-xr-x 8,183 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
#!/bin/bash
#
# chkconfig: - 70 08
# description: Loads and unloads the drbd module
#
# Copyright 2001-2013 LINBIT
#
# Philipp Reisner, Lars Ellenberg
#
### BEGIN INIT INFO
# Provides: drbd
# Required-Start: $local_fs $network $syslog
# Required-Stop:  $local_fs $network $syslog
# Should-Start:   sshd multipathd
# Should-Stop:    sshd multipathd
# Default-Start:  2 3 4 5
# Default-Stop:   0 1 6
# X-Start-Before: heartbeat corosync
# X-Stop-After:   heartbeat corosync
# X-Interactive:  true
# Short-Description:    Control DRBD resources.
# Description:    Control all DRBD resources.
#	You SHOULD NOT enable this init script
#	when using a cluster manager such as Pacemaker.
#	Start will try to:
#	  load the DRBD driver module,
#	  configure (bring up as Secondary) all DRBD resources as described in
#	  the config file, and promote those resources where the
#	  "become-primary-on" config statement matches.
#	Stop will try to:
#	  demote and unconfigure all DRBD resources described in the config
#	  file, and remove the module.
### END INIT INFO

DEFAULTFILE="/etc/default/drbd"
DRBDADM="drbdadm"
DRBDSETUP="drbdsetup"
PROC_DRBD="/proc/drbd"
MODPROBE="/sbin/modprobe"
RMMOD="/sbin/rmmod"
UDEV_TIMEOUT=10
ADD_MOD_PARAM=""

PATH=/sbin:/bin

if [ -f $DEFAULTFILE ]; then
  . $DEFAULTFILE
fi

# we only use these two functions, define fallback versions of them ...
log_daemon_msg() { echo -n "${1:-}: ${2:-}"; }
log_end_msg() { echo "."; }
# ... and let the lsb override them, if it thinks it knows better.
if [ -f /lib/lsb/init-functions ]; then
    . /lib/lsb/init-functions
fi

assure_module_is_loaded()
{
    [ -e "$PROC_DRBD" ] && return

    $MODPROBE -s drbd $ADD_MOD_PARAM || {
	echo "Can not load the drbd module."$'\n'
	exit 5 # LSB for "not installed"
    }
    # tell klogd to reload module symbol information ...
    [ -e /var/run/klogd.pid ] && [ -x /sbin/klogd ] && /sbin/klogd -i
}

drbd_pretty_status()
{
	local proc_drbd=$1
	# add resource names
	if ! type column &> /dev/null ||
	   ! type paste &> /dev/null ||
	   ! type join &> /dev/null ||
	   ! type sed &> /dev/null ||
	   ! type tr &> /dev/null
	then
		cat "$proc_drbd"
		return
	fi
	sed -e '2q' < "$proc_drbd"
	sed_script=$(
		i=0;
		_sh_status_process() {
			let i++ ;
			stacked=${_stacked_on:+"^^${_stacked_on_minor:-${_stacked_on//[!a-zA-Z0-9_ -]/_}}"}
			printf "s|^ *%u:|%6u\t&%s%s|\n" \
				$_minor $i \
				"${_res_name//[!a-zA-Z0-9_ -]/_}" "$stacked"
		};
		eval "$(drbdadm sh-status)" )

	p() {
		sed -e "1,2d" \
		      -e "$sed_script" \
		      -e '/^ *[0-9]\+: cs:Unconfigured/d;' \
		      -e 's/^\(.* cs:.*[^ ]\)   \([rs]...\)$/\1 - \2/g' \
		      -e 's/^\(.* \)cs:\([^ ]* \)st:\([^ ]* \)ds:\([^ ]*\)/\1\2\3\4/' \
		      -e 's/^\(.* \)cs:\([^ ]* \)ro:\([^ ]* \)ds:\([^ ]*\)/\1\2\3\4/' \
		      -e 's/^\(.* \)cs:\([^ ]*\)$/\1\2/' \
		      -e 's/^ *[0-9]\+:/ x &??not-found??/;' \
		      -e '/^$/d;/ns:.*nr:.*dw:/d;/resync:/d;/act_log:/d;' \
		      -e 's/^\(.\[.*\)\(sync.ed:\)/... ... \2/;/^.finish:/d;' \
		      -e 's/^\(.[0-9 %]*oos:\)/... ... \1/' \
		      < "$proc_drbd" | tr -s '\t ' '  ' 
	}
	m() {
		join -1 2 -2 1 -o 1.1,2.2,2.3 \
			<( ( drbdadm sh-dev all ; drbdadm -S sh-dev all ) | cat -n | sort -k2,2) \
			<(sort < /proc/mounts ) |
			sort -n | tr -s '\t ' '  ' | sed -e 's/^ *//'
	}
	# echo "=== p ==="
	# p
	# echo "=== m ==="
	# m
	# echo "========="
	# join -a1 <(p|sort) <(m|sort)
	# echo "========="
	(
	echo m:res cs ro ds p mounted fstype
	join -a1 <(p|sort) <(m|sort) | cut -d' ' -f2-6,8- | sort -k1,1n -k2,2
	) | column -t
}

# Try to settle regardless of udev version or presence,
# so "/etc/init.d/drbd stop" is able to rmmod, without interfering
# temporary module references caused by udev scanning the devices.
# But don't wait too long.
_udev_settle()
{
	if udevadm version ; then
		# ok, we have udevadm, use it.
		udevadm settle --timeout=5
	else
		# if udevsettle is not there,
		# no matter.
		udevsettle --timeout=5
	fi
}

run_hook()
{
	n="hook_$1"
	if t=$(type -t "$n") && [[ "$t" == "function" ]] ; then
		shift
		"$n" "$@"
	fi
}

case "$1" in
    start)
	# no module, no DRBD.
	assure_module_is_loaded

	# Just in case drbdadm want to display any errors in the configuration
	# file, or we need to ask the user about registering this installation
	# at http://usage.drbd.org, we call drbdadm here without any IO
	# redirection.
	# If "no op" has a non-zero exit code, the config is unusable,
	# and every other command will fail.
	out=$($DRBDADM sh-nop 2>&1); ex=$?
	[[ $ex = 127 ]] && exit 5 # LSB for "not installed"
	log_daemon_msg "Starting DRBD resources"
	if [[ $ex != 0 ]] ; then
	    printf "\n%s\n" "$out" >&2
	    log_end_msg 1
	    exit 6 # LSB for "not configured"
	fi

	$DRBDADM adjust-with-progress all
	[[ $? -gt 1 ]] && exit 20

	# make sure udev has time to create the device files
	# FIXME this probably should, on platforms that have it,
	# use udevadm settle --timeout=X --exit-if-exists=$DEVICE
	for DEVICE in `$DRBDADM sh-dev all`; do
	    UDEV_TIMEOUT_LOCAL=$UDEV_TIMEOUT
	    while [ ! -e $DEVICE ] && [ $UDEV_TIMEOUT_LOCAL -gt 0 ] ; do
		sleep 1
		UDEV_TIMEOUT_LOCAL=$(( $UDEV_TIMEOUT_LOCAL-1 ))
	    done
	done

	[ -d /var/lock/subsys ] && touch /var/lock/subsys/drbd	# for RedHat
	run_hook start_before-wait
	$DRBDADM wait-con-int # User interruptible version of wait-connect all
	run_hook start

	# Become primary if configured
	# Currently, this is necessary for drbd8
	# drbd9 supports automatic promote and removes the "sh-b-pri" command.
	$DRBDADM sh-b-pri all || true
	log_end_msg 0

	# Now handle stacked devices, if any
	STACKED_RESOURCES=""
	# no point trying stacking, if we don't have at least one primary.
	if grep -w Primary /proc/drbd &> /dev/null; then
	    # heuristic: don't mess with dinosaurs # :-(
	    if ! grep -Ee '\<drbddisk|drbdupper\>' /etc/ha.d/haresources &> /dev/null; then
		STACKED_RESOURCES=`$DRBDADM -S sh-resources`
	    fi
	fi
	if [[ $STACKED_RESOURCES ]] ; then
	    log_daemon_msg "Starting stacked DRBD resources"
	    DEVICES=`$DRBDADM -S sh-dev all`
	    $DRBDADM -S adjust-with-progress all
	    if [[ $? -gt 1 ]] ; then
		log_end_msg 1
	    else
		for DEVICE in $DEVICES; do
		    UDEV_TIMEOUT_LOCAL=$UDEV_TIMEOUT
		    while [ ! -e $DEVICE ] && [ $UDEV_TIMEOUT_LOCAL -gt 0 ] ; do
			sleep 1
			UDEV_TIMEOUT_LOCAL=$(( $UDEV_TIMEOUT_LOCAL-1 ))
		    done
		done
		$DRBDADM -S wait-con-int # User interruptible version of wait-connect all
		$DRBDADM -S sh-b-pri all || true
		log_end_msg 0
	    fi
	fi

	;;
    stop)
	$DRBDADM sh-nop
	[[ $? = 127 ]] && exit 5 # LSB for "not installed"
	log_daemon_msg "Stopping all DRBD resources"
	for try in 1 2; do
	    if [ -e $PROC_DRBD ] ; then
		[[ $try = 2 ]] && echo "Retrying once..."
		# bypass drbdadm and drbd config file and everything,
		# to avoid leaving devices around that are not referenced by
		# the current config file, or in case the current config file
		# does not parse for some reason.
		for d in /dev/drbd* ; do
			[ -L "$d" ] && continue
			[ -b "$d" ] || continue
			M=$(umount "$d" 2>&1)
			case $M in
			*" not mounted") :;;
			*) echo "$M" >&2 ;;
			esac
		done
		for res in $($DRBDADM --stacked sh-resources) $($DRBDADM sh-resources); do
			$DRBDSETUP down "$res"
		done
		_udev_settle &> /dev/null
		if [ -d /sys/module/drbd/holders ]; then
			(cd /sys/module/drbd/holders; for tr in *; do [ -d ${tr} ] && ${RMMOD} ${tr}; done)
		fi
		$RMMOD drbd && break
	    fi
	done
	run_hook stop
	[ -f /var/lock/subsys/drbd ] && rm /var/lock/subsys/drbd
	log_end_msg 0
	;;
    status)
	# NEEDS to be heartbeat friendly...
	# so: put some "OK" in the output.
	if [ -e $PROC_DRBD ]; then
	    echo "drbd driver loaded OK; device status:"
	    drbd_pretty_status $PROC_DRBD 2>/dev/null
	    exit 0
	else
	    echo >&2 "drbd not loaded"
	    exit 3
	fi
	;;
    reload)
	$DRBDADM sh-nop
	[[ $? = 127 ]] && exit 5 # LSB for "not installed"
	log_daemon_msg  "Reloading DRBD configuration"
	$DRBDADM adjust all
	run_hook reload
	log_end_msg 0
	;;
    restart|force-reload)
	( . $0 stop )
	( . $0 start )
	;;
    *)
	echo "Usage: /etc/init.d/drbd {start|stop|status|reload|restart|force-reload}"
	exit 1
	;;
esac

exit 0