Whamcloud - gitweb
LU-5458: libcfs: protect kkuc_groups from write access
[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         check=$(lctl get_param -n health_check 2>&1)
185         # on first check the lustre modules are not loaded yet
186         if [ $? != 0 ]; then
187                 return 0
188         fi
189
190         if [ "$check" = "healthy" ]; then
191                 return 0
192         else
193                 ocf_log err "health_check is $check"
194                 return 1
195         fi
196 }
197
198 #
199 # START: Start up the filesystem
200 #
201 lustre_server_start()
202 {
203         lustre_health_check
204         if [ $? -ne 0 ]; then
205                 return ${OCF_ERR_GENERIC}
206         fi
207
208         # See if the device is currently mounted
209         lustre_server_status >/dev/null 2>&1
210         rc=$?
211         if [ $rc -ne $OCF_NOT_RUNNING -a $rc -ne $OCF_SUCCESS ]; then
212                 ocf_log err "Unexpected status ($c) before mounting $DEVICE to $MOUNTPOINT"
213         elif [ $rc -eq $OCF_SUCCESS ]; then
214                 return $OCF_SUCCESS
215         fi
216
217         if [ ! -d "$MOUNTPOINT" ] ; then
218                 ocf_log err "Couldn't find directory  [$MOUNTPOINT] to use as a mount point"
219                 exit $OCF_ERR_ARGS
220         fi
221
222         flushbufs $DEVICE
223
224         jdev=`get_external_journal_device`
225         rc=$?
226         if [ $rc -ne 0 ]; then
227                 ocf_log err "Failure to get journal device"
228                 return $rc
229         fi
230
231         if [ -n "$jdev" ]; then
232                 if [ -n "$options" ]; then
233                         options="$options,journal_dev=$jdev"
234                 else
235                         options="-ojournal_dev=$jdev"
236                 fi
237         fi
238
239         # Mount the filesystem.
240         cmd="$MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT"
241         ocf_log info "Running $cmd"
242         res=`eval $cmd 2>&1`
243         if [ $? -ne 0 ]; then
244                 ocf_log err "cmd \"$cmd\" failed: $res"
245                 return $OCF_ERR_GENERIC
246         fi
247
248         return 0
249 }
250 # end of lustre_server_start
251
252 #
253 # STOP: Unmount the filesystem
254 #
255 lustre_server_stop()
256 {
257         # See if the device is currently mounted
258         lustre_server_mounted >/dev/null 2>&1
259         if [ $? -eq $OCF_NOT_RUNNING ]; then
260                 # Already unmounted, wonderful.
261                 rc=$OCF_SUCCESS
262         else
263                 # Umount $MOUNTPOINT.
264                 ocf_log info "Trying to unmount $MOUNTPOINT"
265                 cmd="$UMOUNT $MOUNTPOINT"
266                 ocf_log info "Running $cmd"
267                 res=`eval $cmd 2>&1`
268                 rc=$?
269                 if [ $rc -eq 0 ] ; then
270                         rc=$OCF_SUCCESS
271                         ocf_log info "unmounted $MOUNTPOINT successfully"
272                 else
273                         rc=$OCF_ERR_GENERIC
274                         ocf_log err "\"$cmd\" failed ($rc): $res"
275                 fi
276         fi
277
278         flushbufs $DEVICE
279
280         return $rc
281 }
282 # end of lustre_server_stop
283
284 #
285 # MOUNTED: is the filesystem mounted or not?
286 #
287 lustre_server_mounted()
288 {
289         if list_mounts | grep -q " $MOUNTPOINT " >/dev/null 2>&1; then
290                 rc=$OCF_SUCCESS
291                 msg="$MOUNTPOINT is mounted (running)"
292         else
293                 rc=$OCF_NOT_RUNNING
294                 msg="$MOUNTPOINT is unmounted (stopped)"
295         fi
296
297         # check in all mntdevs if really not mounted
298         # lustre bug 21359 (https://bugzilla.lustre.org/show_bug.cgi?id=21359)
299         if [ $rc -eq $OCF_NOT_RUNNING ]; then
300                 dev=$(lctl get_param -n mds.*.mntdev 2>&1)
301                 if [ $? = 0 ]; then
302                         MNTDEVS=$dev
303                 fi
304                 dev=$(lctl get_param -n obdfilter.*.mntdev 2>&1)
305                 if [ $? = 0 ]; then
306                         MNTDEVS="$MNTDEVS $dev"
307                 fi
308                 dev=$(lctl get_param -n mgs.MGS.mntdev 2>&1)
309                 if [ $? = 0 ]; then
310                         MNTDEVS="$MNTDEVS $dev"
311                 fi
312                 for i in $MNTDEVS; do
313                         if [ "$i" = "$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         var=$(lctl get_param -n version 2>&1)
361         if [ $? != 0 ]; then
362                 modprobe lustre
363
364                 for i in `seq 1 10`; do
365                         var=$(lctl get_param -n version 2>&1)
366                         if [ $? != 0 ]; then
367                                 sleep 1
368                         else
369                                 break
370                         fi
371                 done
372
373                 var=$(lctl get_param -n version 2>&1)
374                 if [ $? != 0 ]; then
375                         ocf_log err "Failed to load the lustre module"
376                         return $OCF_ERR_GENERIC
377                 fi
378         fi
379
380         return $OCF_SUCCESS
381 }
382
383 # Check the arguments passed to this script
384 if [ $# -ne 1 ]; then
385         usage
386         exit $OCF_ERR_ARGS
387 fi
388
389 # Check the OCF_RESKEY_ environment variables...
390 DEVICE=$OCF_RESKEY_device
391 if [ ! -z "$OCF_RESKEY_options" ]; then
392         options="-o $OCF_RESKEY_options"
393 fi
394
395 OP=$1
396
397 if [ "$OCF_DEBUG" = "yes" ]; then
398         ocf_log info "OP = $OP"
399 fi
400
401 # These operations do not require instance parameters
402 case $OP in
403 meta-data)      meta_data
404                 exit $OCF_SUCCESS
405                 ;;
406 usage)          usage
407                 exit $OCF_SUCCESS
408                 ;;
409 esac
410
411 # Normalize instance parameters:
412
413 # It is possible that OCF_RESKEY_directory has one or even multiple trailing "/".
414 # But the output of `mount` and /proc/mounts do not.
415 if [ -z "$OCF_RESKEY_directory" ]; then
416         ocf_log err "Please specify the directory"
417         exit $OCF_ERR_ARGS
418 else
419         MOUNTPOINT=$(echo $OCF_RESKEY_directory | sed 's/\/*$//')
420         : ${MOUNTPOINT:=/}
421         # At this stage, $MOUNTPOINT does not contain trailing "/" unless it is "/"
422         # TODO: / mounted via lustre_server sounds dangerous. On stop, we'll
423         # kill the whole system. Is that a good idea?
424 fi
425
426 MOUNTPOINT=`echo $MOUNTPOINT | sed -e 's/\s*//'`
427 if [ -z "$MOUNTPOINT" ]; then
428         ocf_log err "Empty mount point!"
429         ocf_log err "Please specify the directory"
430         exit $OCF_ERR_ARGS
431 fi
432
433 # Check to make sure the utilites are found
434 check_binary $MODPROBE
435 check_binary $FSCK
436 check_binary $MOUNT
437 check_binary $UMOUNT
438
439 if [ "$OP" != "monitor" ]; then
440         ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT"
441 fi
442
443 # These operations do not require the clone checking + OCFS2
444 # initialization.
445 case $OP in
446 status|monitor) lustre_server_status
447                 exit $?
448                 ;;
449 validate-all)   lustre_server_validate_all
450                 exit $?
451                 ;;
452 stop)           lustre_server_stop
453                 exit $?
454                 ;;
455 esac
456
457 if [ -n "$OCF_RESKEY_CRM_meta_clone" ]; then
458         ocf_log err "DANGER! $FSTYPE on $DEVICE is NOT cluster-aware!"
459         ocf_log err "DO NOT RUN IT AS A CLONE!"
460         ocf_log err "Politely refusing to proceed to avoid data corruption."
461         exit $OCF_ERR_GENERIC
462 fi
463
464 case $OP in
465 start)  lustre_server_start
466         ;;
467 *)      usage
468         exit $OCF_ERR_UNIMPLEMENTED
469         ;;
470 esac
471 exit $?
472
473
474