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