#!/bin/bash
# Authors: Steven Shiau <steven _at_ nchc org tw>, Ceasar Sun <ceasar _at_ nchc org tw>
# License: GPL
#
# generate the NFS exports or clean the old one.

# Load DRBL setting and functions
DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"

. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions

#
check_if_root

# setting
nfs_exports="/etc/exports"
EXPORTS_NFS_RO_NRS_OPT="ro,async,no_root_squash,no_subtree_check"
EXPORTS_NFS_RW_NRS_OPT="rw,sync,no_root_squash,no_subtree_check"
EXPORTS_NFS_RW_RS_OPT="rw,sync,root_squash,no_subtree_check"

# main
usage() {
  echo "To generate or clean NFS exports for DRBL clients"
  echo "Usage: $0 [Options] {generate|clean}"
  echo "Options:"
  language_help_prompt_by_idx_no
  echo "-a, --all-subnet:   Make all subnet can access to this NFS server."
  echo "-n, --no-restart: Not restart NFS service"
  echo "-v, --verbose:  Verbose mode."
  echo "Example: To generate NFS exports for DRBL clients"
  echo "$0 generate"
}

#
set_nfsd_number() {
  local total_nfsd=$1
  if [ -z "$total_nfsd" ]; then
    echo "No total_nfsd is assigned!!! Program terminated!"
    exit 1
  fi
  # set the RPCNFSDCOUNT to $total_client_no*$NFSD_RATIO (say "40") 
  # in /etc/sysconfig/nfs instead of 8 in /etc/init.d/nfs (for RH-like)
  # 
  if [ -e /etc/debian_version ]; then
    # Debian
    if [ -f /etc/default/nfs-kernel-server ]; then
      # The nfs-kernel-server reads /etc/default/nfs-kernel-server (Sarge)
      perl -p -i -e "s/RPCNFSDCOUNT=.*/RPCNFSDCOUNT=$total_nfsd/g" /etc/default/nfs-kernel-server
    else
      # The nfs-kernel-server does NOT support /etc/default/nfs-kernel-server,
      # put it in the service (Woody).
      # If it's unfsd, not config file at all. Therefore we test it before modify it.
      if [ -f /etc/init.d/nfs-kernel-server ]; then
        perl -p -i -e "s/^RPCNFSDCOUNT=.*/RPCNFSDCOUNT=$total_nfsd/g" /etc/init.d/nfs-kernel-server
      fi
    fi
  elif [ -e /etc/SuSE-release ]; then
    # SUSE
    perl -p -i -e "s/^USE_KERNEL_NFSD_NUMBER=.*/USE_KERNEL_NFSD_NUMBER=$total_nfsd/g" /etc/sysconfig/nfs
  else
    # RH-like
    # Fedora uses service name "nfs", so does Mandriva 2007 or earlier. However, from Mandriva 2008.0, it's nfs-server. Therefore we use $NFS_SRV_NAME from drbl.conf
    # We need to know the parameter for NFS daemon number, check that in /etc/init.d/nfs. Maybe it RPCNFSDCOUNT or NFSDCOUNT
    if grep -qE "\<RPCNFSDCOUNT=.*" /etc/init.d/$NFS_SRV_NAME 2>/dev/null; then
      # For Mandriva 2006, the /etc/sysconfig/nfs already exists when fresh installed. We had better to keep other parameters, not "cat ..." to overwrite all.
      if grep -q "^[#]*[[:space:]]*RPCNFSDCOUNT=.*" /etc/sysconfig/$NFS_SRV_NAME 2>/dev/null; then
        perl -p -i -e "s/^.*RPCNFSDCOUNT=.*/RPCNFSDCOUNT=$total_nfsd/g" /etc/sysconfig/$NFS_SRV_NAME
      else
        cat <<-NFSRPC_END > /etc/sysconfig/$NFS_SRV_NAME
RPCNFSDCOUNT=$total_nfsd
NFSRPC_END
      fi
    elif grep -q "\<NFSDCOUNT=.*" /etc/init.d/$NFS_SRV_NAME 2>/dev/null; then
      # For Mandrake 9.2-10.1, the /etc/sysconfig/nfs already exists when fresh installed. We had better to keep other parameters.
      if grep -q "^[#]*[[:space:]]*NFSDCOUNT=.*" /etc/sysconfig/$NFS_SRV_NAME 2>/dev/null; then
        perl -p -i -e "s/^.*NFSDCOUNT=.*/NFSDCOUNT=$total_nfsd/g" /etc/sysconfig/$NFS_SRV_NAME
      else
        cat <<-NFSRPC_END > /etc/sysconfig/$NFS_SRV_NAME
NFSDCOUNT=$total_nfsd
NFSRPC_END
      fi
    elif grep -q "\<RPCNFSDCOUNT=.*" /etc/sysconfig/$NFS_SRV_NAME 2>/dev/null; then
      # For systemd-like, E.g. FC17
      perl -p -i -e "s/^.*RPCNFSDCOUNT=.*/RPCNFSDCOUNT=$total_nfsd/g" /etc/sysconfig/$NFS_SRV_NAME
    else
      [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
      echo "Warning!!! Unable to determine the NFS daemon number parameter (Not RPCNFSDCOUNT or NFSDCOUNT)! This NFS service will not be good enough when there is heavy client traffic!!!"
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    fi
  fi
}

# load the setting, especiall "drbl_mode".
[ -f "/etc/drbl/drbl_deploy.conf" ] && . /etc/drbl/drbl_deploy.conf

# default setting
all_subnet="no"
restart_nfs="yes"
specified_lang="en_US"

while [ $# -gt 0 ]; do
  case "$1" in
    -a|--all-subnet)
		all_subnet="yes"
                shift;;
    -n|--no-restart)
		restart_nfs="no"
                shift;;
    -v|--verbose)
		shift; verbose="on"
                ;;
    -*)		echo "${0}: ${1}: invalid option" >&2
		usage >& 2
		exit 2 ;;
    *)		break ;;
  esac
done
mode="$1"

#
ask_and_load_lang_set $specified_lang

case "$mode" in
   "generate")
      echo "Generating the NFS exports for DRBL clients... "
      echo "Backup the original $nfs_exports as $nfs_exports.drblsave"
      [ -f "$nfs_exports" ] && mv -f $nfs_exports ${nfs_exports}.drblsave
      time_now="$(date "+%T %Y/%m/%d")"
      cat <<EOF > $nfs_exports
# Generated by DRBL at $time_now
EOF
      if [ "$all_subnet" = "yes" ]; then
        # export all subnet to clients
	echo "Exporting whole subnet to clients..."
        subnet_list="$(get-client-ip-list | awk -F"." '{print $1"."$2"."$3}' | sort | uniq )"
        for subnet in $subnet_list; do
          cat <<EOF >> $nfs_exports
$drbl_common_root $subnet.*($EXPORTS_NFS_RO_NRS_OPT)
/usr $subnet.*($EXPORTS_NFS_RO_NRS_OPT)
/home $subnet.*($EXPORTS_NFS_RW_NRS_OPT)
/var/spool/mail $subnet.*($EXPORTS_NFS_RW_RS_OPT)
EOF
          # if $ocsroot is not under /home, or if $ocsroot is a mount point, we have to export it
          if [ -z "$(echo $ocsroot | grep -Ew "^/home")" -o \
	       -n "$(awk -F" " '{print $2}' /proc/mounts | grep -Ew "$ocsroot")" ]; then
            cat <<EOF >> $nfs_exports
$ocsroot $subnet.*($EXPORTS_NFS_RW_NRS_OPT)
EOF
          fi
          # add user assigned dir to exports
          for d in $diskless_root_dir_ro_user_add; do
          cat <<EOF >> $nfs_exports
$d $subnet.*($EXPORTS_NFS_RO_NRS_OPT)
EOF
          done
          for d in $diskless_root_dir_rw_user_add; do
          cat <<EOF >> $nfs_exports
$d $subnet.*($EXPORTS_NFS_RW_NRS_OPT)
EOF
          done
	  # append one space line
          cat <<EOF >> $nfs_exports

EOF
        done
      else
        # export one by one
	echo "Exporting to clients by IP address line-by-line..."
        for ip in `get-client-ip-list`; do
          cat <<EOF >> $nfs_exports
$drbl_common_root $ip($EXPORTS_NFS_RO_NRS_OPT)
/usr $ip($EXPORTS_NFS_RO_NRS_OPT)
/home $ip($EXPORTS_NFS_RW_NRS_OPT)
/var/spool/mail $ip($EXPORTS_NFS_RW_RS_OPT)
EOF
          # if $ocsroot is not under /home, or if $ocsroot is a mount point, we have to export it
          if [ -z "$(echo $ocsroot | grep -Ew "^/home")" -o \
	       -n "$(awk -F" " '{print $2}' /proc/mounts | grep -Ew "$ocsroot")" ]; then
            cat <<EOF >> $nfs_exports
$ocsroot $ip($EXPORTS_NFS_RW_NRS_OPT)
EOF
          fi
          # add user assigned dir to exports
          for d in $diskless_root_dir_ro_user_add; do
          cat <<EOF >> $nfs_exports
$d $ip($EXPORTS_NFS_RO_NRS_OPT)
EOF
          done
          for d in $diskless_root_dir_rw_user_add; do
          cat <<EOF >> $nfs_exports
$d $ip($EXPORTS_NFS_RW_NRS_OPT)
EOF
          done
	  # append one space line
          cat <<EOF >> $nfs_exports

EOF
        done
      fi

      # export for every client's etc, var 
      if [ "$drbl_mode" = "full_drbl_mode" -o "$clonezilla_mode" = "full_clonezilla_mode" ]; then
        echo "Full DRBL or Full Clonezilla mode, exporting client's directories etc, var, root..." 
        for ip in `get-client-ip-list`; do
          [ ! -d "$drblroot/$ip/" ] && continue
          [ -n "$verbose" ] && echo "Creating exports for directories etc, var, root of node $ip..."
          cat <<EOF >> $nfs_exports
$drblroot/$ip/ $ip($EXPORTS_NFS_RW_NRS_OPT)
EOF
        done
      fi

      echo "The $nfs_exports setting is ok now!"
      # rm /var/lib/nfs/rmtab to avoid a long time try when restart NFS
      [ -f /var/lib/nfs/rmtab ] && rm -f /var/lib/nfs/rmtab

      # calculate the number of the NFS daemon 
      nfsd_no="$(get-necessary-nfsd-no)"
      if [ -z "$nfsd_no" ]; then
         [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
         echo "Unable to get necessary NFSD number, program terminated!!!"
         [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
	 exit 1
      fi
      set_nfsd_number $nfsd_no

      # restart nfs if necessary
      if [ "$restart_nfs" = "yes" ]; then
         echo "Restarting NFS service..."
	 echo "$msg_delimiter_star_line"
         /etc/init.d/$NFS_SRV_NAME restart
	 echo "$msg_delimiter_star_line"
      fi
      ;;
    "clean")
      echo "Now disable the NFS exports for DRBL clients..."
      # stop nfs if necessary
      if [ "$restart_nfs" = "yes" ]; then
         echo "Stopping NFS service..."
	 echo "$msg_delimiter_star_line"
         /etc/init.d/$NFS_SRV_NAME stop
	 echo "$msg_delimiter_star_line"
      fi
      if [ -f $nfs_exports ]; then 
        echo "Remove the $nfs_exports..."
        [ -f "$nfs_exports" ] && mv -f $nfs_exports ${nfs_exports}.drblsave
      fi
      echo "done!"
      ;;
    *)
      usage
      exit 1
esac
