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