Merge commit 'ronnie/master'
[nivanova/samba-autobuild/.git] / ctdb / config / events.d / 50.samba
index 0c48252a763ec4449aa1b39459bdfb681910fc7c..3e7164abaf3186220a695543792706fef291baf0 100755 (executable)
 
 PATH=/bin:/usr/bin:$PATH
 
-. /etc/ctdb/functions
+. $CTDB_BASE/functions
 loadconfig ctdb
+loadconfig samba
+
+detect_init_style
+
+case $CTDB_INIT_STYLE in
+       suse)
+               CTDB_SERVICE_SMB="smb"
+               CTDB_SERVICE_NMB="nmb"
+               CTDB_SERVICE_WINBIND="winbind"
+               ;;
+       ubuntu)
+               CTDB_SERVICE_SMB="samba"
+               CTDB_SERVICE_NMB=""
+               CTDB_SERVICE_WINBIND="winbind"
+               ;;
+       redhat)
+               CTDB_SERVICE_SMB="smb"
+               CTDB_SERVICE_NMB=""
+               CTDB_SERVICE_WINBIND="winbind"
+               ;;
+       *)
+               # should not happen, but for now use redhat style as default:
+               CTDB_SERVICE_SMB="smb"
+               CTDB_SERVICE_NMB=""
+               CTDB_SERVICE_WINBIND="winbind"
+               ;;
+esac
 
 cmd="$1"
 shift
 
 [ "$CTDB_MANAGES_SAMBA" = "yes" ] || exit 0
 
+# 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="$CTDB_BASE/state/samba/smb.conf.cache"
+
+
+#############################################
+# update the smb.conf cache in the foreground
+testparm_foreground_update() {
+    mkdir -p "$CTDB_BASE/state/samba" || exit 1
+    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
+check_ctdb_manages_winbind() {
+  [ -z "$CTDB_MANAGES_WINBIND" ] && {
+    secmode=`testparm_cat --parameter-name=security`
+    case $secmode in
+       ADS|DOMAIN)
+           CTDB_MANAGES_WINBIND="yes";
+           ;;
+       *)
+           CTDB_MANAGES_WINBIND="no";
+           ;;
+    esac
+  }
+}
+
+###########################
+# 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 &
+}
+
 case $cmd in 
      startup)
-       # wait for all shared directories to become available
-       smb_dirs=`testparm -s 2> /dev/null | egrep '^\s*path = '  | cut -d= -f2`
-       ctdb_wait_directories "Samba" $smb_dirs 
+       # 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
-       service winbind stop > /dev/null 2>&1
+       service "$CTDB_SERVICE_SMB" stop > /dev/null 2>&1
+       service "$CTDB_SERVICE_NMB" stop > /dev/null 2>&1
+       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
+       }
+
+       # restart the winbind service
+       check_ctdb_manages_winbind
+       [ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
+               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
+               }
+               service "$CTDB_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
-       service winbind start
-
-       # wait for the Samba tcp ports to become available
-       smb_ports=`testparm -sv 2> /dev/null | egrep '\s*smb ports =' | cut -d= -f2`
-       ctdb_wait_tcp_ports "Samba" $smb_ports
+       nice_service "$CTDB_SERVICE_NMB" start
+       nice_service "$CTDB_SERVICE_SMB" start
        ;;
        
      takeip)
@@ -47,21 +192,58 @@ case $cmd in
 
      shutdown)
        # shutdown Samba when ctdb goes down
-       service smb stop
-       service winbind stop
+       service "$CTDB_SERVICE_SMB" stop
+       service "$CTDB_SERVICE_NMB" stop
+
+       # stop the winbind service
+       check_ctdb_manages_winbind
+       [ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
+               service "$CTDB_SERVICE_WINBIND" stop
+       }
        ;;
 
      monitor)
-       testparm -s 2>&1 | egrep '^WARNING|^ERROR|^Unknown' && {
-           echo "`date` ERROR: testparm shows smb.conf is not clean"
-           exit 1
+       # 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
        }
 
-       smb_dirs=`testparm -s 2> /dev/null | egrep '^\s*path = '  | cut -d= -f2`
-       ctdb_check_directories "Samba" $smb_dirs        
+       [ "$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
+                   }
+               }
+
+               smb_dirs=`testparm_cat | egrep '^[[:space:]]*path = ' | cut -d= -f2`
+               ctdb_check_directories_probe "Samba" $smb_dirs || {
+                   testparm_foreground_update
+                   smb_dirs=`testparm_cat | egrep '^[[:space:]]*path = ' | cut -d= -f2`
+                   ctdb_check_directories "Samba" $smb_dirs
+               }
+       }
 
-       smb_ports=`testparm -sv 2> /dev/null | egrep '\s*smb ports =' | cut -d= -f2`
+       smb_ports="$CTDB_SAMBA_CHECK_PORTS"
+       [ -z "$smb_ports" ] && {
+               smb_ports=`testparm_cat --parameter-name="smb ports"`
+       }
        ctdb_check_tcp_ports "Samba" $smb_ports
+
+       # check winbind is OK
+       check_ctdb_manages_winbind
+       [ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
+               ctdb_check_command "winbind" "wbinfo -p"
+       }
        ;;
 
 esac