blob: 2c3462d2b9f26e35e08fd688fac7b5cd65eae1aa [file] [log] [blame]
#!/bin/bash
#
# chkconfig: - 21 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:
# 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=/usr/sbin:/sbin:$PATH
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