#!/bin/bash

# Builds a list of filesystems which should be mounted and compares
# it against what the kernel thinks is mounted.
#
# Original code by Michael Groves - michael.r.groves@census.gov
#
# 2018-Aug-28 - Revised by Bert Quattro - robert.s.quattro@census.gov
#  v2.0  - Add support for GPFS, PCS HA & PCS GFS2. Ignore sys/kernel mounts.
#  v2.1  - Add support for bind mounts defined in /etc/fstab
# 2019-Apr-02
#  v2.2  - Add support for GPFS fail at boot time & CIFS

# Variables

CIBXML=/var/lib/pacemaker/cib/cib.xml
CLCNF=/etc/cluster/cluster.conf
MDIFF=/tmp/mount.diff
VFS1=/tmp/vfstab.txt
VFS2=/tmp/vfstab2.txt
VMT1=/tmp/vmount.txt
VMT2=/tmp/vmount2.txt

############################################################
# Code

# Add filesytems from /etc/fstab and compare to mount output
# Exclude pipefs, selinuxfs, configfs, sys/kernel
# Include ext[234], gfs, xfs, nfs, gpfs and bind
# If they match, exit successfully

vFSTAB=`cat /etc/fstab | grep -v '^#\|rpc_pipefs' \
| grep 'ext[234]\|gfs\|xfs\|nfs\|gpfs\|bind\|cifs' \
| awk '{ print $2 }' | sort -u`
cat /etc/fstab | grep -v '^#\|rpc_pipefs' \
| grep 'ext[234]\|gfs\|xfs\|nfs\|gpfs\|bind\|cifs' \
| awk '{ print $2 }' | sort -u > $VFS1
vMOUNT=`/bin/mount | grep -v 'pipefs\|^none\|^nfsd\ ' \
| grep 'ext[234]\|gfs\|xfs\|nfs\|gpfs\|cifs' |egrep -v "selinux|sys/kernel" \
| awk '{print $3}' | sort -u`
/bin/mount | grep -v 'pipefs\|^none\|^nfsd\ ' \
| grep 'ext[234]\|gfs\|xfs\|nfs\|gpfs\|cifs' \
|egrep -v "selinux|sys/kernel" \
| awk '{print $3}' | sort -u > $VMT1

if [ "$vFSTAB" == "$vMOUNT" ]; then exit 0; fi

# Check for failed GPFS mounts

if [ -x /usr/lpp/mmfs/bin/mmlsmount ] ;
    then
    mmLS=`mmlsmount all |awk '{print $3}' |sort -u`
    mmMOUNT=`for mnt in $mmLS ; do mount |grep $mnt |awk '{print $1}' ; done`
 if ! [ "$mmLS" == "$mmMOUNT" ]; then exit 1; fi
fi

# Add RHEL 5/6 (CCS) GFS2 filesystems to list, if present
# Checks cluster.conf for configured fs devices that should be mounted

if [ -e /usr/sbin/clustat ] ;
    then
    /usr/bin/comm -13 $VFS1 $VMT1 > $MDIFF
    for I in `cat $MDIFF` ; do

     cat $CLCNF | sed -n "/resources/,/\/resources/p" \
     | grep "<fs device" | grep "mountpoint=" |tr ' ' '\n' |grep mountpoint \
     | awk -F\" '{print $2}' |sed 's:/$::' |grep $I >> $VFS1

    done

fi

# Add RHEL 7 high availability, if present
# Checks for started heartbeat filesystems - no action taken if server
# is currently the secondary, or otherwise has none. Add filesystems
# to list if primary.

if [ -x /sbin/pcs ] ;
    then
    pcs status |grep ocf::heartbeat:Filesystem |grep "Started `hostname`" \
    | awk '{print $1}' > /tmp/pcs1.txt

    for K in `cat /tmp/pcs1.txt` ; do
	grep $K-instance_attributes-directory $CIBXML \
	|awk -F\" '{print $6}' >> $VFS1
    done

fi

# Add RHEL 7 GFS2 clustered filesystems
# Checks for configured Clone Sets and if found, adds expected GFS2
# mounts from cib.xml to list

if [ -x /sbin/pcs ] ;
    then
    if [ $(pcs status |grep "Clone Set" |wc -l) -gt "0" ]  ;
	then 
	grep "name=\"directory\"" $CIBXML \
	|awk -F\" '{print $6}' >> $VFS1
    fi
fi

# Check for PCS NFS state mount. If present, ignore. (add to list)
# /var/lib/nfs is not defined physically, it's a static
# location and cannot be changed and must be ignored as
# a result. See:   man 7 ocf_heartbeat_nfsserver 

cat $VFS1 |sort -u > $VFS2

if [[ `/usr/bin/comm -13 $VFS2 $VMT1` == "/var/lib/nfs" ]] ;
	then
	echo "/var/lib/nfs" >> $VFS2
fi

# Check for normal bind mounts. For IRE - This check ignores the special
# bind mounts used in IRE, but does check for the chroot filesystem,
# which is a normal bind mount defined in /etc/fstab.

for M in `/usr/bin/comm -13 $VMT1 $VFS2` ; do
	/bin/mount |grep " $M " |awk '{print $3}' >> $VMT2
done

# Final concatenation, sort and cleanup

cat $VMT1 >> $VMT2

cat $VFS2 |sort -u > $VFS1
cat $VMT2 |sort -u > $VMT1

rm -f $VFS2 $VMT2 $MDIFF

# Final check. Output files are left in place for troubleshooting
# and identification of any missing mounts detected by this script.

diff $VMT1 $VFS1
