1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00
samba-mirror/ctdb/config/ctdb.init
Martin Schwenke b5ebff6931 tools/ctdb: "ctdb runstate" now accepts optional expected run state arguments
If one or more run states are specified then "ctdb runstate" succeeds
only if ctdbd is in one of those run states.

At the moment, if the "setup" event fails then the initscript succeeds
but ctdbd exits almost immediately.  This behaviour isn't very
friendly.

The initscript now waits until ctdbd is in "startup" or "running" run
state via the use of "ctdb runstate startup running", meaning that ctdbd
has successfully passed the "setup" event.

The "setup" event code in 00.ctdb now waits until ctdbd is in the
"setup" run state before proceeding via the use of "ctdb runstate setup".

Signed-off-by: Martin Schwenke <martin@meltin.net>
Pair-programmed-with: Amitay Isaacs <amitay@gmail.com>

(This used to be ctdb commit 4a2effcc455be67ff4a779a59ca81ba584312cd6)
2013-05-24 14:08:07 +10:00

437 lines
10 KiB
Bash
Executable File

#!/bin/sh
#
##############################
# ctdb: Starts the clustered tdb daemon
#
# chkconfig: - 90 01
#
# description: Starts and stops the clustered tdb daemon
# pidfile: /var/run/ctdb/ctdbd.pid
#
### BEGIN INIT INFO
# Provides: ctdb
# Required-Start: $network
# Required-Stop: $network
# Default-Stop:
# Default-Start: 3 5
# Short-Description: start and stop ctdb service
# Description: initscript for the ctdb service
### END INIT INFO
# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
fi
[ -f /etc/rc.status ] && {
. /etc/rc.status
rc_reset
LC_ALL=en_US.UTF-8
}
if [ -f /lib/lsb/init-functions ] ; then
. /lib/lsb/init-functions
fi
# Avoid using root's TMPDIR
unset TMPDIR
[ -z "$CTDB_BASE" ] && {
export CTDB_BASE="/etc/ctdb"
}
. $CTDB_BASE/functions
loadconfig network
loadconfig ctdb
# check networking is up (for redhat)
[ "$NETWORKING" = "no" ] && exit 0
detect_init_style
export CTDB_INIT_STYLE
ctdbd=${CTDBD:-/usr/sbin/ctdbd}
pidfile="/var/run/ctdb/ctdbd.pid"
if [ "$CTDB_VALGRIND" = "yes" ]; then
init_style="valgrind"
else
init_style="$CTDB_INIT_STYLE"
fi
build_ctdb_options () {
maybe_set () {
# If the 2nd arg is null then return - don't set anything.
# Else if the 3rd arg is set and it doesn't match the 2nd arg
# then return
[ -z "$2" -o \( -n "$3" -a "$3" != "$2" \) ] && return
val="'$2'"
case "$1" in
--*) sep="=" ;;
-*) sep=" " ;;
esac
# For these options we're only passing a value-less flag.
[ -n "$3" ] && {
val=""
sep=""
}
CTDB_OPTIONS="${CTDB_OPTIONS}${CTDB_OPTIONS:+ }${1}${sep}${val}"
}
[ -z "$CTDB_RECOVERY_LOCK" ] && {
echo "No recovery lock specified. Starting CTDB without split brain prevention"
}
maybe_set "--reclock" "$CTDB_RECOVERY_LOCK"
mkdir -p $(dirname "$pidfile")
maybe_set "--pidfile" "$pidfile"
# build up CTDB_OPTIONS variable from optional parameters
maybe_set "--logfile" "$CTDB_LOGFILE"
maybe_set "--nlist" "$CTDB_NODES"
maybe_set "--socket" "$CTDB_SOCKET"
maybe_set "--public-addresses" "$CTDB_PUBLIC_ADDRESSES"
maybe_set "--public-interface" "$CTDB_PUBLIC_INTERFACE"
maybe_set "--dbdir" "$CTDB_DBDIR"
maybe_set "--dbdir-persistent" "$CTDB_DBDIR_PERSISTENT"
maybe_set "--event-script-dir" "$CTDB_EVENT_SCRIPT_DIR"
maybe_set "--transport" "$CTDB_TRANSPORT"
maybe_set "-d" "$CTDB_DEBUGLEVEL"
maybe_set "--notification-script" "$CTDB_NOTIFY_SCRIPT"
maybe_set "--start-as-disabled" "$CTDB_START_AS_DISABLED" "yes"
maybe_set "--start-as-stopped " "$CTDB_START_AS_STOPPED" "yes"
maybe_set "--no-recmaster" "$CTDB_CAPABILITY_RECMASTER" "no"
maybe_set "--no-lmaster" "$CTDB_CAPABILITY_LMASTER" "no"
maybe_set "--lvs --single-public-ip" "$CTDB_LVS_PUBLIC_IP"
maybe_set "--script-log-level" "$CTDB_SCRIPT_LOG_LEVEL"
maybe_set "--log-ringbuf-size" "$CTDB_LOG_RINGBUF_SIZE"
maybe_set "--syslog" "$CTDB_SYSLOG" "yes"
maybe_set "--max-persistent-check-errors" "$CTDB_MAX_PERSISTENT_CHECK_ERRORS"
}
export_debug_variables ()
{
export CTDB_DEBUG_HUNG_SCRIPT CTDB_EXTERNAL_TRACE
}
# Log given message or stdin to either syslog or a CTDB log file
do_log ()
{
script_log "ctdb.init" "$@"
}
select_tdb_checker ()
{
# Find the best TDB consistency check available.
use_tdb_tool_check=false
if which tdbtool >/dev/null 2>&1 && \
echo "help" | tdbtool | grep -q check ; then
use_tdb_tool_check=true
elif which tdbtool >/dev/null 2>&1 && which tdbdump >/dev/null 2>&1 ; then
do_log <<EOF
WARNING: The installed 'tdbtool' does not offer the 'check' subcommand.
Using 'tdbdump' for database checks.
Consider updating 'tdbtool' for better checks!
EOF
elif which tdbdump >/dev/null 2>&1 ; then
do_log <<EOF
WARNING: 'tdbtool' is not available.
Using 'tdbdump' to check the databases.
Consider installing a recent 'tdbtool' for better checks!
EOF
else
do_log <<EOF
WARNING: Cannot check databases since neither
'tdbdump' nor 'tdbtool check' is available.
Consider installing tdbtool or at least tdbdump!
EOF
return 1
fi
}
check_tdb ()
{
_db="$1"
if $use_tdb_tool_check ; then
# tdbtool always exits with 0 :-(
if tdbtool "$_db" check 2>/dev/null |
grep -q "Database integrity is OK" ; then
return 0
else
return 1
fi
else
tdbdump "$_db" >/dev/null 2>/dev/null
return $?
fi
}
check_persistent_databases ()
{
_dir="${CTDB_DBDIR_PERSISTENT:-${CTDB_DBDIR:-/var/ctdb}/persistent}"
mkdir -p "$_dir" 2>/dev/null
[ "${CTDB_MAX_PERSISTENT_CHECK_ERRORS:-0}" = "0" ] || return 0
for _db in $(ls "$_dir/"*.tdb.*[0-9] 2>/dev/null) ; do
check_tdb $_db || {
do_log "Persistent database $_db is corrupted! CTDB will not start."
return 1
}
done
}
check_non_persistent_databases ()
{
_dir="${CTDB_DBDIR:-/var/ctdb}"
mkdir -p "$_dir" 2>/dev/null
for _db in $(ls "${_dir}/"*.tdb.*[0-9] 2>/dev/null) ; do
check_tdb $_db || {
_backup="${_db}.$(date +'%Y%m%d.%H%M%S.%N').corrupt"
do_log <<EOF
WARNING: database ${_db} is corrupted.
Moving to backup ${_backup} for later analysis.
EOF
mv "$_db" "$_backup"
# Now remove excess backups
ls -td "${_db}."*".corrupt" |
tail -n +$((${CTDB_MAX_CORRUPT_DB_BACKUPS:-10} + 1)) |
xargs rm -f
}
done
}
set_retval() {
return $1
}
wait_until_ready () {
_timeout="${1:-10}" # default is 10 seconds
_count=0
while ! ctdb runstate startup running >/dev/null 2>&1 ; do
if [ $_count -ge $_timeout ] ; then
return 1
fi
sleep 1
_count=$(($_count + 1))
done
}
start() {
echo -n $"Starting ctdbd service: "
ctdb ping >/dev/null 2>&1 && {
echo $"CTDB is already running"
return 0
}
# About to start new $ctdbd. The ping above has failed and any
# new $ctdbd will destroy the Unix domain socket, so any processes
# that aren't yet completely useless soon will be... so kill
# them.
pkill -9 -f "$ctdbd"
build_ctdb_options
export_debug_variables
# make sure we drop any ips that might still be held if previous
# instance of ctdb got killed with -9 or similar
drop_all_public_ips "ctdb.init"
if select_tdb_checker ; then
check_persistent_databases || return $?
check_non_persistent_databases
fi
if [ "$CTDB_SUPPRESS_COREFILE" = "yes" ]; then
ulimit -c 0
else
ulimit -c unlimited
fi
case $init_style in
valgrind)
eval valgrind -q --log-file=/var/log/ctdb_valgrind \
$ctdbd --valgrinding "$CTDB_OPTIONS"
RETVAL=$?
echo
;;
suse)
eval startproc $ctdbd "$CTDB_OPTIONS"
RETVAL=$?
;;
redhat)
eval $ctdbd "$CTDB_OPTIONS"
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/ctdb || RETVAL=1
;;
debian)
eval start-stop-daemon --start --quiet --background \
--exec $ctdbd -- "$CTDB_OPTIONS"
RETVAL=$?
;;
esac
if [ $RETVAL -eq 0 ] ; then
if ! wait_until_ready ; then
RETVAL=1
echo "Timed out waiting for initialisation - killing CTDB"
pkill -9 -f $ctdbd >/dev/null 2>&1
fi
fi
case $init_style in
suse)
set_retval $RETVAL
rc_status -v
;;
redhat)
[ $RETVAL -eq 0 ] && success || failure
echo
;;
esac
return $RETVAL
}
stop() {
echo -n $"Shutting down ctdbd service: "
pkill -0 -f $ctdbd || {
echo -n " Warning: ctdbd not running ! "
case $init_style in
suse)
rc_status -v
;;
redhat)
echo ""
;;
esac
return 0
}
ctdb shutdown >/dev/null 2>&1
RETVAL=$?
count=0
while pkill -0 -f $ctdbd ; do
sleep 1
count=$(($count + 1))
[ $count -gt 30 ] && {
echo -n $"killing ctdbd "
pkill -9 -f $ctdbd
pkill -9 -f $CTDB_BASE/events.d/
}
done
# make sure all ips are dropped, pfkill -9 might leave them hanging around
drop_all_public_ips
rm -f "$pidfile"
case $init_style in
suse)
# re-set the return code to the recorded RETVAL in order
# to print the correct status message
set_retval $RETVAL
rc_status -v
;;
redhat)
[ $RETVAL -eq 0 ] && success || failure
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/ctdb
echo ""
;;
esac
return $RETVAL
}
restart() {
stop
start
}
# Given that CTDB_VALGRIND is a debug option we don't support the pid
# file. We just do a quick and dirty hack instead. Otherwise we just
# end up re-implementing each distro's pidfile support...
check_status_valgrind ()
{
if pkill -0 -f "valgrind.*${ctdbd}" ; then
echo "ctdbd is running under valgrind..."
return 0
else
echo "ctdbd is not running"
return 1
fi
}
check_status ()
{
# Backward compatibility. When we arrange to pass --pidfile to
# ctdbd we also create the directory that will contain it. If
# that directory is missing then we don't use the pidfile to check
# status.
if [ -d $(dirname "$pidfile") ] ; then
_pf_opt="-p $pidfile"
else
_pf_opt=""
fi
case "$init_style" in
valgrind)
check_status_valgrind
;;
suse)
checkproc $_pf_opt "$ctdbd"
rc_status -v
;;
redhat)
status $_pf_opt -l "ctdb" "$ctdbd"
;;
debian)
status_of_proc $_pf_opt "$ctdbd" "ctdb"
;;
esac
}
[ -x "$CTDB_BASE/rc.ctdb" ] && "$CTDB_BASE/rc.ctdb" $1
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload|force-reload)
restart
;;
status)
check_status
;;
condrestart|try-restart)
if check_status >/dev/null ; then
restart
fi
;;
cron)
# used from cron to auto-restart ctdb
check_status >/dev/null || restart
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|force-reload|status|cron|condrestart|try-restart}"
exit 1
esac
exit $?