#!/bin/bash # # init fragment for O2CB. # # chkconfig: 2345 24 20 # description: Load O2CB cluster services at system boot. # # Source function library . /etc/rc.d/init.d/functions # Try get config [ -f /etc/sysconfig/o2cb ] && . /etc/sysconfig/o2cb CLUSTERCONF=/etc/ocfs2/cluster.conf # # This is a tricky bit of eval work. There are many steps involved in # O2CB startup/shutdown, so we collect them here. Each line is a line # of shell code that needs to be run. The code is run via eval as # follows: # # start/load: # Eval of the exact lines, in order. So, the first call is # "eval load_module configfs". # # status: # Eval of the lines with "check_" prepended, in order. So the first # call is "eval check_load_module configfs". # # stop/unload: # Eval of the lines with "un" prepened, in reverse order. So the # *last* call is "eval unload_module configfs". # # To provide an action, create a set of shell functions or commands # "foo", "check_foo", and "unfoo". Then add "foo arguments" to the # appropriate place. Be careful, eval requires quoting to be right. # LOAD_ACTIONS=("load_module configfs" "mount_fs configfs /sys/kernel/config" "load_module ocfs2_nodemanager" "load_module ocfs2_dlm" "load_module ocfs2_dlmfs" "mount_fs ocfs2_dlmfs /dlm") # # if_fail() # # Evaluates return codes. If 0, prints "OK", if 1, prints "Failed" # and exits. If 2, status is "already done" and nothing is printed. # The rest of the functions in here all honor this convention. # if_fail() { RC="$1" REASON="$2" if [ "$RC" = "0" ] then echo "OK" return elif [ "$RC" = "2" ] then return fi echo "Failed" if [ -n "${REASON}" ] then echo "${REASON}" >&2 fi exit 1 } # # load_module() # Load a module # load_module() { _modprobe single $1 } # # check_heartbeat() # # 0 is hb not active, 1 is error, 2 is hb active # check_heartbeat() { if [ "$#" -lt "1" -o -z "$1" ]; then echo "check_heartbeat(): Requires an argument" >&2 return 1 fi CLUSTER="$1" RC=0 if [ -d "/sys/kernel/config/cluster/${CLUSTER}/heartbeat/" ] then ls -1 "/sys/kernel/config/cluster/${CLUSTER}/heartbeat/" | while read HBUUID do if [ -d "/sys/kernel/config/cluster/${CLUSTER}/heartbeat/${HBUUID}" ] then return 2; fi done if [ $? = 2 ] then RC=2 fi fi return $RC } # # clean_heartbeat() # Removes the inactive heartbeat regions # clean_heartbeat() { if [ "$#" -lt "1" -o -z "$1" ]; then echo "clean_heartbeat(): Requires an argument" >&2 return 1 fi CLUSTER="$1" echo -n "Cleaning heartbeat on ${CLUSTER}: " if [ ! -d "/sys/kernel/config/cluster/${CLUSTER}/heartbeat/" ] then echo "OK" return fi ls -1 "/sys/kernel/config/cluster/${CLUSTER}/heartbeat/" | while read HBUUID do if [ ! -d "/sys/kernel/config/cluster/${CLUSTER}/heartbeat/${HBUUID}" ] then continue fi OUTPUT="`ocfs2_hb_ctl -I -u ${HBUUID} 2>&1`" if [ $? != 0 ] then echo "Failed" echo "${OUTPUT}" >&2 exit 1 fi REF="`echo ${OUTPUT} | awk '/refs/ {print $2; exit;}' 2>&1`" if [ $REF != 0 ] then echo "Failed" echo "At least one heartbeat region still active" >&2 exit 1 else OUTPUT="`ocfs2_hb_ctl -K -u ${HBUUID} 2>&1`" fi done if [ $? = 1 ] then exit 1 fi echo "OK" } # # unload_module() # Unload a module # # 0 is success, 1 is error, 2 is not loaded # unload_module() { if [ "$#" -lt "1" -o -z "$1" ]; then echo "unload_module(): Requires an argument" >&2 return 1 fi MODNAME="$1" MODOUT="`awk '$1 ~ /^'$MODNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null`" if [ -z "$MODOUT" ] then return 2 fi case "$MODOUT" in $MODNAME\ 0) ;; $MODNAME\ *) return 2 ;; *) echo -n "Invalid module parsing! " return 1 ;; esac echo "Unloading module \"$MODNAME\": " modprobe -rs "$MODNAME" if [ "$?" != 0 ]; then echo "Unable to unload module \"$MODNAME\"" >&2 return 1 fi return 0 } # # check_load_module() # # 0 is not loaded, 1 is error, 2 is already loaded # check_load_module() { if [ "$#" -lt "1" -o -z "$1" ] then echo "check_load_module(): Requires an argument" >&2 return 1 fi MODNAME="$1" echo -n "Module \"$MODNAME\": " MODOUT="`awk '$1 ~ /^'$MODNAME'$/{print $1,$3;exit}' < /proc/modules 2>/dev/null`" if [ -z "$MODOUT" ] then echo "Not loaded" return 0 fi echo "Loaded" return 2 } # # mount_fs() # Mount a filesystem. # # 0 is success, 1 is error, 2 is already mounted # mount_fs() { TYPE=$1 FULL_MOUNT="$2" FULL_MOUNTSEARCH="`echo "$FULL_MOUNT" | sed -e 's/\//\\\\\//g'`" MOUNTOUT="`awk '$2 ~ /^'$FULL_MOUNTSEARCH'$/{print $2; exit}' < /proc/mounts 2>/dev/null`" if [ -n "$MOUNTOUT" ] then return 2 fi run_cmd "Mounting ${TYPE} filesystems" mount -t ${TYPE} ${TYPE} $FULL_MOUNT return 0 } # # check_mount_fs() # # 0 is not mounted, 1 is error, 2 is already mounted # check_mount_fs() { TYPE="$1" FULL_MOUNT="$2" FULL_MOUNTSEARCH="`echo "$FULL_MOUNT" | sed -e 's/\//\\\\\//g'`" MOUNTOUT="`awk '$2 ~ /^'$FULL_MOUNTSEARCH'$/{print $2; exit}' < /proc/mounts 2>/dev/null`" echo -n "Filesystem \"$TYPE\": " if [ -n "$MOUNTOUT" ] then echo "Mounted" return 2 fi echo "Not mounted" return 0 } # # unmount_fs() # Unmount a filesystem # # 0 is success, 1 is error, 2 is not mounted # unmount_fs() { TYPE=$1 FULL_MOUNT=$2 FULL_MOUNTSEARCH="`echo "$FULL_MOUNT" | sed -e 's/\//\\\\\//g'`" MOUNTOUT="`awk '$2 ~ /^'$FULL_MOUNTSEARCH'$/{print $2; exit}' < /proc/mounts 2>/dev/null`" if [ -z "$MOUNTOUT" ] then return 2 fi run_cmd "Unmounting ${TYPE} filesystem" umount $FULL_MOUNT } load() { for i in $(seq 0 $((${#LOAD_ACTIONS[*]} - 1)) ); do eval ${LOAD_ACTIONS[i]} done } load_status() { for i in $(seq 0 $((${#LOAD_ACTIONS[*]} - 1)) ); do eval "check_${LOAD_ACTIONS[i]}" done return "$?" } online() { CLUSTER="${1:-${O2CB_BOOTCLUSTER}}" if [ -z "$CLUSTER" ] then echo "Cluster not known" return fi check_online $CLUSTER if [ $? = 2 ] then echo "Cluster ${CLUSTER} already online" return fi if ! [ -f ${CLUSTERCONF} ] then echo -n "Checking cluster configuration : " if_fail 1 fi echo -n "Starting cluster ${CLUSTER}: " OUTPUT="`o2cb_ctl -H -n "${CLUSTER}" -t cluster -a online=yes 2>&1`" if [ $? = 0 ] then O2CB_HEARTBEAT_THRESHOLD_FILE_OLD=/proc/fs/ocfs2_nodemanager/hb_dead_threshold O2CB_HEARTBEAT_THRESHOLD_FILE=/sys/kernel/config/cluster/${CLUSTER}/heartbeat/dead_threshold if [ -n "$O2CB_HEARTBEAT_THRESHOLD" ]; then if [ -f "$O2CB_HEARTBEAT_THRESHOLD_FILE" ]; then echo "$O2CB_HEARTBEAT_THRESHOLD" > "$O2CB_HEARTBEAT_THRESHOLD_FILE" elif [ -f "$O2CB_HEARTBEAT_THRESHOLD_FILE_OLD" ]; then echo "$O2CB_HEARTBEAT_THRESHOLD" > "$O2CB_HEARTBEAT_THRESHOLD_FILE_OLD" else echo "WARNING: Unable to set heartbeat dead threshold" >&2 fi fi echo "OK" return else echo "Failed" echo "$OUTPUT" fi echo -n "Stopping cluster ${CLUSTER}: " OUTPUT="`o2cb_ctl -H -n "${CLUSTER}" -t cluster -a online=no 2>&1`" if_fail "$?" "$OUTPUT" } # # check_online() # # 0 is not online, 1 is error, 2 is online # check_online() { if [ "$#" -lt "1" -o -z "$1" ] then echo "check_online(): Requires an argument" >&2 return 1 fi CLUSTER="$1" RC=0 if [ -d "/sys/kernel/config/cluster/${CLUSTER}/node/" ] then ls -1 "/sys/kernel/config/cluster/${CLUSTER}/node/" | while read NODE do LOCAL="`cat \"/sys/kernel/config/cluster/${CLUSTER}/node/${NODE}/local\"`" if [ $LOCAL = 1 ] then return 2 fi done if [ $? = 2 ] then RC=2 fi fi return $RC } offline() { CLUSTER="${1:-${O2CB_BOOTCLUSTER}}" if [ -z "$CLUSTER" ] then return fi if [ ! -e "/sys/kernel/config/cluster/${CLUSTER}" ] then return fi clean_heartbeat $CLUSTER echo -n "Stopping cluster ${CLUSTER}: " check_heartbeat $CLUSTER if [ $? != 0 ] then echo "Failed" echo "Unable to stop cluster as heartbeat region still active" >&2 fi OUTPUT="`o2cb_ctl -H -n "${CLUSTER}" -t cluster -a online=no 2>&1`" if_fail "$?" "$OUTPUT" unload_module ocfs2 if_fail "$?" } start() { if [ "$O2CB_ENABLED" != "true" ] then exit 0 fi load online "$1" } unload() { if [ -d /sys/kernel/config/cluster/ ]; then ls -1 /sys/kernel/config/cluster/ | while read CLUSTER do echo "Unable to unload modules as Cluster ${CLUSTER} is still online" >&2 exit 1 done if [ $? = 1 ] then exit 1 fi fi for i in $(seq $((${#LOAD_ACTIONS[*]} - 1)) -1 0); do eval "un${LOAD_ACTIONS[i]}" done } stop() { offline "$1" unload } status() { load_status if [ $? != 2 ] then return 0; fi CLUSTER="${1:-${O2CB_BOOTCLUSTER}}" if [ -z "$CLUSTER" ] then return 1; fi echo -n "Checking cluster $CLUSTER: " check_online $CLUSTER if [ $? = 2 ] then echo "Online" else echo "Offline" return 0; fi echo -n "Checking heartbeat: " check_heartbeat $CLUSTER if [ $? = 2 ] then echo "Active" else echo "Not active" return 0; fi return echo -n "Checking if O2CB is loaded: " RC=0 for MODSPEC in $MODULE_LIST do MODULE_NAME="`echo $MODSPEC | cut -d: -f1`" FSTYPE="`echo $MODSPEC | cut -d: -f2`" MOUNT_POINT="`echo $MODSPEC | cut -d: -f3`" if grep "^${MODULE_NAME} " /proc/modules >/dev/null 2>&1 then echo -n "${MODULE_NAME} " else RC=1 break fi done if_fail "$RC" echo -n "Checking O2CB mount points: " for MODSPEC in $MODULE_LIST do MODULE_NAME="`echo $MODSPEC | cut -d: -f1`" FSTYPE="`echo $MODSPEC | cut -d: -f2`" MOUNT_POINT="`echo $MODSPEC | cut -d: -f3`" if [ -z "$FSTYPE" -o -z "$MOUNT_POINT" ] then continue fi FULL_MOUNT="${O2CB_MANAGER}/${MOUNT_POINT}" FULL_MOUNTSEARCH="`echo "$FULL_MOUNT" | sed -e 's/\//\\\\\//g'`" if grep "^${FSTYPE} ${FULL_MOUNTSEARCH} ${FSTYPE}" /proc/mounts >/dev/null 2>&1 then echo -n "${MOUNT_POINT} " else RC=1 break fi done if_fail "$RC" } case "$1" in start) start "$2" ;; status) status "$2" ;; stop) stop "$2" ;; restart) stop "$2" start "$2" ;; force-reload) stop "$2" start "$2" ;; load) load ;; online) load online "$2" ;; offline) offline "$2" ;; unload) offline "$2" unload ;; *) msg_usage "$0 {start|stop|restart|force-reload|load|unload|online|offline|status}" exit 3 ;; esac exit 0