#!/bin/bash # # chkconfig: - 70 08 # description: Loads and unloads the drbd module # # Copyright 2001-2010 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. ### END INIT INFO DEFAULTFILE="/etc/default/drbd" DRBDADM="/sbin/drbdadm" DRBDSETUP="/sbin/drbdsetup" PROC_DRBD="/proc/drbd" MODPROBE="/sbin/modprobe" RMMOD="/sbin/rmmod" UDEV_TIMEOUT=10 ADD_MOD_PARAM="" if [ -f $DEFAULTFILE ]; then . $DEFAULTFILE fi test -f $DRBDADM || exit 5 # 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 function assure_module_is_loaded { [ -e "$PROC_DRBD" ] && return $MODPROBE -s drbd $ADD_MOD_PARAM || { echo "Can not load the drbd module."$'\n'; exit 20 } # 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 } case "$1" in start) # 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. log_daemon_msg "Starting DRBD resources" if ! out=$($DRBDADM sh-nop 2>&1) ; then printf "\n%s\n" "$out" >&2 log_end_msg 1 exit 1 fi assure_module_is_loaded $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 $DRBDADM wait-con-int # User interruptible version of wait-connect all $DRBDADM sh-b-pri all # Become primary if configured log_end_msg 0 ;; stop) $DRBDADM sh-nop 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 $(drbdsetup all show | sed -ne 's/^resource \(.*\) {$/\1/p'); do drbdsetup "$res" down done _udev_settle &> /dev/null $RMMOD drbd && break fi done [ -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 log_daemon_msg "Reloading DRBD configuration" $DRBDADM adjust all 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