Whamcloud - gitweb
LU-5162 mdc: Add exception entry check for radix_tree
[fs/lustre-release.git] / lustre / contrib / lustre_server.sh
1 #!/bin/bash
2 #
3 # License:      GNU General Public License (GPL)
4
5 # lustre_server
6 #      Description: Manages a lustre_server on a shared storage medium.
7 #  Original Author: Eric Z. Ayers (eric.ayers@compgen.com)
8 # Original Release: 25 Oct 2000
9 #
10 # Rewritten Filesystem agent to lustre_server agent by bschubert@ddn.com
11 #
12 # usage: ./lustre_server {start|stop|status|monitor|validate-all|meta-data}
13 #
14 #         OCF parameters are as below:
15 #               OCF_RESKEY_device
16 #               OCF_RESKEY_directory
17 #               OCF_RESKEY_options
18 #
19 #OCF_RESKEY_device    : name of block device for the filesystem. e.g. /dev/sda1, /dev/md0
20 #                       Or a -U or -L option for mount, or an NFS mount specification
21 #OCF_RESKEY_directory : the mount point for the filesystem
22 #OCF_RESKEY_options   : options to be given to the mount command via -o
23 #
24 #
25 # NOTE: There is no locking (such as a SCSI reservation) being done here.
26 #       I would if the SCSI driver could properly maintain the reservation,
27 #       which it cannot, even with the 'scsi reservation' patch submitted
28 #       earlier this year by James Bottomley.  The patch minimizes the
29 #       bus resets caused by a RESERVATION_CONFLICT return, and helps the
30 #       reservation stay when 2 nodes contend for a reservation,
31 #       but it does not attempt to recover the reservation in the
32 #       case of a bus reset.
33 #
34 #       What all this means is that if 2 nodes mount the same file system
35 #       read-write, the filesystem is going to become corrupted. However
36 #       Lustre provides the Multi-Mount-Protection feature (MMP).
37 #
38 #       As a result, you should use this together with the stonith option
39 #       and redundant, independent communications paths.
40 #
41 #       If you don't do this, don't blame us when you scramble your disk.
42 #
43 #       Note:  the ServeRAID controller does prohibit concurrent acess
44 #       In this case, you don't actually need STONITH, but redundant comm is
45 #       still an excellent idea.
46 #
47
48 #######################################################################
49 # Initialization:
50
51 . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
52
53 #######################################################################
54 HOSTOS=`uname`
55 FSTYPE="lustre"
56
57 # FIXME: OCF_DEBUG officially supported in the the mean time?
58 #OCF_DEBUG=yes
59
60 usage() {
61         cat <<-EOT
62         usage: $0 {start|stop|status|monitor|validate-all|meta-data}
63         EOT
64 }
65
66 meta_data() {
67         cat <<END
68 <?xml version="1.0"?>
69 <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
70 <resource-agent name="lustre_server">
71 <version>1.0</version>
72
73
74 <longdesc lang="en">
75   Resource script for lustre_server. It manages a lustre_server on a shared storage medium. 
76 </longdesc>
77 <shortdesc lang="en">lustre_server resource agent</shortdesc>
78
79 <parameters>
80   <parameter name="device" required="1">
81     <longdesc lang="en">
82        The name of block device for the filesystem
83   </longdesc>
84   <shortdesc lang="en">block device</shortdesc>
85   <content type="string" default="" />
86 </parameter>
87
88 <parameter name="directory" required="1">
89  <longdesc lang="en">
90    The mount point for the filesystem.
91  </longdesc>
92  <shortdesc lang="en">mount point</shortdesc>
93  <content type="string" default="" />
94 </parameter>
95
96 <parameter name="options">
97  <longdesc lang="en">
98   Any extra options to be given as -o options to mount.
99  </longdesc>
100  <shortdesc lang="en">options</shortdesc>
101  <content type="string" default="" />
102 </parameter>
103 </parameters>
104
105 <actions>
106  <action name="start" timeout="300" />
107  <action name="stop" timeout="300" />
108  <action name="monitor" depth="0" timeout="300" interval="120" start-delay="10" />
109  <action name="validate-all" timeout="5" />
110  <action name="meta-data" timeout="5" />
111  </actions>
112 </resource-agent>
113 END
114 }
115
116 #
117 #       Make sure the kernel does the right thing with the FS buffers
118 #       This function should be called after unmounting and before mounting
119 #       It may not be necessary in 2.4 and later kernels, but it shouldn't hurt
120 #       anything either...
121 #
122 #       It's really a bug that you have to do this at all...
123 #
124 flushbufs() {
125     if have_binary $BLOCKDEV ; then
126        $BLOCKDEV --flushbufs $1
127     fi
128     return 0
129 }
130
131 # Figure out the real device number of external journals
132 # we need to provide as mount options, since the block
133 # device only know major/minor of the the journal device and it
134 # might/will change dynamically on reboots and between servers
135 # It would be MUCH better if 'mount' would do it on its own
136 # and in fact mount is already linked against libblkid to do
137 # this job
138 get_external_journal_device()
139 {
140         UUID=`dumpe2fs -h $DEVICE 2>/dev/null | awk '/^Journal UUID/{print $3}'`
141         if [ -z "$UUID" ]; then
142                 # device has internal journal, not need to proceed
143                 return
144         fi
145
146         # prefer /dev/mapper/
147         JDEV="`blkid -t UUID=$UUID /dev/mapper/* | awk -F: '{print $1}'`"
148         if [ -z "$JDEV" ]; then
149                 JDEV="`blkid -t UUID=$UUID | awk -F: '{print $1}'`"
150         fi
151
152         if [ -z "$JDEV" ]; then
153                 # know the journal is on an external device, but we can't find it
154                 ocf_log err "Cannot find device with journal UUID $UUID"
155                 return $OCF_ERR_GENERIC
156         fi
157
158         DEVNUM="`stat -c %02t%02T $JDEV`"
159         if [ -z "$DEVNUM" ]; then
160                 ocf_log err "Failed to retrieve device number of Journal device"
161                 return $OCF_ERR_GENERIC
162         fi
163
164         # add 0x only here, because we couldn't check for an empty string otherwise
165         DEVNUM="0x$DEVNUM"
166
167         echo $DEVNUM
168         return 0
169 }
170
171 # Take advantage of /proc/mounts if present, use portable mount command
172 # otherwise. Normalize format to "dev mountpoint fstype".
173 list_mounts() {
174         mtab=/proc/mounts
175         if [ ! -f $mtab ]; then
176                 ocf_log err "$mtab is missing!"
177                 exit $OCF_ERR_GENERIC
178         fi
179         cat $mtab | cut -d' ' -f1,2,3
180 }
181
182 lustre_health_check()
183 {
184         proc="/proc/fs/lustre/health_check"
185         # on first check the lustre modules are not loaded yet
186         if [ ! -e $proc ]; then
187                 return 0
188         fi
189
190         check=`cat $proc`
191         if [ "$check" = "healthy" ]; then
192                 return 0
193         else
194                 ocf_log err "$proc is $check"
195                 return 1
196         fi
197 }
198
199 #
200 # START: Start up the filesystem
201 #
202 lustre_server_start()
203 {
204         lustre_health_check
205         if [ $? -ne 0 ]; then
206                 return ${OCF_ERR_GENERIC}
207         fi
208
209         # See if the device is currently mounted
210         lustre_server_status >/dev/null 2>&1
211         rc=$?
212         if [ $rc -ne $OCF_NOT_RUNNING -a $rc -ne $OCF_SUCCESS ]; then
213                 ocf_log err "Unexpected status ($c) before mounting $DEVICE to $MOUNTPOINT"
214         elif [ $rc -eq $OCF_SUCCESS ]; then
215                 return $OCF_SUCCESS
216         fi
217
218         if [ ! -d "$MOUNTPOINT" ] ; then
219                 ocf_log err "Couldn't find directory  [$MOUNTPOINT] to use as a mount point"
220                 exit $OCF_ERR_ARGS
221         fi
222
223         flushbufs $DEVICE
224
225         jdev=`get_external_journal_device`
226         rc=$?
227         if [ $rc -ne 0 ]; then
228                 ocf_log err "Failure to get journal device"
229                 return $rc
230         fi
231
232         if [ -n "$jdev" ]; then
233                 if [ -n "$options" ]; then
234                         options="$options,journal_dev=$jdev"
235                 else
236                         options="-ojournal_dev=$jdev"
237                 fi
238         fi
239
240         # Mount the filesystem.
241         cmd="$MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT"
242         ocf_log info "Running $cmd"
243         res=`eval $cmd 2>&1`
244         if [ $? -ne 0 ]; then
245                 ocf_log err "cmd \"$cmd\" failed: $res"
246                 return $OCF_ERR_GENERIC
247         fi
248
249         return 0
250 }
251 # end of lustre_server_start
252
253 #
254 # STOP: Unmount the filesystem
255 #
256 lustre_server_stop()
257 {
258         # See if the device is currently mounted
259         lustre_server_mounted >/dev/null 2>&1
260         if [ $? -eq $OCF_NOT_RUNNING ]; then
261                 # Already unmounted, wonderful.
262                 rc=$OCF_SUCCESS
263         else
264                 # Umount $MOUNTPOINT.
265                 ocf_log info "Trying to unmount $MOUNTPOINT"
266                 cmd="$UMOUNT $MOUNTPOINT"
267                 ocf_log info "Running $cmd"
268                 res=`eval $cmd 2>&1`
269                 rc=$?
270                 if [ $rc -eq 0 ] ; then
271                         rc=$OCF_SUCCESS
272                         ocf_log info "unmounted $MOUNTPOINT successfully"
273                 else
274                         rc=$OCF_ERR_GENERIC
275                         ocf_log err "\"$cmd\" failed ($rc): $res"
276                 fi
277         fi
278
279         flushbufs $DEVICE
280
281         return $rc
282 }
283 # end of lustre_server_stop
284
285 #
286 # MOUNTED: is the filesystem mounted or not?
287 #
288 lustre_server_mounted()
289 {
290         if list_mounts | grep -q " $MOUNTPOINT " >/dev/null 2>&1; then
291                 rc=$OCF_SUCCESS
292                 msg="$MOUNTPOINT is mounted (running)"
293         else
294                 rc=$OCF_NOT_RUNNING
295                 msg="$MOUNTPOINT is unmounted (stopped)"
296         fi
297
298         # check in all mntdevs if really not mounted
299         # lustre bug 21359 (https://bugzilla.lustre.org/show_bug.cgi?id=21359)
300         if [ $rc -eq $OCF_NOT_RUNNING ]; then
301                 local list="/proc/fs/lustre/mds/* /proc/fs/lustre/obdfilter/*"
302                 for i in $list ; do
303                         if [ -f ${i}/mntdev ]; then
304                                 MNTDEVS="$MNTDEVS ${i}/mntdev"
305                         fi
306                 done
307                 local mgsdev=/proc/fs/lustre/mgs/MGS/mntdev
308                 if [ -f $mgsdev ]; then
309                         MNTDEVS="$MNTDEVS $mgsdev"
310                 fi
311                 for i in $MNTDEVS; do
312                         local dev=`cat $i`
313                         if [ "$dev" = "$DEVICE" ]; then
314                                 ocf_log err "Bug21359, /proc/mounts claims device is not mounted, but $i proves this is wrong"
315                                 rc=$OCF_ERR_GENERIC
316                         fi
317                 done
318
319         fi
320
321         if [ "$OCF_DEBUG" = "yes" ]; then
322                 ocf_log info "$msg"
323         fi
324
325         case "$OP" in
326         status) ocf_log info "$msg"
327                 ;;
328         monitor)
329                 if [ $rc -ne $OCF_SUCCESS ]; then
330                         ocf_log err "$msg"
331                 fi
332         esac
333
334         return $rc
335 }
336 # end of lustre_server_mounted
337
338 #
339 # STATUS: is the filesystem mounted and healthy or not?
340 #
341 lustre_server_status()
342 {
343         lustre_health_check
344         if [ $? -ne 0 ]; then
345                 return ${OCF_ERR_GENERIC}
346         fi
347
348         lustre_server_mounted
349         rc=$?
350
351         return $rc
352 }
353 # end of lustre_server_status
354
355 #
356 #       Check if Lustre is available at all
357 #
358 lustre_server_validate_all()
359 {
360         proc="/proc/fs/lustre"
361         if [ ! -d $proc ]; then
362                 modprobe lustre
363                 count=0
364                 while [ ! -d $proc -o $count -gt 10 ]; do
365                         sleep 1
366                 done
367
368                 if [ ! -d $proc ];  then
369                         ocf_log err "Failed to load the lustre module"
370                         return $OCF_ERR_GENERIC
371                 fi
372         fi
373
374         return $OCF_SUCCESS
375 }
376
377 # Check the arguments passed to this script
378 if [ $# -ne 1 ]; then
379         usage
380         exit $OCF_ERR_ARGS
381 fi
382
383 # Check the OCF_RESKEY_ environment variables...
384 DEVICE=$OCF_RESKEY_device
385 if [ ! -z "$OCF_RESKEY_options" ]; then
386         options="-o $OCF_RESKEY_options"
387 fi
388
389 OP=$1
390
391 if [ "$OCF_DEBUG" = "yes" ]; then
392         ocf_log info "OP = $OP"
393 fi
394
395 # These operations do not require instance parameters
396 case $OP in
397 meta-data)      meta_data
398                 exit $OCF_SUCCESS
399                 ;;
400 usage)          usage
401                 exit $OCF_SUCCESS
402                 ;;
403 esac
404
405 # Normalize instance parameters:
406
407 # It is possible that OCF_RESKEY_directory has one or even multiple trailing "/".
408 # But the output of `mount` and /proc/mounts do not.
409 if [ -z "$OCF_RESKEY_directory" ]; then
410         ocf_log err "Please specify the directory"
411         exit $OCF_ERR_ARGS
412 else
413         MOUNTPOINT=$(echo $OCF_RESKEY_directory | sed 's/\/*$//')
414         : ${MOUNTPOINT:=/}
415         # At this stage, $MOUNTPOINT does not contain trailing "/" unless it is "/"
416         # TODO: / mounted via lustre_server sounds dangerous. On stop, we'll
417         # kill the whole system. Is that a good idea?
418 fi
419
420 MOUNTPOINT=`echo $MOUNTPOINT | sed -e 's/\s*//'`
421 if [ -z "$MOUNTPOINT" ]; then
422         ocf_log err "Empty mount point!"
423         ocf_log err "Please specify the directory"
424         exit $OCF_ERR_ARGS
425 fi
426
427 # Check to make sure the utilites are found
428 check_binary $MODPROBE
429 check_binary $FSCK
430 check_binary $MOUNT
431 check_binary $UMOUNT
432
433 if [ "$OP" != "monitor" ]; then
434         ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT"
435 fi
436
437 # These operations do not require the clone checking + OCFS2
438 # initialization.
439 case $OP in
440 status|monitor) lustre_server_status
441                 exit $?
442                 ;;
443 validate-all)   lustre_server_validate_all
444                 exit $?
445                 ;;
446 stop)           lustre_server_stop
447                 exit $?
448                 ;;
449 esac
450
451 if [ -n "$OCF_RESKEY_CRM_meta_clone" ]; then
452         ocf_log err "DANGER! $FSTYPE on $DEVICE is NOT cluster-aware!"
453         ocf_log err "DO NOT RUN IT AS A CLONE!"
454         ocf_log err "Politely refusing to proceed to avoid data corruption."
455         exit $OCF_ERR_GENERIC
456 fi
457
458 case $OP in
459 start)  lustre_server_start
460         ;;
461 *)      usage
462         exit $OCF_ERR_UNIMPLEMENTED
463         ;;
464 esac
465 exit $?
466
467
468