| #!/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 |