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