Eventscripts: make 50.samba use $service_state_dir.
[samba.git] / ctdb / 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 # set default samba cleanup period - in minutes
117 [ -z "$SAMBA_CLEANUP_PERIOD" ] && {
118     SAMBA_CLEANUP_PERIOD=10
119 }
120
121 # we keep a cached copy of smb.conf here
122 smbconf_cache="$service_state_dir/smb.conf.cache"
123
124
125 #############################################
126 # update the smb.conf cache in the foreground
127 testparm_foreground_update() {
128     testparm -s 2> /dev/null | egrep -v 'registry.shares.=|include.=' > "$smbconf_cache"
129 }
130
131 #############################################
132 # update the smb.conf cache in the background
133 testparm_background_update() {
134     # if the cache doesn't exist, then update in the foreground
135     [ -f $smbconf_cache ] || {
136         testparm_foreground_update
137     }
138     # otherwise do a background update
139     (
140         tmpfile="${smbconf_cache}.$$"
141         testparm -s > $tmpfile 2> /dev/null &
142         # remember the pid of the teamparm process
143         pid="$!"
144         # give it 10 seconds to run
145         timeleft=10
146         while [ $timeleft -gt 0 ]; do
147             timeleft=$(($timeleft - 1))
148             # see if the process still exists
149             kill -0 $pid > /dev/null 2>&1 || {
150                 # it doesn't exist, grab its exit status
151                 wait $pid
152                 [ $? = 0 ] || {
153                     echo "50.samba: smb.conf background update exited with status $?"
154                     rm -f "${tmpfile}"
155                     exit 1
156                 }               
157                 # put the new smb.conf contents in the cache (atomic rename)
158                 # make sure we remove references to the registry while doing 
159                 # this to ensure that running testparm on the cache does
160                 # not use the registry
161                 egrep -v 'registry.shares.=|include.=' < "$tmpfile" > "${tmpfile}.2"
162                 rm -f "$tmpfile"
163                 mv -f "${tmpfile}.2" "$smbconf_cache" || {
164                     echo "50.samba: failed to update background cache"
165                     rm -f "${tmpfile}.2"
166                     exit 1
167                 }
168                 exit 0
169             }
170             # keep waiting for testparm to finish
171             sleep 1
172         done
173         # it took more than 10 seconds - kill it off
174         rm -f "${tmpfile}"
175         kill -9 "$pid" > /dev/null 2>&1
176         echo "50.samba: timed out updating smbconf cache in background"
177         exit 1
178     ) &
179 }
180
181 ##################################################
182 # show the testparm output using a cached smb.conf 
183 # to avoid registry access
184 testparm_cat() {
185     [ -f $smbconf_cache ] || {
186         testparm_foreground_update
187     }
188     testparm -s "$smbconf_cache" "$@" 2>/dev/null
189 }
190
191 # function to see if ctdb manages winbind - this overrides with extra
192 # logic if $CTDB_MANAGES_WINBIND is not set or null.
193 check_ctdb_manages_winbind() {
194     if is_ctdb_managed_service "winbind" ; then
195         return 0
196     elif [ -n "$CTDB_MANAGES_WINBIND" ] ; then
197         # If this variable is set we want to respect it.  We return
198         # false here because we know it is not set to "yes" - if it
199         # were then the 1st "if" above would have succeeded.
200         return 1
201     else
202         _secmode=`testparm_cat --parameter-name=security`
203         case "$_secmode" in
204             ADS|DOMAIN)
205                 return 0
206                 ;;
207             *)
208                 return 1
209                 ;;
210         esac
211     fi
212 }
213
214 list_samba_shares ()
215 {
216     testparm_cat |
217     sed -n -e 's@^[[:space:]]*path[[:space:]]*=[[:space:]]@@p' |
218     sed -e 's/"//g'
219 }
220
221
222 ###########################
223 # periodic cleanup function
224 periodic_cleanup() {
225     # running smbstatus scrubs any dead entries from the connections
226     # and sessionid database
227     # echo "Running periodic cleanup of samba databases"
228     smbstatus -np > /dev/null 2>&1 &
229 }
230
231 ###########################
232
233 ctdb_start_stop_service
234 ctdb_start_stop_service "winbind"
235
236 is_ctdb_managed_service || is_ctdb_managed_service "winbind" || exit 0
237
238 ###########################
239
240 case "$1" in 
241      startup)
242         ctdb_service_start
243         ;;
244         
245      shutdown)
246         ctdb_service_stop
247         ;;
248
249      monitor)
250         # Create a dummy file to track when we need to do periodic cleanup
251         # of samba databases
252         periodic_cleanup_file="$service_state_dir/periodic_cleanup"
253         [ -f "$periodic_cleanup_file" ] || {
254                 touch "$periodic_cleanup_file"
255         }
256         [ `find "$periodic_cleanup_file" -mmin +$SAMBA_CLEANUP_PERIOD | wc -l` -eq 1 ] && {
257                 # Cleanup the databases
258                 periodic_cleanup
259                 touch "$periodic_cleanup_file"
260         }
261
262         is_ctdb_managed_service "samba" && {
263                 [ "$CTDB_SAMBA_SKIP_SHARE_CHECK" = "yes" ] || {
264                         testparm_background_update
265
266                         testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && {
267                             testparm_foreground_update
268                             testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && {
269                                 echo "ERROR: testparm shows smb.conf is not clean"
270                                 exit 1
271                             }
272                         }
273                         
274                         list_samba_shares |
275                         ctdb_check_directories_probe || {
276                             testparm_foreground_update
277                             list_samba_shares |
278                             ctdb_check_directories
279                         } || exit $?
280                 }
281
282                 smb_ports="$CTDB_SAMBA_CHECK_PORTS"
283                 [ -z "$smb_ports" ] && {
284                         smb_ports=`testparm_cat --parameter-name="smb ports"`
285                 }
286                 ctdb_check_tcp_ports $smb_ports || exit $?
287         }
288
289         # check winbind is OK
290         check_ctdb_manages_winbind && {
291                 ctdb_check_command "winbind" "wbinfo -p"
292         }
293         ;;
294
295      takeip|releaseip)
296         iface=$2
297         ip=$3
298         maskbits=$4
299
300         smbcontrol winbindd ip-dropped $ip >/dev/null 2>/dev/null
301         ;;
302     *)
303         ctdb_standard_event_handler "$@"
304         ;;
305 esac
306
307 exit 0