Eventscripts: 50.samba needs null service_reconfigure() function.
[ctdb.git] / config / events.d / 50.samba
1 #!/bin/sh
2 # ctdb event script for Samba
3
4 . $CTDB_BASE/functions
5
6 detect_init_style
7
8 case $CTDB_INIT_STYLE in
9         suse)
10                 CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb}
11                 CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-nmb}
12                 CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind}
13                 ;;
14         debian)
15                 CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-samba}
16                 CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""}
17                 CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind}
18                 ;;
19         *)
20                 # should not happen, but for now use redhat style as default:
21                 CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb}
22                 CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""}
23                 CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind}
24                 ;;
25 esac
26
27 service_name="samba"
28
29 loadconfig
30
31 ctdb_setup_service_state_dir
32
33 service_start ()
34 {
35         # If set then we force-start the relevant service.
36         _service_name="$1"
37
38         # make sure samba is not already started
39         if [ "$_service_name" = "samba" ] || \
40             is_ctdb_managed_service "samba" ; then
41                 service "$CTDB_SERVICE_SMB" stop > /dev/null 2>&1
42                 service "$CTDB_SERVICE_NMB" stop > /dev/null 2>&1
43                 killall -0 -q smbd && {
44                     sleep 1
45                     # make absolutely sure samba is dead
46                     killall -q -9 smbd
47                 }
48
49                 killall -0 -q nmbd && {
50                     sleep 1
51                     # make absolutely sure samba is dead
52                     killall -q -9 nmbd
53                 }
54         fi
55
56         # make sure winbind is not already started
57         if [ "$_service_name" = "winbind" ] || \
58             check_ctdb_manages_winbind ; then
59                 service "$CTDB_SERVICE_WINBIND" stop > /dev/null 2>&1
60                 killall -0 -q winbindd && {
61                     sleep 1
62                     # make absolutely sure winbindd is dead
63                     killall -q -9 winbindd
64                 }
65
66         fi
67
68         # start the winbind service
69         if [ "$_service_name" = "winbind" ] || \
70             check_ctdb_manages_winbind ; then
71                 service "$CTDB_SERVICE_WINBIND" start || {
72                     echo failed to start winbind
73                     exit 1
74                 }
75         fi
76
77         # start Samba service. Start it reniced, as under very heavy load 
78         # the number of smbd processes will mean that it leaves few cycles for
79         # anything else
80         if [ "$_service_name" = "samba" ] || \
81             is_ctdb_managed_service "samba" ; then
82                 net serverid wipe
83
84                 nice_service "$CTDB_SERVICE_NMB" start || {
85                         echo failed to start nmbd
86                         exit 1
87                 }
88                 nice_service "$CTDB_SERVICE_SMB" start || {
89                         echo failed to start samba
90                         exit 1
91                 }
92         fi
93 }
94
95 service_stop ()
96 {
97         # If set then we force-stop the relevant service.
98         _service_name="$1"
99
100         # shutdown Samba when ctdb goes down
101         if [ "$_service_name" = "samba" ] || \
102             is_ctdb_managed_service "samba" ; then
103                 service "$CTDB_SERVICE_SMB" stop
104                 service "$CTDB_SERVICE_NMB" stop
105         fi
106
107         # stop the winbind service
108         if [ "$_service_name" = "winbind" ] || \
109             check_ctdb_manages_winbind ; then
110                 service "$CTDB_SERVICE_WINBIND" stop
111         fi
112
113         return 0
114 }
115
116 service_reconfigure ()
117 {
118     # Samba automatically reloads config - no restart needed.
119     :
120 }
121
122 # set default samba cleanup period - in minutes
123 [ -z "$SAMBA_CLEANUP_PERIOD" ] && {
124     SAMBA_CLEANUP_PERIOD=10
125 }
126
127 # we keep a cached copy of smb.conf here
128 smbconf_cache="$service_state_dir/smb.conf.cache"
129
130
131 #############################################
132 # update the smb.conf cache in the foreground
133 testparm_foreground_update() {
134     testparm -s 2> /dev/null | egrep -v 'registry.shares.=|include.=' > "$smbconf_cache"
135 }
136
137 #############################################
138 # update the smb.conf cache in the background
139 testparm_background_update() {
140     # if the cache doesn't exist, then update in the foreground
141     [ -f $smbconf_cache ] || {
142         testparm_foreground_update
143     }
144     # otherwise do a background update
145     (
146         tmpfile="${smbconf_cache}.$$"
147         testparm -s > $tmpfile 2> /dev/null &
148         # remember the pid of the teamparm process
149         pid="$!"
150         # give it 10 seconds to run
151         timeleft=10
152         while [ $timeleft -gt 0 ]; do
153             timeleft=$(($timeleft - 1))
154             # see if the process still exists
155             kill -0 $pid > /dev/null 2>&1 || {
156                 # it doesn't exist, grab its exit status
157                 wait $pid
158                 [ $? = 0 ] || {
159                     echo "50.samba: smb.conf background update exited with status $?"
160                     rm -f "${tmpfile}"
161                     exit 1
162                 }               
163                 # put the new smb.conf contents in the cache (atomic rename)
164                 # make sure we remove references to the registry while doing 
165                 # this to ensure that running testparm on the cache does
166                 # not use the registry
167                 egrep -v 'registry.shares.=|include.=' < "$tmpfile" > "${tmpfile}.2"
168                 rm -f "$tmpfile"
169                 mv -f "${tmpfile}.2" "$smbconf_cache" || {
170                     echo "50.samba: failed to update background cache"
171                     rm -f "${tmpfile}.2"
172                     exit 1
173                 }
174                 exit 0
175             }
176             # keep waiting for testparm to finish
177             sleep 1
178         done
179         # it took more than 10 seconds - kill it off
180         rm -f "${tmpfile}"
181         kill -9 "$pid" > /dev/null 2>&1
182         echo "50.samba: timed out updating smbconf cache in background"
183         exit 1
184     ) &
185 }
186
187 ##################################################
188 # show the testparm output using a cached smb.conf 
189 # to avoid registry access
190 testparm_cat() {
191     [ -f $smbconf_cache ] || {
192         testparm_foreground_update
193     }
194     testparm -s "$smbconf_cache" "$@" 2>/dev/null
195 }
196
197 # function to see if ctdb manages winbind - this overrides with extra
198 # logic if $CTDB_MANAGES_WINBIND is not set or null.
199 check_ctdb_manages_winbind() {
200     if is_ctdb_managed_service "winbind" ; then
201         return 0
202     elif [ -n "$CTDB_MANAGES_WINBIND" ] ; then
203         # If this variable is set we want to respect it.  We return
204         # false here because we know it is not set to "yes" - if it
205         # were then the 1st "if" above would have succeeded.
206         return 1
207     else
208         _secmode=`testparm_cat --parameter-name=security`
209         case "$_secmode" in
210             ADS|DOMAIN)
211                 return 0
212                 ;;
213             *)
214                 return 1
215                 ;;
216         esac
217     fi
218 }
219
220 list_samba_shares ()
221 {
222     testparm_cat |
223     sed -n -e 's@^[[:space:]]*path[[:space:]]*=[[:space:]]@@p' |
224     sed -e 's/"//g'
225 }
226
227
228 ###########################
229 # periodic cleanup function
230 periodic_cleanup() {
231     # running smbstatus scrubs any dead entries from the connections
232     # and sessionid database
233     # echo "Running periodic cleanup of samba databases"
234     smbstatus -np > /dev/null 2>&1 &
235 }
236
237 ###########################
238
239 ctdb_start_stop_service
240 ctdb_start_stop_service "winbind"
241
242 is_ctdb_managed_service || is_ctdb_managed_service "winbind" || exit 0
243
244 ###########################
245
246 case "$1" in 
247      startup)
248         ctdb_service_start
249         ;;
250         
251      shutdown)
252         ctdb_service_stop
253         ;;
254
255      monitor)
256         # Create a dummy file to track when we need to do periodic cleanup
257         # of samba databases
258         periodic_cleanup_file="$service_state_dir/periodic_cleanup"
259         [ -f "$periodic_cleanup_file" ] || {
260                 touch "$periodic_cleanup_file"
261         }
262         [ `find "$periodic_cleanup_file" -mmin +$SAMBA_CLEANUP_PERIOD | wc -l` -eq 1 ] && {
263                 # Cleanup the databases
264                 periodic_cleanup
265                 touch "$periodic_cleanup_file"
266         }
267
268         is_ctdb_managed_service "samba" && {
269                 [ "$CTDB_SAMBA_SKIP_SHARE_CHECK" = "yes" ] || {
270                         testparm_background_update
271
272                         testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && {
273                             testparm_foreground_update
274                             testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && {
275                                 echo "ERROR: testparm shows smb.conf is not clean"
276                                 exit 1
277                             }
278                         }
279                         
280                         list_samba_shares |
281                         ctdb_check_directories_probe || {
282                             testparm_foreground_update
283                             list_samba_shares |
284                             ctdb_check_directories
285                         } || exit $?
286                 }
287
288                 smb_ports="$CTDB_SAMBA_CHECK_PORTS"
289                 [ -z "$smb_ports" ] && {
290                         smb_ports=`testparm_cat --parameter-name="smb ports"`
291                 }
292                 ctdb_check_tcp_ports $smb_ports || exit $?
293         }
294
295         # check winbind is OK
296         check_ctdb_manages_winbind && {
297                 ctdb_check_command "winbind" "wbinfo -p"
298         }
299         ;;
300
301      takeip|releaseip)
302         iface=$2
303         ip=$3
304         maskbits=$4
305
306         smbcontrol winbindd ip-dropped $ip >/dev/null 2>/dev/null
307         ;;
308     *)
309         ctdb_standard_event_handler "$@"
310         ;;
311 esac
312
313 exit 0