#!/bin/sh
# ctdb event script for Samba
-PATH=/bin:/usr/bin:$PATH
-
-. $CTDB_BASE/functions
-loadconfig ctdb
-
-cmd="$1"
-shift
-
-[ "$CTDB_MANAGES_SAMBA" = "yes" ] || exit 0
+[ -n "$CTDB_BASE" ] || \
+ CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; dirname "$PWD")
+
+. "${CTDB_BASE}/functions"
+
+detect_init_style
+
+case $CTDB_INIT_STYLE in
+ suse)
+ CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb}
+ CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-nmb}
+ ;;
+ debian)
+ CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-samba}
+ CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""}
+ ;;
+ *)
+ # Use redhat style as default:
+ CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb}
+ CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""}
+ ;;
+esac
-# set default samba cleanup period - in minutes
-[ -z "$SAMBA_CLEANUP_PERIOD" ] && {
- SAMBA_CLEANUP_PERIOD=10
+service_name="samba"
+
+loadconfig
+
+ctdb_setup_service_state_dir
+
+service_start ()
+{
+ # make sure samba is not already started
+ service "$CTDB_SERVICE_SMB" stop > /dev/null 2>&1
+ if [ -n "$CTDB_SERVICE_NMB" ] ; then
+ service "$CTDB_SERVICE_NMB" stop > /dev/null 2>&1
+ fi
+ killall -0 -q smbd && {
+ sleep 1
+ # make absolutely sure samba is dead
+ killall -q -9 smbd
+ }
+ killall -0 -q nmbd && {
+ sleep 1
+ # make absolutely sure samba is dead
+ killall -q -9 nmbd
+ }
+
+ # start Samba service. Start it reniced, as under very heavy load
+ # the number of smbd processes will mean that it leaves few cycles
+ # for anything else
+ net serverid wipe
+
+ if [ -n "$CTDB_SERVICE_NMB" ] ; then
+ nice_service "$CTDB_SERVICE_NMB" start || die "Failed to start nmbd"
+ fi
+
+ nice_service "$CTDB_SERVICE_SMB" start || die "Failed to start samba"
}
+service_stop ()
+{
+ service "$CTDB_SERVICE_SMB" stop
+ if [ -n "$CTDB_SERVICE_NMB" ] ; then
+ service "$CTDB_SERVICE_NMB" stop
+ fi
+}
-# autodetect use of winbind if not set in config file
-[ -z "$CTDB_MANAGES_WINBIND" ] && {
- secmode=`testparm -s --parameter-name=security 2> /dev/null`
- case $secmode in
- ADS|DOMAIN)
- CTDB_MANAGES_WINBIND="yes";
+######################################################################
+# Show the testparm output using a cached smb.conf to avoid delays due
+# to registry access.
+
+smbconf_cache="$service_state_dir/smb.conf.cache"
+
+testparm_foreground_update ()
+{
+ _timeout="$1"
+
+ # No need to remove these temporary files, since there are only 2
+ # of them.
+ _out="${smbconf_cache}.out"
+ _err="${smbconf_cache}.err"
+
+ timeout "$_timeout" testparm -v -s >"$_out" 2>"$_err"
+ case $? in
+ 0) : ;;
+ 124)
+ if [ -f "$smbconf_cache" ] ; then
+ echo "WARNING: smb.conf cache update timed out - using old cache file"
+ return 1
+ else
+ echo "ERROR: smb.conf cache create failed - testparm command timed out"
+ exit 1
+ fi
;;
*)
- CTDB_MANAGES_WINBIND="no";
- ;;
+ if [ -f "$smbconf_cache" ] ; then
+ echo "WARNING: smb.conf cache update failed - using old cache file"
+ cat "$_err"
+ return 1
+ else
+ echo "ERROR: smb.conf cache create failed - testparm failed with:"
+ cat "$_err"
+ exit 1
+ fi
esac
+
+ # Only using $$ here to avoid a collision. This is written into
+ # CTDB's own state directory so there is no real need for a secure
+ # temporary file.
+ _tmpfile="${smbconf_cache}.$$"
+ # Patterns to exclude...
+ _pat='^[[:space:]]+(registry[[:space:]]+shares|include|copy|winbind[[:space:]]+separator)[[:space:]]+='
+ grep -Ev "$_pat" <"$_out" >"$_tmpfile"
+ mv "$_tmpfile" "$smbconf_cache" # atomic
+
+ return 0
}
-###########################
-# periodic cleanup function
-periodic_cleanup() {
- # running smbstatus scrubs any dead entries from the connections
- # and sessionid database
- echo "Running periodic cleanup of samba databases"
- smbstatus -n > /dev/null 2>&1 &
+testparm_background_update ()
+{
+ _timeout="$1"
+
+ testparm_foreground_update "$_timeout" >/dev/null 2>&1 </dev/null &
}
-case $cmd in
- startup)
- # create the state directory for samba
- /bin/mkdir -p $CTDB_BASE/state/samba
-
- # make sure samba is not already started
- service smb stop > /dev/null 2>&1
- killall -0 -q smbd && {
- sleep 1
- # make absolutely sure samba is dead
- killall -q -9 smbd
- }
-
- # restart the winbind service
- [ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
- service winbind stop > /dev/null 2>&1
- killall -0 -q winbindd && {
- sleep 1
- # make absolutely sure winbindd is dead
- killall -q -9 winbindd
- }
- service winbind start
- }
-
- # start Samba service. Start it reniced, as under very heavy load
- # the number of smbd processes will mean that it leaves few cycles for
- # anything else
- nice service smb start
- ;;
-
- takeip)
- # nothing special for Samba
- ;;
+testparm_cat ()
+{
+ testparm -s "$smbconf_cache" "$@" 2>/dev/null
+}
- releaseip)
- # nothing special for Samba
- ;;
+list_samba_shares ()
+{
+ testparm_cat |
+ sed -n -e 's@^[[:space:]]*path[[:space:]]*=[[:space:]]@@p' |
+ sed -e 's/"//g'
+}
+
+list_samba_ports ()
+{
+ testparm_cat --parameter-name="smb ports" |
+ sed -e 's@,@ @g'
+}
+
+###########################
- recovered)
- # nothing special for Samba
- exit 0
+ctdb_start_stop_service
+
+is_ctdb_managed_service || exit 0
+
+###########################
+
+case "$1" in
+ startup)
+ ctdb_service_start
;;
shutdown)
- # shutdown Samba when ctdb goes down
- service smb stop
-
- # stop the winbind service
- [ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
- service winbind stop
- }
+ ctdb_service_stop
;;
monitor)
- # Create a dummy file to track when we need to do periodic cleanup
- # of samba databases
- [ -f $CTDB_BASE/state/samba/periodic_cleanup ] || {
- touch $CTDB_BASE/state/samba/periodic_cleanup
- }
- [ `/usr/bin/find $CTDB_BASE/state/samba/periodic_cleanup -mmin +$SAMBA_CLEANUP_PERIOD | wc -l` -eq 1 ] && {
- # Cleanup the databases
- periodic_cleanup
- touch $CTDB_BASE/state/samba/periodic_cleanup
- }
-
- testparm -s 2>&1 | egrep '^WARNING|^ERROR|^Unknown' && {
- echo "ERROR: testparm shows smb.conf is not clean"
- exit 1
- }
-
- smb_dirs=`testparm -s 2> /dev/null | egrep '^\s*path = ' | cut -d= -f2`
- ctdb_check_directories "Samba" $smb_dirs
-
- smb_ports=`testparm -s --parameter-name="smb ports" 2> /dev/null`
- ctdb_check_tcp_ports "Samba" $smb_ports
-
- # check winbind is OK
- [ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
- ctdb_check_command "winbind" "wbinfo -p"
- }
+ testparm_foreground_update 10
+ ret=$?
+
+ smb_ports="$CTDB_SAMBA_CHECK_PORTS"
+ if [ -z "$smb_ports" ] ; then
+ smb_ports=$(list_samba_ports)
+ [ -n "$smb_ports" ] || die "Failed to set smb ports"
+ fi
+ ctdb_check_tcp_ports $smb_ports || exit $?
+
+ if [ "$CTDB_SAMBA_SKIP_SHARE_CHECK" != "yes" ] ; then
+ list_samba_shares | ctdb_check_directories || exit $?
+ fi
+
+ if [ $ret -ne 0 ] ; then
+ testparm_background_update 10
+ fi
;;
+ *)
+ ctdb_standard_event_handler "$@"
+ ;;
esac
-# ignore unknown commands
exit 0