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