#!/bin/sh # ctdb event script for Samba . $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} CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind} ;; debian) CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-samba} CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""} CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind} ;; *) # should not happen, but for now use redhat style as default: CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb} CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""} CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind} ;; esac service_name="samba" loadconfig ctdb_setup_service_state_dir service_start () { # If set then we force-start the relevant service. _service_name="$1" # make sure samba is not already started if [ "$_service_name" = "samba" ] || \ is_ctdb_managed_service "samba" ; then 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 } fi # make sure winbind is not already started if [ "$_service_name" = "winbind" ] || \ check_ctdb_manages_winbind ; then service "$CTDB_SERVICE_WINBIND" stop > /dev/null 2>&1 killall -0 -q winbindd && { sleep 1 # make absolutely sure winbindd is dead killall -q -9 winbindd } fi # start the winbind service if [ "$_service_name" = "winbind" ] || \ check_ctdb_manages_winbind ; then service "$CTDB_SERVICE_WINBIND" start || { echo failed to start winbind exit 1 } fi # 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 if [ "$_service_name" = "samba" ] || \ is_ctdb_managed_service "samba" ; then net serverid wipe if [ -n "$CTDB_SERVICE_NMB" ] ; then nice_service "$CTDB_SERVICE_NMB" start || { echo failed to start nmbd exit 1 } fi nice_service "$CTDB_SERVICE_SMB" start || { echo failed to start samba exit 1 } fi } service_stop () { # If set then we force-stop the relevant service. _service_name="$1" # shutdown Samba when ctdb goes down if [ "$_service_name" = "samba" ] || \ is_ctdb_managed_service "samba" ; then service "$CTDB_SERVICE_SMB" stop if [ -n "$CTDB_SERVICE_NMB" ] ; then service "$CTDB_SERVICE_NMB" stop fi fi # stop the winbind service if [ "$_service_name" = "winbind" ] || \ check_ctdb_manages_winbind ; then service "$CTDB_SERVICE_WINBIND" stop fi } service_reconfigure () { # Samba automatically reloads config - no restart needed. : } # set default samba cleanup period - in minutes [ -z "$SAMBA_CLEANUP_PERIOD" ] && { SAMBA_CLEANUP_PERIOD=10 } # we keep a cached copy of smb.conf here smbconf_cache="$service_state_dir/smb.conf.cache" ############################################# # update the smb.conf cache in the foreground testparm_foreground_update() { testparm -s 2> /dev/null | egrep -v 'registry.shares.=|include.=' > "$smbconf_cache" } ############################################# # update the smb.conf cache in the background testparm_background_update() { # if the cache doesn't exist, then update in the foreground [ -f $smbconf_cache ] || { testparm_foreground_update } # otherwise do a background update ( tmpfile="${smbconf_cache}.$$" testparm -s > $tmpfile 2> /dev/null & # remember the pid of the teamparm process pid="$!" # give it 10 seconds to run timeleft=10 while [ $timeleft -gt 0 ]; do timeleft=$(($timeleft - 1)) # see if the process still exists kill -0 $pid > /dev/null 2>&1 || { # it doesn't exist, grab its exit status wait $pid [ $? = 0 ] || { echo "50.samba: smb.conf background update exited with status $?" rm -f "${tmpfile}" exit 1 } # put the new smb.conf contents in the cache (atomic rename) # make sure we remove references to the registry while doing # this to ensure that running testparm on the cache does # not use the registry egrep -v 'registry.shares.=|include.=' < "$tmpfile" > "${tmpfile}.2" rm -f "$tmpfile" mv -f "${tmpfile}.2" "$smbconf_cache" || { echo "50.samba: failed to update background cache" rm -f "${tmpfile}.2" exit 1 } exit 0 } # keep waiting for testparm to finish sleep 1 done # it took more than 10 seconds - kill it off rm -f "${tmpfile}" kill -9 "$pid" > /dev/null 2>&1 echo "50.samba: timed out updating smbconf cache in background" exit 1 ) & } ################################################## # show the testparm output using a cached smb.conf # to avoid registry access testparm_cat() { [ -f $smbconf_cache ] || { testparm_foreground_update } testparm -s "$smbconf_cache" "$@" 2>/dev/null } # function to see if ctdb manages winbind - this overrides with extra # logic if $CTDB_MANAGES_WINBIND is not set or null. check_ctdb_manages_winbind() { if is_ctdb_managed_service "winbind" ; then return 0 elif [ -n "$CTDB_MANAGES_WINBIND" ] ; then # If this variable is set we want to respect it. We return # false here because we know it is not set to "yes" - if it # were then the 1st "if" above would have succeeded. return 1 else _secmode=`testparm_cat --parameter-name=security` case "$_secmode" in ADS|DOMAIN) return 0 ;; *) return 1 ;; esac fi } list_samba_shares () { testparm_cat | sed -n -e 's@^[[:space:]]*path[[:space:]]*=[[:space:]]@@p' | sed -e 's/"//g' } ########################### # 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 -np > /dev/null 2>&1 & } ########################### ctdb_start_stop_service ctdb_start_stop_service "winbind" is_ctdb_managed_service || is_ctdb_managed_service "winbind" || exit 0 ########################### case "$1" in startup) ctdb_service_start ;; shutdown) ctdb_service_stop ;; monitor) # Create a dummy file to track when we need to do periodic cleanup # of samba databases periodic_cleanup_file="$service_state_dir/periodic_cleanup" [ -f "$periodic_cleanup_file" ] || { touch "$periodic_cleanup_file" } [ `find "$periodic_cleanup_file" -mmin +$SAMBA_CLEANUP_PERIOD | wc -l` -eq 1 ] && { # Cleanup the databases periodic_cleanup touch "$periodic_cleanup_file" } is_ctdb_managed_service "samba" && { [ "$CTDB_SAMBA_SKIP_SHARE_CHECK" = "yes" ] || { testparm_background_update testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && { testparm_foreground_update testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && { echo "ERROR: testparm shows smb.conf is not clean" exit 1 } } list_samba_shares | ctdb_check_directories_probe || { testparm_foreground_update list_samba_shares | ctdb_check_directories } || exit $? } smb_ports="$CTDB_SAMBA_CHECK_PORTS" [ -z "$smb_ports" ] && { smb_ports=`testparm_cat --parameter-name="smb ports"` } ctdb_check_tcp_ports $smb_ports || exit $? } # check winbind is OK check_ctdb_manages_winbind && { ctdb_check_command "winbind" "wbinfo -p" } ;; takeip|releaseip) iface=$2 ip=$3 maskbits=$4 smbcontrol winbindd ip-dropped $ip >/dev/null 2>/dev/null ;; *) ctdb_standard_event_handler "$@" ;; esac exit 0