3 # License: GNU General Public License (GPL)
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
10 # Rewritten Filesystem agent to lustre_server agent by bschubert@ddn.com
12 # usage: ./lustre_server {start|stop|status|monitor|validate-all|meta-data}
14 # OCF parameters are as below:
16 # OCF_RESKEY_directory
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
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.
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).
38 # As a result, you should use this together with the stonith option
39 # and redundant, independent communications paths.
41 # If you don't do this, don't blame us when you scramble your disk.
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.
48 #######################################################################
51 . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
53 #######################################################################
57 # FIXME: OCF_DEBUG officially supported in the the mean time?
62 usage: $0 {start|stop|status|monitor|validate-all|meta-data}
69 <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
70 <resource-agent name="lustre_server">
71 <version>1.0</version>
75 Resource script for lustre_server. It manages a lustre_server on a shared storage medium.
77 <shortdesc lang="en">lustre_server resource agent</shortdesc>
80 <parameter name="device" required="1">
82 The name of block device for the filesystem
84 <shortdesc lang="en">block device</shortdesc>
85 <content type="string" default="" />
88 <parameter name="directory" required="1">
90 The mount point for the filesystem.
92 <shortdesc lang="en">mount point</shortdesc>
93 <content type="string" default="" />
96 <parameter name="options">
98 Any extra options to be given as -o options to mount.
100 <shortdesc lang="en">options</shortdesc>
101 <content type="string" default="" />
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" />
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
122 # It's really a bug that you have to do this at all...
125 if have_binary $BLOCKDEV ; then
126 $BLOCKDEV --flushbufs $1
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
138 get_external_journal_device()
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
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}'`"
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
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
164 # add 0x only here, because we couldn't check for an empty string otherwise
171 # Take advantage of /proc/mounts if present, use portable mount command
172 # otherwise. Normalize format to "dev mountpoint fstype".
175 if [ ! -f $mtab ]; then
176 ocf_log err "$mtab is missing!"
177 exit $OCF_ERR_GENERIC
179 cat $mtab | cut -d' ' -f1,2,3
182 lustre_health_check()
184 check=$(lctl get_param -n health_check 2>&1)
185 # on first check the lustre modules are not loaded yet
190 if [ "$check" = "healthy" ]; then
193 ocf_log err "health_check is $check"
199 # START: Start up the filesystem
201 lustre_server_start()
204 if [ $? -ne 0 ]; then
205 return ${OCF_ERR_GENERIC}
208 # See if the device is currently mounted
209 lustre_server_status >/dev/null 2>&1
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
217 if [ ! -d "$MOUNTPOINT" ] ; then
218 ocf_log err "Couldn't find directory [$MOUNTPOINT] to use as a mount point"
224 jdev=`get_external_journal_device`
226 if [ $rc -ne 0 ]; then
227 ocf_log err "Failure to get journal device"
231 if [ -n "$jdev" ]; then
232 if [ -n "$options" ]; then
233 options="$options,journal_dev=$jdev"
235 options="-ojournal_dev=$jdev"
239 # Mount the filesystem.
240 cmd="$MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT"
241 ocf_log info "Running $cmd"
243 if [ $? -ne 0 ]; then
244 ocf_log err "cmd \"$cmd\" failed: $res"
245 return $OCF_ERR_GENERIC
250 # end of lustre_server_start
253 # STOP: Unmount the filesystem
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.
263 # Umount $MOUNTPOINT.
264 ocf_log info "Trying to unmount $MOUNTPOINT"
265 cmd="$UMOUNT $MOUNTPOINT"
266 ocf_log info "Running $cmd"
269 if [ $rc -eq 0 ] ; then
271 ocf_log info "unmounted $MOUNTPOINT successfully"
274 ocf_log err "\"$cmd\" failed ($rc): $res"
282 # end of lustre_server_stop
285 # MOUNTED: is the filesystem mounted or not?
287 lustre_server_mounted()
289 if list_mounts | grep -q " $MOUNTPOINT " >/dev/null 2>&1; then
291 msg="$MOUNTPOINT is mounted (running)"
294 msg="$MOUNTPOINT is unmounted (stopped)"
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)
304 dev=$(lctl get_param -n obdfilter.*.mntdev 2>&1)
306 MNTDEVS="$MNTDEVS $dev"
308 dev=$(lctl get_param -n mgs.MGS.mntdev 2>&1)
310 MNTDEVS="$MNTDEVS $dev"
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"
321 if [ "$OCF_DEBUG" = "yes" ]; then
326 status) ocf_log info "$msg"
329 if [ $rc -ne $OCF_SUCCESS ]; then
336 # end of lustre_server_mounted
339 # STATUS: is the filesystem mounted and healthy or not?
341 lustre_server_status()
344 if [ $? -ne 0 ]; then
345 return ${OCF_ERR_GENERIC}
348 lustre_server_mounted
353 # end of lustre_server_status
356 # Check if Lustre is available at all
358 lustre_server_validate_all()
360 var=$(lctl get_param -n version 2>&1)
364 for i in `seq 1 10`; do
365 var=$(lctl get_param -n version 2>&1)
373 var=$(lctl get_param -n version 2>&1)
375 ocf_log err "Failed to load the lustre module"
376 return $OCF_ERR_GENERIC
383 # Check the arguments passed to this script
384 if [ $# -ne 1 ]; then
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"
397 if [ "$OCF_DEBUG" = "yes" ]; then
398 ocf_log info "OP = $OP"
401 # These operations do not require instance parameters
411 # Normalize instance parameters:
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"
419 MOUNTPOINT=$(echo $OCF_RESKEY_directory | sed 's/\/*$//')
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?
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"
433 # Check to make sure the utilites are found
434 check_binary $MODPROBE
439 if [ "$OP" != "monitor" ]; then
440 ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT"
443 # These operations do not require the clone checking + OCFS2
446 status|monitor) lustre_server_status
449 validate-all) lustre_server_validate_all
452 stop) lustre_server_stop
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
465 start) lustre_server_start
468 exit $OCF_ERR_UNIMPLEMENTED