home *** CD-ROM | disk | FTP | other *** search
/ ftp.parl.clemson.edu / 2015-02-07.ftp.parl.clemson.edu.tar / ftp.parl.clemson.edu / pub / pvfs2 / orangefs-2.8.3-20110323.tar.gz / orangefs-2.8.3-20110323.tar / orangefs / examples / heartbeat / hardware-specific / Filesystem-qla-monitor < prev    next >
Text File  |  2010-04-30  |  24KB  |  841 lines

  1. #!/bin/sh
  2. #
  3. # Support:      linux-ha@lists.linux-ha.org
  4. # License:      GNU General Public License (GPL)
  5. # Filesystem
  6. #      Description: Manages a Filesystem on a shared storage medium.
  7. #  Original Author: Eric Z. Ayers (eric.ayers@compgen.com)
  8. # Original Release: 25 Oct 2000
  9. #
  10. # Modified to support monitoring of a QLogic adapter, 2007
  11. # Relies on underlying scripts named fs-instance-alarm.pl and
  12. # fs-power-control.pl to take action in the event of monitoring failure
  13. #
  14. # usage: ./Filesystem {start|stop|status|monitor|validate-all|meta-data}
  15. #
  16. #      OCF parameters are as below:
  17. #        OCF_RESKEY_device
  18. #        OCF_RESKEY_directory
  19. #        OCF_RESKEY_fstype
  20. #        OCF_RESKEY_options
  21. #        OCF_RESKEY_fsname
  22. #        OCF_RESKEY_conf_dir
  23. #
  24. #OCF_RESKEY_device    : name of block device for the filesystem. e.g. /dev/sda1, /dev/md0
  25. #            Or a -U or -L option for mount, or an NFS mount specification
  26. #OCF_RESKEY_directory : the mount point for the filesystem
  27. #OCF_RESKEY_fstype    : optional name of the filesystem type. e.g. ext2
  28. #OCF_RESKEY_options   : options to be given to the mount command via -o
  29. #OCF_RESKEY_fsname    : file system name (PVFS2)
  30. #OCF_RESKEY_conf_dir  : file system conf directory (PVFS2)
  31. #
  32. #
  33. # An example usage in /etc/ha.d/haresources: 
  34. #       node1  10.0.0.170 Filesystem::/dev/sda1::/data1::ext2
  35. #  or
  36. #       node1  10.0.0.170 Filesystem::-Ldata1::/data1::ext2
  37. #  or
  38. #       node1  10.0.0.170 Filesystem::server:/data1::/data1::nfs::ro
  39. #
  40. # This assumes you want to manage a filesystem on a shared (scsi) bus.
  41. # Do not put this filesystem in /etc/fstab.  This script manages all of
  42. # that for you.
  43. #
  44. # If you are interested in High Availability, you will probably also want
  45. # some sort of external hardware RAID controller in front of the actual 
  46. # disks.  I don't mean a RAID controller embedded in the host controller -
  47. # it has to be an external controller.
  48. #
  49. # It can also be an internal RAID controller if the controller supports
  50. # failover.  IBM's ServeRAID controller does this, and it automatically
  51. # prohibits concurrent access too, so it's pretty cool in this application.
  52. #
  53. # There is a script for software RAID-1 included in this directory.  Right 
  54. # now, I wouldn't recommend using software RAID (see notes in the Raid1 script)
  55. #
  56. # NOTE: There is no locking (such as a SCSI reservation) being done here.
  57. #       I would if the SCSI driver could properly maintain the reservation,
  58. #       which it cannot, even with the 'scsi reservation' patch submitted
  59. #       earlier this year by James Bottomley.  The patch minimizes the
  60. #       bus resets caused by a RESERVATION_CONFLICT return, and helps the 
  61. #       reservation stay when 2 nodes contend for a reservation, 
  62. #       but it does not attempt to recover the reservation in the 
  63. #       case of a bus reset.  
  64. #
  65. #       What all this means is that if 2 nodes mount the same file system
  66. #       read-write, the filesystem is going to become corrupted.
  67. #
  68. #    As a result, you should use this together with the stonith option
  69. #    and redundant, independent communications paths.
  70. #
  71. #    If you don't do this, don't blame us when you scramble your disk.
  72. #    Note:  the ServeRAID controller does prohibit concurrent acess
  73. #    In this case, you don't actually need STONITH, but redundant comm is
  74. #    still an excellent idea.
  75. #
  76.  
  77. #######################################################################
  78. # Initialization:
  79.  
  80. # newer versions of heartbeat have moved the ocf-shellfuncs  file
  81. if [ -f /usr/lib/ocf/resource.d/heartbeat/.ocf-shellfuncs ] ; then
  82. . /usr/lib/ocf/resource.d/heartbeat/.ocf-shellfuncs
  83. else
  84. . /usr/lib/heartbeat/ocf-shellfuncs
  85. fi
  86.  
  87. #######################################################################
  88.  
  89. # Utilities used by this script
  90. MODPROBE=/sbin/modprobe
  91. FSCK=/sbin/fsck
  92. FUSER=/sbin/fuser
  93. MOUNT=/bin/mount
  94. UMOUNT=/bin/umount
  95. BLOCKDEV=/sbin/blockdev
  96.  
  97. check_util () {
  98.     if [ ! -x "$1" ] ; then
  99.     ocf_log err "Setup problem: Couldn't find utility $1"
  100.     exit $OCF_ERR_GENERIC
  101.     fi
  102. }
  103.  
  104. usage() {
  105.     cat <<-EOT
  106.     usage: $0 {start|stop|status|monitor|validate-all|meta-data}
  107.     EOT
  108. }
  109.  
  110. meta_data() {
  111.     cat <<END
  112. <?xml version="1.0"?>
  113. <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
  114. <resource-agent name="Filesystem">
  115. <version>1.0</version>
  116.  
  117. <longdesc lang="en">
  118. Resource script for Filesystem. It manages a Filesystem on a shared storage medium. 
  119. </longdesc>
  120. <shortdesc lang="en">Filesystem resource agent</shortdesc>
  121.  
  122. <parameters>
  123. <parameter name="device" unique="0" required="1">
  124. <longdesc lang="en">
  125. The name of block device for the filesystem, or -U, -L options for mount, or NFS mount specification.
  126. </longdesc>
  127. <shortdesc lang="en">block device</shortdesc>
  128. <content type="string" default="" />
  129. </parameter>
  130.  
  131. <parameter name="directory" unique="0" required="1">
  132. <longdesc lang="en">
  133. The mount point for the filesystem.
  134. </longdesc>
  135. <shortdesc lang="en">mount point</shortdesc>
  136. <content type="string" default="" />
  137. </parameter>
  138.  
  139. <parameter name="fsname" unique="0" required="1">
  140. <longdesc lang="en">
  141. Name of PVFS2 file system 
  142. </longdesc>
  143. <shortdesc lang="en">File system</shortdesc>
  144. <content type="string" default="" />
  145. </parameter>
  146.  
  147. <parameter name="conf_dir" unique="0" required="1">
  148. <longdesc lang="en">
  149. Path to file system conf directory
  150. </longdesc>
  151. <shortdesc lang="en">File system conf directory</shortdesc>
  152. <content type="string" default="" />
  153. </parameter>
  154.  
  155. <parameter name="fstype" unique="0" required="1">
  156. <longdesc lang="en">
  157. The optional type of filesystem to be mounted.
  158. </longdesc>
  159. <shortdesc lang="en">filesystem type</shortdesc>
  160. <content type="string" default="" />
  161. </parameter>
  162.  
  163. <parameter name="options" unique="0">
  164. <longdesc lang="en">
  165. Any extra options to be given as -o options to mount.
  166. </longdesc>
  167. <shortdesc lang="en">options</shortdesc>
  168. <content type="string" default="" />
  169. </parameter>
  170.  
  171. <parameter name="ocfs2_cluster" unique="0">
  172. <longdesc lang="en">
  173. The name (UUID) of the OCFS2 cluster this filesystem is part of,
  174. iff this is an OCFS2 resource and there's more than one cluster. You
  175. should not need to specify this.
  176. </longdesc>
  177. <shortdesc lang="en">OCFS2 cluster name/UUID</shortdesc>
  178. <content type="string" default="" />
  179. </parameter>
  180.  
  181. <parameter name="ocfs2_configfs" unique="0">
  182. <longdesc lang="en">
  183. Mountpoint of the cluster hierarchy below configfs. You should not
  184. need to specify this.
  185. </longdesc>
  186. <shortdesc lang="en">OCFS2 configfs root</shortdesc>
  187. <content type="string" default="" />
  188. </parameter>
  189. </parameters>
  190.  
  191. <actions>
  192. <action name="start" timeout="60" />
  193. <action name="stop" timeout="60" />
  194. <action name="notify" timeout="60" />
  195. <action name="status" depth="0" timeout="10" interval="10" start-delay="10" />
  196. <action name="monitor" depth="0" timeout="10" interval="10" start-delay="10" />
  197. <action name="validate-all" timeout="5" />
  198. <action name="meta-data" timeout="5" />
  199. </actions>
  200. </resource-agent>
  201. END
  202. }
  203.  
  204. #
  205. #    Make sure the kernel does the right thing with the FS buffers
  206. #    This function should be called after unmounting and before mounting
  207. #    It may not be necessary in 2.4 and later kernels, but it shouldn't hurt
  208. #    anything either...
  209. #
  210. #    It's really a bug that you have to do this at all...
  211. #
  212. flushbufs() {
  213.   if
  214.     [ "$BLOCKDEV" != "" -a -x "$BLOCKDEV" -a "$blockdevice" = "yes" ]
  215.   then
  216.     $BLOCKDEV --flushbufs $1
  217.     return $?
  218.   fi
  219.   
  220.   return 0
  221. }
  222.  
  223. # Take advantage of /proc/mounts if present, use portabel mount command
  224. # otherwise. Normalize format to "dev mountpoint fstype".
  225. list_mounts() {
  226.   if [ -f "/proc/mounts" -a -r "/proc/mounts" ]; then
  227.     cut -d' ' -f1,2,3 </proc/mounts
  228.   else
  229.     $MOUNT | cut -d' ' -f1,3,5
  230.   fi
  231. }
  232.  
  233. determine_blockdevice() {
  234.   if [ $blockdevice == "yes" ]; then
  235.     return
  236.   fi
  237.   
  238.   # Get the current real device name, if possible.
  239.   # (specified devname could be -L or -U...)
  240.   case "$FSTYPE" in
  241.     nfs|smbfs|cifs) ;;
  242.     *)    DEVICE=`list_mounts | grep " $MOUNTPOINT " | cut -d' ' -f1`
  243.         if [ -b "$DEVICE" ]; then
  244.             blockdevice=yes
  245.     fi
  246.     ;;
  247.   esac
  248. }
  249.  
  250. # Lists all filesystems potentially mounted under a given path,
  251. # excluding the path itself.
  252. list_submounts() {
  253.   list_mounts | grep " $1/" | cut -d' ' -f2 | sort -r
  254. }
  255.  
  256. ocfs2_cleanup() {
  257.     # We'll never see the post-stop notification. We're gone now,
  258.     # have unmounted, and thus should remove the membership.
  259.     #
  260.     # (Do so regardless of whether we were unmounted already,
  261.     # because the admin might have manually unmounted but not
  262.     # cleared up the membership directory. Bad admin, no cookie.)
  263.     #
  264.     if [ ! -d "$OCFS2_FS_ROOT" ]; then
  265.         ocf_log info "$OCFS2_FS_ROOT: Filesystem membership already gone."
  266.     else
  267.         ocf_log info "$OCFS2_FS_ROOT: Removing membership directory."
  268.         rm -rf $OCFS2_FS_ROOT/
  269.     fi
  270. }
  271.  
  272. ocfs2_init()
  273. {
  274.     # Check & initialize the OCFS2 specific variables.
  275.     if [ -z "$OCF_RESKEY_CRM_meta_clone_max" ]; then
  276.         ocf_log err "ocfs2 must be run as a clone."
  277.         exit $OCF_ERR_GENERIC
  278.     fi
  279.  
  280.     if [ $blockdevice = "no" ]; then
  281.         ocf_log err "$DEVICE: ocfs2 needs a block device instead."
  282.         exit $OCF_ERR_GENERIC
  283.     fi
  284.     
  285.     for f in "$OCF_RESKEY_ocfs2_configfs" /sys/kernel/config/cluster /configfs/cluster ; do
  286.         if [ -n "$f" -a -d "$f" ]; then
  287.             OCFS2_CONFIGFS="$f"
  288.             break
  289.         fi
  290.     done
  291.     if [ ! -d "$OCFS2_CONFIGFS" ]; then
  292.         ocf_log err "ocfs2 needs configfs mounted."
  293.         exit $OCF_ERR_GENERIC
  294.     fi
  295.  
  296.     OCFS2_UUID=$(mounted.ocfs2 -d $DEVICE|tail -1|awk '{print $3}'|tr -d -- -|tr a-z A-Z)
  297.     if [ -z "$OCFS2_UUID" -o "$OCFS2_UUID" = "UUID" ]; then
  298.         ocf_log err "$DEVICE: Could not determine ocfs2 UUID."
  299.         exit $OCF_ERR_GENERIC
  300.     fi
  301.     
  302.     if [ -n "$OCF_RESKEY_ocfs2_cluster" ]; then
  303.         OCFS2_CLUSTER=$(echo $OCF_RESKEY_ocfs2_cluster | tr a-z A-Z)
  304.     else
  305.         OCFS2_CLUSTER=$(find "$OCFS2_CONFIGFS" -maxdepth 1 -mindepth 1 -type d -printf %f 2>/dev/null)
  306.         set -- $OCFS2_CLUSTER
  307.         local n="$#"
  308.         if [ $n -gt 1 ]; then
  309.             ocf_log err "$OCFS2_CLUSTER: several clusters found."
  310.             exit $OCF_ERR_GENERIC
  311.         fi
  312.         if [ $n -eq 0 ]; then
  313.             ocf_log err "$OCFS2_CONFIGFS: no clusters found."
  314.             exit $OCF_ERR_GENERIC
  315.         fi
  316.     fi
  317.  
  318.     OCFS2_CLUSTER_ROOT="$OCFS2_CONFIGFS/$OCFS2_CLUSTER"
  319.     if [ ! -d "$OCFS2_CLUSTER_ROOT" ]; then
  320.         ocf_log err "$OCFS2_CLUSTER: Cluster doesn't exist. Maybe o2cb hasn't been run?"
  321.         exit $OCF_ERR_GENERIC
  322.     fi
  323.     
  324.     OCFS2_FS_ROOT=$OCFS2_CLUSTER_ROOT/heartbeat/$OCFS2_UUID
  325. }
  326.  
  327. #
  328. # START: Start up the filesystem
  329. #
  330. Filesystem_start()
  331. {
  332.     if [ "$FSTYPE" = "ocfs2" ]; then
  333.         # "start" now has the notification data available; that
  334.         # we're being started means we didn't get the
  335.         # pre-notification, because we weren't running, so
  336.         # process the information now first.
  337.         ocf_log info "$OCFS2_UUID: Faking pre-notification on start."
  338.         OCF_RESKEY_CRM_meta_notify_type="pre"
  339.         OCF_RESKEY_CRM_meta_notify_operation="start"
  340.         Filesystem_notify
  341.     fi        
  342.  
  343.     # See if the device is already mounted.
  344.     if Filesystem_status >/dev/null 2>&1 ; then
  345.         ocf_log info "Filesystem $MOUNTPOINT is already mounted."
  346.         return $OCF_SUCCESS
  347.     fi
  348.  
  349.     # Insert SCSI module
  350.     # TODO: This probably should go away. Why should the filesystem
  351.     # RA magically load a kernel module?
  352.     $MODPROBE scsi_hostadapter >/dev/null 2>&1
  353.  
  354.     if [ -z $FSTYPE ]; then
  355.         : No $FSTYPE specified, rely on the system has the right file-system support already 
  356.     else
  357.         # Insert Filesystem module
  358.         $MODPROBE $FSTYPE >/dev/null 2>&1
  359.         grep -e "$FSTYPE"'$' /proc/filesystems >/dev/null
  360.         if [ $? != 0  ] ; then
  361.         ocf_log err "Couldn't find filesystem $FSTYPE in /proc/filesystems"
  362.         return $OCF_ERR_ARGS
  363.         fi
  364.     fi
  365.  
  366.     # Check the filesystem & auto repair.  
  367.     # NOTE: Some filesystem types don't need this step...  Please modify
  368.     #       accordingly
  369.  
  370.     if [ $blockdevice = "yes" ]; then
  371.     if [ ! -b "$DEVICE" ] ; then
  372.         ocf_log err "Couldn't find device [$DEVICE]. Expected /dev/??? to exist"
  373.         exit $OCF_ERR_ARGS
  374.     fi
  375.  
  376.     if
  377.       case $FSTYPE in
  378.         ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs|cifs|smbfs|ocfs2)    false;;
  379.         *)                true;;
  380.       esac
  381.         then
  382.       ocf_log info  "Starting filesystem check on $DEVICE"
  383.       if [ -z $FSTYPE ]; then
  384.         $FSCK -a $DEVICE
  385.       else
  386.         $FSCK -t $FSTYPE -a $DEVICE
  387.       fi
  388.     
  389.       # NOTE: if any errors at all are detected, it returns non-zero
  390.       # if the error is >= 4 then there is a big problem
  391.       if
  392.         [ $? -ge 4 ]
  393.       then
  394.         ocf_log err "Couldn't sucessfully fsck filesystem for $DEVICE"
  395.         return $OCF_ERR_GENERIC    
  396.       fi    
  397.     fi
  398.     fi
  399.  
  400.     if [ ! -d "$MOUNTPOINT" ] ; then
  401.         ocf_log err "Couldn't find directory  [$MOUNTPOINT] to use as a mount point"
  402.         exit $OCF_ERR_ARGS
  403.     fi
  404.  
  405.     flushbufs $DEVICE
  406.     # Mount the filesystem.
  407.     if [ -z $FSTYPE ]; then
  408.       $MOUNT $options $DEVICE $MOUNTPOINT
  409.     else
  410.       $MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT
  411.         fi
  412.  
  413.         if [ $? -ne 0 ]; then
  414.       ocf_log err "Couldn't mount filesystem $DEVICE on $MOUNTPOINT"
  415.       if [ "$FSTYPE" = "ocfs2" ]; then
  416.           ocfs2_cleanup
  417.       fi
  418.       return $OCF_ERR_GENERIC
  419.     fi
  420.  
  421.     return 0
  422. }
  423. # end of Filesystem_start
  424.  
  425. Filesystem_notify() {
  426.     # Process notifications; this is the essential glue level for
  427.     # giving user-space membership events to a cluster-aware
  428.     # filesystem. Right now, only OCFS2 is supported.
  429.     #
  430.     # When we get a pre-start notification, we set up all the nodes
  431.     # which will be active in our membership for the filesystem.
  432.     # (For the resource to be started, this happens at the time of
  433.     # the actual 'start' operation.)
  434.     #
  435.     # At a post-start, actually there's nothing to do for us really,
  436.     # but no harm done in re-syncing either.
  437.     #
  438.     # pre-stop is meaningless; we can't remove any node yet, it
  439.     # first needs to unmount.
  440.     #
  441.     # post-stop: the node is removed from the membership of the
  442.     # other nodes.
  443.     # 
  444.     # Note that this expects that the base cluster is already
  445.     # active; ie o2cb has been started and populated
  446.     # $OCFS2_CLUSTER_ROOT/node/ already. This can be achieved by
  447.     # simply having o2cb run on all nodes by the CRM too.  This
  448.     # probably ought to be mentioned somewhere in the to be written
  449.     # documentation. ;-)
  450.     #
  451.  
  452.     if [ "$FSTYPE" != "ocfs2" ]; then
  453.         # One of the cases which shouldn't occur; it should have
  454.         # been caught much earlier. Still, you know ...
  455.         ocf_log err "$DEVICE: Notification received for non-ocfs2 mount."
  456.         return $OCF_ERR_GENERIC
  457.     fi
  458.  
  459.     local n_type="$OCF_RESKEY_CRM_meta_notify_type"
  460.     local n_op="$OCF_RESKEY_CRM_meta_notify_operation"
  461.     local n_active="$OCF_RESKEY_CRM_meta_notify_active_uname"
  462.     local n_stop="$OCF_RESKEY_CRM_meta_notify_stop_uname"
  463.     local n_start="$OCF_RESKEY_CRM_meta_notify_start_uname"
  464.  
  465.     ocf_log info "$OCFS2_UUID: notify: $n_type for $n_op"
  466.     ocf_log info "$OCFS2_UUID: notify active: $n_active"
  467.     ocf_log info "$OCFS2_UUID: notify stop: $n_stop"
  468.     ocf_log info "$OCFS2_UUID: notify start: $n_start"
  469.  
  470.     case "$n_type" in
  471.     pre)
  472.         case "$n_op" in
  473.         stop)
  474.             ocf_log info "$OCFS2_UUID: ignoring pre-notify for stop."
  475.             return $infoUCCESS
  476.             ;;
  477.         start)
  478.             # These are about to become active; prepare to
  479.             # communicate with them.
  480.             n_active="$n_active $n_start"
  481.             ;;
  482.         esac
  483.         ;;
  484.     post)
  485.         case "$n_op" in
  486.         stop)
  487.             # remove unames from notify_stop_uname; these have been
  488.             # stopped and can no longer be considered active.
  489.             for UNAME in "$n_stop"; do
  490.                 n_active="${n_active//$UNAME/}"
  491.             done
  492.             ;;
  493.         start)
  494.             if [ "$n_op" = "start" ]; then
  495.                 ocf_log info "$OCFS2_UUID: ignoring post-notify for start."
  496.                 return $OCF_SUCCESS
  497.             fi
  498.             ;;
  499.         esac
  500.         ;;
  501.     esac
  502.     
  503.     ocf_log info "$OCFS2_UUID: post-processed active: $n_active"
  504.  
  505.     local n_myself=${HA_CURHOST:-$(uname -n | tr A-Z a-z)}
  506.     ocf_log info "$OCFS2_UUID: I am node $n_myself."
  507.  
  508.     case " $n_active " in
  509.     *" $n_myself "*) ;;
  510.     *)    ocf_log err "$OCFS2_UUID: $n_myself (local) not on active list!"
  511.         return $OCF_ERR_GENERIC
  512.         ;;
  513.     esac
  514.  
  515.     if [ -d "$OCFS2_FS_ROOT" ]; then
  516.     entry_prefix=$OCFS2_FS_ROOT/
  517.     for entry in $OCFS2_FS_ROOT/* ; do
  518.         n_fs="${entry##$entry_prefix}"
  519. #        ocf_log info "$OCFS2_UUID: Found current node $n_fs"
  520.         case " $n_active " in
  521.         *" $n_fs "*)
  522.             # Construct a list of nodes which are present
  523.             # already in the membership.
  524.             n_exists="$n_exists $n_fs"
  525.             ocf_log info "$OCFS2_UUID: Keeping node: $n_fs"
  526.             ;;
  527.         *)
  528.             # Node is in the membership currently, but not on our 
  529.             # active list. Must be removed.
  530.             if [ "$n_op" = "start" ]; then
  531.                 ocf_log warn "$OCFS2_UUID: Removing nodes on start"
  532.             fi
  533.             ocf_log info "$OCFS2_UUID: Removing dead node: $n_fs"
  534.             if ! rm -f $entry ; then
  535.                 ocf_log err "$OCFS2_UUID: Removal of $n_fs failed!"
  536.             fi
  537.             ;;
  538.         esac
  539.     done
  540.     else
  541.         ocf_log info "$OCFS2_UUID: heartbeat directory doesn't exist yet, creating."
  542.         mkdir -p $OCFS2_FS_ROOT
  543.     fi
  544.  
  545.     ocf_log info "$OCFS2_UUID: Existing node list: $n_exists"
  546.     
  547.     # (2)
  548.     for entry in $n_active ; do
  549. #        ocf_log info "$OCFS2_UUID: Expected active node: $entry"
  550.         case " $n_exists " in
  551.         *" $entry "*)
  552.             ocf_log info "$OCFS2_UUID: Already active: $entry"
  553.             ;;
  554.         *)
  555.             if [ "$n_op" = "stop" ]; then
  556.                 ocf_log warn "$OCFS2_UUID: Adding nodes on stop"
  557.             fi
  558.             ocf_log info "$OCFS2_UUID: Activating node: $entry"
  559.             if ! ln -s $OCFS2_CLUSTER_ROOT/node/$entry $OCFS2_FS_ROOT/$entry ; then
  560.                 ocf_log err "$OCFS2_CLUSTER_ROOT/node/$entry: failed to link"
  561.             fi
  562.             ;;
  563.         esac
  564.     done
  565. }
  566.  
  567. #
  568. # STOP: Unmount the filesystem
  569. #
  570. Filesystem_stop()
  571. {
  572.   # See if the device is currently mounted
  573.   Filesystem_status >/dev/null 2>&1
  574.   if [ $? -ne $OCF_NOT_RUNNING ]; then
  575.     # Determine the real blockdevice this is mounted on (if
  576.     # possible) prior to unmounting.
  577.     determine_blockdevice
  578.     
  579.     # For networked filesystems, there's merit in trying -f:
  580.     case "$FSTYPE" in
  581.       nfs|cifs|smbfs) umount_force="-f" ;;
  582.     esac
  583.     
  584.     # Umount all sub-filesystems mounted under $MOUNTPOINT/ too.
  585.     for SUB in `list_submounts $MOUNTPOINT` $MOUNTPOINT; do
  586.       ocf_log info "Trying to unmount $MOUNTPOINT"
  587.       for sig in SIGTERM SIGTERM SIGTERM SIGKILL SIGKILL SIGKILL; do
  588.           if $UMOUNT $umount_force $SUB ; then
  589.           rc=$OCF_SUCCESS
  590.             ocf_log info "unmounted $SUB successfully"
  591.       break
  592.           else
  593.           rc=$OCF_ERR_GENERIC
  594.           ocf_log err "Couldn't unmount $SUB; trying cleanup with $sig"
  595.           # fuser returns a non-zero return code if none of the
  596.           # specified files is accessed or in case of a fatal 
  597.           # error.
  598.           if $FUSER -$sig -m -k $SUB ; then
  599.         ocf_log info "Some processes on $SUB were signalled"
  600.       else
  601.         ocf_log info "No processes on $SUB were signalled"
  602.           fi
  603.           sleep 1
  604.           fi
  605.       done
  606.       
  607.       if [ $rc -ne $OCF_SUCCESS ]; then
  608.           ocf_log err "Couldn't unmount $SUB, giving up!"
  609.       fi
  610.     done
  611.   else
  612.     # Already unmounted, wonderful.
  613.     rc=$OCF_SUCCESS
  614.   fi
  615.   
  616.   flushbufs $DEVICE
  617.   
  618.   if [ "$FSTYPE" = "ocfs2" ]; then
  619.     ocfs2_cleanup
  620.   fi
  621.   
  622.   return $rc
  623. }
  624. # end of Filesystem_stop
  625.  
  626. #
  627. # STATUS: is the file system mounted and the SAN path alive?
  628. #
  629. Filesystem_status_qla_monitor()
  630. {
  631.   Filesystem_status >/dev/null 2>&1
  632.   ORIG_RET=$?
  633.   if [ $ORIG_RET -eq $OCF_SUCCESS ]; then
  634.     # the fs is mounted.  Are the paths ok?
  635.     /usr/bin/qla-monitor.pl --device $DEVICE
  636.     if [ $? -ne 0 ]; then
  637.       # log as much as we can
  638.       ocf_log info "Error: $DEVICE is dead."
  639.       echo "Error: $DEVICE is dead on node `hostname`, failing over" >> /var/log/pvfs2/pvfs2-failover.log;
  640.       /usr/bin/fs-instance-alarm.pl --fs-name $fsname --ce `hostname` --type PVFS2_HA --msg "$DEVICE is dead, failing over."
  641.       /usr/bin/fs-power-control.pl --fs-name $fsname --conf-dir $conf_dir --host `hostname` --command reboot
  642.       # shoot ourselves in the head
  643.       return $OCF_ERR_GENERIC
  644.     fi
  645.     dd bs=4096 count=1 if=/dev/zero oflag=direct of=${MOUNTPOINT}/filesystem.monitor
  646.     if [ $? -ne 0 ]; then
  647.       ocf_log err "Error: Unable to write to $DEVICE on node `hostname`."
  648.       /usr/bin/logger -p user.err -t PVFS2 "Error: Unable to write to $DEVICE on node `hostname`, failing over."
  649.       /usr/bin/fs-instance-alarm.pl --fs-name $fsname --ce `hostname` --type PVFS2_HA --msg "Error: Unable to write to $DEVICE on node `hostname`, failing over."
  650.       # shoot ourselves in the head
  651.       /usr/bin/fs-power-control.pl --fs-name $fsname --conf-dir $conf_dir --host `hostname` --command reboot
  652.       return $OCF_ERR_GENERIC
  653.     fi
  654.   fi
  655.   return $ORIG_RET
  656. }
  657. # end of Filesystem_status_qla_monitor
  658.  
  659. #
  660. # STATUS: is the filesystem mounted or not?
  661. #
  662. Filesystem_status()
  663. {
  664.     if
  665.       list_mounts | grep -q " $MOUNTPOINT " >/dev/null 2>&1
  666.         then
  667.           rc=$OCF_SUCCESS
  668.           msg="$MOUNTPOINT is mounted (running)"
  669.         else
  670.           rc=$OCF_NOT_RUNNING
  671.           msg="$MOUNTPOINT is unmounted (stopped)"
  672.         fi
  673.  
  674.     # TODO: For ocfs2, or other cluster filesystems, should we be
  675.     # checking connectivity to other nodes here, or the IO path to
  676.     # the storage?
  677.     
  678.         case "$OP" in
  679.       status)    ocf_log info "$msg";;
  680.     esac
  681.         return $rc
  682. }
  683. # end of Filesystem_status
  684.  
  685. #
  686. # VALIDATE_ALL: Are the instance parameters valid?
  687. #    FIXME!!  The only part that's useful is the return code.
  688. #    This code always returns $OCF_SUCCESS (!)
  689. #
  690. Filesystem_validate_all()
  691. {
  692.     if [ -n $MOUNTPOINT -a ! -d $MOUNTPOINT ]; then
  693.         ocf_log warn "Mountpoint $MOUNTPOINT does not exist"
  694.     fi
  695.  
  696. # Check if the $FSTYPE is workable
  697. # NOTE: Without inserting the $FSTYPE module, this step may be imprecise
  698. # TODO: This is Linux specific crap.
  699.     if [ ! -z $FSTYPE ]; then
  700.         cut -f2 /proc/filesystems |grep -q ^$FSTYPE$
  701.         if [ $? -ne 0 ]; then
  702.         modpath=/lib/modules/`uname -r` 
  703.         moddep=$modpath/modules.dep
  704.         # Do we have $FSTYPE in modules.dep?
  705.         cut -d' ' -f1 $moddep |grep -q "^$modpath.*$FSTYPE\.k\?o:$"
  706.         if [ $? -ne 0 ]; then
  707.             ocf_log info "It seems we do not have $FSTYPE support"
  708.         fi
  709.         fi
  710.     fi
  711.  
  712. #TODO: How to check the $options ?
  713.  
  714.     return $OCF_SUCCESS
  715. }
  716.  
  717. # Check the arguments passed to this script
  718. if
  719.   [ $# -ne 1 ]
  720. then
  721.   usage
  722.   exit $OCF_ERR_ARGS
  723. fi
  724.  
  725. OP=$1
  726.  
  727. # These operations do not require instance parameters
  728. case $OP in
  729.   meta-data)        meta_data
  730.             exit $OCF_SUCCESS
  731.             ;;
  732.   usage)        usage
  733.             exit $OCF_SUCCESS
  734.             ;;
  735. esac
  736.  
  737. if 
  738.   [ -z "$OCF_RESKEY_fsname" ]
  739. then
  740.   ocf_log err "Filesystem-qla-monitor must specify fsname!"
  741. #  usage
  742.   exit $OCF_ERR_GENERIC
  743. fi
  744.  
  745. if 
  746.   [ -z "$OCF_RESKEY_conf_dir" ]
  747. then
  748.   ocf_log err "Filesystem-qla-monitor must specify conf_dir!"
  749. #  usage
  750.   exit $OCF_ERR_GENERIC
  751. fi
  752.  
  753. # Check the OCF_RESKEY_ environment variables...
  754. DEVICE=$OCF_RESKEY_device
  755. FSTYPE=$OCF_RESKEY_fstype
  756. if [ ! -z "$OCF_RESKEY_options" ]; then
  757.     options="-o $OCF_RESKEY_options"
  758. fi
  759. fsname=$OCF_RESKEY_fsname
  760. conf_dir=$OCF_RESKEY_conf_dir
  761.  
  762. blockdevice=no
  763. case $DEVICE in
  764.   "")    ocf_log err "Please set OCF_RESKEY_device to the device to be managed"
  765.     exit $OCF_ERR_ARGS
  766.     ;;
  767.   -*) # Oh... An option to mount instead...  Typically -U or -L
  768.     ;;
  769.   [^/]*:/*)    # An NFS filesystem specification...
  770.     ;;
  771.   //[^/]*/*)    # An SMB filesystem specification...
  772.     ;;
  773.   *)    if [ ! -b "$DEVICE"  -a "X$OP" != Xstart ] ; then
  774.       ocf_log warn "Couldn't find device [$DEVICE]. Expected /dev/??? to exist"
  775.     fi
  776.     blockdevice=yes
  777.     ;;
  778. esac
  779.  
  780. case $FSTYPE in
  781.   ocfs2)
  782.     ocfs2_init
  783.   ;;
  784.   nfs)
  785.     : # this is kind of safe too
  786.   ;;
  787.   *) 
  788.     if [ -n "$OCF_RESKEY_CRM_meta_clone_max" ]; then
  789.         ocf_log err "DANGER! $FSTYPE on $DEVICE is NOT cluster-aware!"
  790.         ocf_log err "DO NOT RUN IT AS A CLONE!"
  791.         ocf_log err "Politely refusing to proceed to avoid data corruption."
  792.         exit $OCF_ERR_GENERIC    
  793.     fi
  794.   ;;
  795. esac
  796.  
  797. # It is possible that OCF_RESKEY_directory has one or even multiple trailing "/".
  798. # But the output of `mount` and /proc/mounts do not.
  799. if [ -z $OCF_RESKEY_directory ]; then
  800.     if [ X$OP = "Xstart" -o $blockdevice = "no" ]; then
  801.     ocf_log err "Please specify the directory"
  802.     exit $OCF_ERR_ARGS 
  803.     fi
  804. else
  805.     MOUNTPOINT=$(echo $OCF_RESKEY_directory | sed 's/\/*$//')
  806.     : ${MOUNTPOINT:=/}
  807.     # At this stage, $MOUNTPOINT does not contain trailing "/" unless it is "/"
  808.     # TODO: / mounted via Filesystem sounds dangerous. On stop, we'll
  809.     # kill the whole system. Is that a good idea?
  810. fi
  811.     
  812. # Check to make sure the utilites are found
  813. check_util $MODPROBE
  814. check_util $FSCK
  815. check_util $FUSER
  816. check_util $MOUNT
  817. check_util $UMOUNT
  818.  
  819. if [ "$OP" != "monitor" ]; then
  820.     ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT"
  821. fi
  822.  
  823. case $OP in
  824.   start)        Filesystem_start
  825.             ;;
  826.   notify)        Filesystem_notify
  827.             ;;
  828.   stop)            Filesystem_stop
  829.             ;;
  830.   status|monitor)    Filesystem_status_qla_monitor
  831.             ;;
  832.   validate-all)        Filesystem_validate_all
  833.             ;;
  834.   *)            usage
  835.             exit $OCF_ERR_UNIMPLEMENTED
  836.             ;;
  837. esac
  838. exit $?
  839.