#!/bin/bash

# Copyright (c) 1996-2014 HuaWei, China.
# Copyright (c) 2014 HuaWei Products.
# All rights reserved.
#
# Author: huawei, 2014
#
# Please send feedback to http://www.huawei.com

KERNEL_VERSION=`uname -r`

source /OSM/script/os_load_base.sh
source /OSM/script/nasproto_init_cgroup.sh
source /OSM/script/nasproto_process.sh
if [ "${KERNEL_VERSION:0:4}" == "4.19" ];then
source /OSM/script/os_vrf_exec.rc
fi


#xnet bind cpu may cause current sh can not schedule,
#we need use taskset bind to other cpu
if [ ! -f /OSM/script/get_usable_cpu_core.sh ];then
    OS_echo "/OSM/script/get_usable_cpu_core.sh not exist"
else
    source /OSM/script/get_usable_cpu_core.sh
    taskset -pc $usableCPUcoreNum $$
    OS_echo "usable cpu:$usableCPUcoreNum"
    nasnfs_cpu=`ps -eo pid,args:50,psr|grep "nasnfs.sh"|grep -v grep`
    OS_echo "nasnfs.sh ps info:$nasnfs_cpu"
fi

. /etc/sysconfig/nasnfs.conf

# Shell functions sourced from /etc/rc.status:
#      rc_check         check and set local and overall rc status
#      rc_status        check and set local and overall rc status
#      rc_status -v     ditto but be verbose in local rc status
#      rc_status -v -r  ditto and clear the local rc status
#      rc_failed        set local and overall rc status to failed
#      rc_failed <num>  set local and overall rc status to <num><num>
#      rc_reset         clear local rc status (overall remains)
#      rc_exit          exit appropriate to overall rc status
. /etc/rc.status

# First reset status of this service
rc_reset

##########################
# global varies          #
##########################
HAVE_NFSDFS="no"
NEED_SVCGSSD="no"
NEED_IDMAPD="no"

SVCGSSD_BIN=rpc.svcgssd
IDMAPD_BIN=rpc.idmapd
NAS_CLUSTER_BIN=cmr_cluster
NAS_STORE_BIN=cmr_store
NFSD_BIN=rpc.nfsd
IDMAPD_CLIENT_STATE=/var/lock/subsys/nfs-rpc.idmapd
IDMAPD_SERVER_STATE=/var/lock/subsys/nfsserver-rpc.idmapd
mkdir -p /var/lock/subsys; chmod 750 /var/lock/subsys;
NAS_PROTO_PUM_BIN=/OSM/bin/nas_proto_pum


##########################
# module list (can edit) #
##########################
COMKO_LIST=(
nas_pum
nas_klog
nas_mem
nas_netlink
nas_sysctrl
sunrpc
nas_lock
nas_proto_vfs
nas_acl
nas_notify
)

NFSKO_LIST=(
auth_rpcgss
nal
lockd
nfsd
)

##########################
# function               #
##########################

case $NFS_SECURITY_GSS in
  [Nn]*)        flavors="";;
  [Yy]*)        flavors=krb5;;
  *)            flavors="$NFS_SECURITY_GSS";;
esac

if [ "$flavors" ]; then
    NEED_SVCGSSD=yes
fi

nfsd_port_set=""
if [ -n "$NFS_NFSD_PORT" ]; then
   nfsd_port_set="-p ${NFS_NFSD_PORT}"
fi

nfsd_tcp_set=""
if [ "$NFS_NFSD_TCP_SUPPORT" = no ]; then
   nfsd_tcp_set=" -T "
fi

nfsd_udp_set=""
if [ "$NFS_NFSD_UDP_SUPPORT" = no ]; then
   nfsd_udp_set=" -U "
fi

acceptedhostname=""
if [ -n "$NFS_NFSD_ACCEPTED_IP" ]; then
   acceptedhostname="-H ${NFS_NFSD_ACCEPTED_IP}"
fi

statd_port_set=""
if [ -n "$STATD_PORT" ]; then
   statd_port_set="-p ${STATD_PORT}" 
fi

lockd_port_set=""
if [ -n "$LOCKD_PORT" ]; then
   lockd_port_set="nlm_udpport=${LOCKD_PORT} nlm_tcpport=${LOCKD_PORT}"
fi

if [ "$NFS4_SUPPORT" = yes ]; then
    NEED_IDMAPD=yes
fi

check_for_nfsdfs() {
    while read dummy type ; do
    if [ "$type" = "nfsd" ] ; then
        HAVE_NFSDFS="yes"
    fi
    done < /proc/filesystems
}

mount_rpc_pipefs() {
    # See if the file system is there yet
    case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs` in
    *67596969*)
        return 0;;
    esac
    mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs
}

umount_rpc_pipefs() {

    case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs` in
    *67596969*)
        umount /var/lib/nfs/rpc_pipefs;;
    esac
}

do_start_svcgssd() {
    for flavor in $flavors; do
        /sbin/modprobe rpcsec_gss_$flavor
    done

    mount_rpc_pipefs
    /OSM/bin/rpc.svcgssd 2>/dev/null &
    return $?
}

do_start_idmapd() {
    mount_rpc_pipefs

    if CheckProcess $IDMAPD_BIN && test -f $IDMAPD_CLIENT_STATE; then
        KillProcess $IDMAPD_BIN && /OSM/bin/$IDMAPD_BIN &
    else
        num=`ps -ef|grep -w "/OSM/bin/rpc.idmapd" |grep -v "/OSM/bin/rpc.idmapd -T 10000" |grep -v grep |wc -l`
        if [ $num -eq 0 ];then
            /OSM/bin/$IDMAPD_BIN 2>/dev/null &
        fi
        return $?
    fi
}

nfs_get_threads_num() {
    nas_rc_tmp=0
    com_threads_num=8
    nas_rc_tmp=$?
    if [ $nas_rc_tmp -eq 0 ]; then
        OS_echo "[nasnfs.sh] [Com_threads_num $com_threads_num.]" 
    else
        com_threads_num="$USE_KERNEL_NFSD_NUMBER"
        OS_echo "[nasnfs.sh] [Com_threads_num 4 with default value.]" 
    fi

    nfs_workerthreads_set=""
    nas_rc_tmp=0
    work_threads_num=percpu
    nas_rc_tmp=$?
    if [ $nas_rc_tmp -eq 0 ]; then
        OS_echo "[nasnfs.sh] [Work_threads_num $work_threads_num.]"  
        nfs_workerthreads_set="-t ${work_threads_num}"
    fi
}

check_config_exist()
{
    mount |grep /startup_disk/conf >/dev/null 2>&1
    if [ $? -ne 0 ];then
        OS_echo "[nasnfs.sh] [The mount path /startup_disk/conf is not exist.]"
    fi
    PROTO_CONFIG_SSD_DIR=/startup_disk/conf/conf_local/protocol
    [ ! -d $PROTO_CONFIG_SSD_DIR/nfs ] && mkdir -p $PROTO_CONFIG_SSD_DIR/nfs
    chmod 750 $PROTO_CONFIG_SSD_DIR/nfs  >/dev/null 2>&1
    
    if [ ! -f ${PROTO_CONFIG_SSD_DIR}/nfs/nasnfs.conf ];then
        cp /etc/sysconfig/nasnfs.conf ${PROTO_CONFIG_SSD_DIR}/nfs/
    fi
    chmod 600 $PROTO_CONFIG_SSD_DIR/nfs/nasnfs.conf  >/dev/null 2>&1
    if [ ! -f ${PROTO_CONFIG_SSD_DIR}/nfs/ldap.conf.bak ];then
        cp /etc/ldap.conf.bak ${PROTO_CONFIG_SSD_DIR}/nfs/
    fi
    chmod 640 $PROTO_CONFIG_SSD_DIR/nfs/ldap.conf.bak  >/dev/null 2>&1
    if [ ! -f ${PROTO_CONFIG_SSD_DIR}/nfs/nsswitch.conf ];then
        cp /etc/nsswitch.conf ${PROTO_CONFIG_SSD_DIR}/nfs/
    fi
    chmod 600 $PROTO_CONFIG_SSD_DIR/nfs/nsswitch.conf  >/dev/null 2>&1
    if [ ! -f ${PROTO_CONFIG_SSD_DIR}/nfs/idmapd.conf ];then
        cp /etc/idmapd.conf ${PROTO_CONFIG_SSD_DIR}/nfs/
    fi
    chmod 600 $PROTO_CONFIG_SSD_DIR/nfs/idmapd.conf  >/dev/null 2>&1

    chmod 640 $PROTO_CONFIG_SSD_DIR/nfs/defaultdomain  >/dev/null 2>&1
    chmod 640 $PROTO_CONFIG_SSD_DIR/nfs/ldap.conf.openbak  >/dev/null 2>&1
    chmod 640 $PROTO_CONFIG_SSD_DIR/nfs/yp.conf  >/dev/null 2>&1
    chmod 600 $PROTO_CONFIG_SSD_DIR/nfs/nslcd.conf.bak  >/dev/null 2>&1
}

case "$1" in       
    start) 
        OS_echo "[nasnfs.sh][Begin start service.]"    
        ldconfig
        
        check_config_exist
                
        mount | grep pum >/dev/null
        if [ $? -ne 0 ] ; then
            mkdir -p /var/lib/pum
            mount -t pum pum /var/lib/pum 
        fi 
        
        mkdir -p /var/lib/nfs/rpc_pipefs; chmod 750 /var/lib/nfs/rpc_pipefs
        mkdir -p /var/camaro/log;
        mkdir -p /var/camaro/db;
        mkdir -p /var/lib/nfs/sm; chmod 750 /var/lib/nfs/sm
        mkdir -p /var/lib/nfs/sm.bak; chmod 750 /var/lib/nfs/sm.bak
        touch /var/lib/nfs/state; chmod 600 /var/lib/nfs/state
      
        # mount nfsd filesystem
        check_for_nfsdfs
        if [ "$HAVE_NFSDFS" = "yes" -a ! -f /proc/fs/nfsd/exports ] ; then
            mount -t nfsd nfsd /proc/fs/nfsd 
        fi
        
        /OSM/bin/cgroup_manage.sh -c memory -g protocol start
        OS_echo "[nasnfs.sh] [nasnfs pid is $$]"
        
        CheckProcess cmr_store
        if [ $? -ne 0 ];then
            cmr_store 2>/dev/null &
        fi
        
        CheckProcess cmr_cm
        if [ $? -ne 0 ];then 
            cmr_cm 2>/dev/null &
        fi
        
        /OSM/bin/cgroup_manage.sh -c memory -g protocol end
        OS_echo "[nasnfs.sh][Start notify kernel basic config.]"
        /OSM/bin/nas_proto_cfg -c notify_kernel_basic_cfg -v nfs 2>&1 > /dev/null &
        pid=`pidof rpcbind`
        /OSM/bin/cgroup_manage.sh -i $pid end
        init_common_proc
        OS_echo "[nasnfs.sh][End start service.]" 
        exit 0
        
        ;;
    
    ustart)
        OS_echo "[nasnfs.sh][Begin ustart service.]"
        
        /OSM/bin/cgroup_manage.sh -c memory -g protocol start
        OS_echo "[nasnfs.sh] [nasnfs ustart pid is $$]"
        
        
        if [ "$NFS4_SUPPORT" = "yes" ]; then
            VERSION_LIST="+3 +4"
            VERSION_PARAMS=""
        else
            VERSION_LIST="+3 -4"
            VERSION_PARAMS="--no-nfs-version 4"
        fi

        if [ "$NFS41_SUPPORT" = "yes" ]; then
            VERSION_LIST="$VERSION_LIST +4.1"
        else
            VERSION_LIST="$VERSION_LIST -4.1"
        fi
        
        ret=`nas_proto_pum -m nfs -c get_nfsd_threads`
        if [ "$ret" = "0" ]; then
            nas_proto_pum -m nfs -c set_versions -v "$VERSION_LIST"
        fi
      
        # svcgssd; idmapd
        if [ "$NEED_SVCGSSD" = yes ]; then
            do_start_svcgssd || {
                OS_echo "[nasnfs.sh] [Do_start_svcgssd failed.]"
            }
        fi
        if [ "$NEED_IDMAPD" = yes ]; then
            do_start_idmapd 
            num=`ps -ef|grep -w "/OSM/bin/rpc.idmapd" |grep -v "/OSM/bin/rpc.idmapd -T 10000" |grep -v grep |wc -l`
            if [ $num -eq 0 ];then
                OS_echo "[nasnfs.sh] [Do_start_idmapd failed.]"
            fi
            echo $IDMAPD_BIN > $IDMAPD_SERVER_STATE; chmod 600 $IDMAPD_SERVER_STATE;
        fi
      
        #check rpcbind
        if [ "${KERNEL_VERSION:0:4}" == "4.19" ];then
            retry=0
            num=`ps -ef|grep  "/usr/bin/rpcbind" |grep w |grep f |grep -v grep |wc -l`
            while [[ $num -ge 1 && $retry -le 5 ]];do
                KillProcess rpcbind
                sleep 1
                let retry++
                OS_echo "[nasnfs.sh] [Do_restart_rpcbind.]"
                num=`ps -ef|grep  "/usr/bin/rpcbind" |grep w |grep f |grep -v grep |wc -l`
            done
        fi
        ps -ef |grep rpcbind |grep -v grep >/dev/null
        if [ $? -ne 0 ];then
            export RPCBIND_GETADDR_RETURN_CLIENT_IP=1
            if [ "${KERNEL_VERSION:0:4}" == "4.19" ];then
                OS_EXEC_TO_SRV_VRF rpcbind 2>/dev/kmsg
            else
                rpcbind 2>/dev/kmsg
            fi
            ps -ef |grep rpcbind |grep -v grep
            if [ $? -ne 0 ];then
                OS_echo "[nasnfs.sh] [Rpcbind start failed.]"
            fi
        fi
        # rpc.mountd
        num=`ps -ef|grep -w "/OSM/bin/rpc.mountd -p" |grep -v grep |wc -l`
        if [ $num -eq 0 ]; then
            mountd_thread_num_set=""
            if [ -n "$NFS_MOUNTD_THREAD_NUM" ]; then
                mountd_thread_num_set="-t ${NFS_MOUNTD_THREAD_NUM}"  
            fi
            
            mountd_port_set=""
            if [ -n "$MOUNTD_PORT" ]; then
               mountd_port_set="-p ${MOUNTD_PORT}" 
            fi
            
            mountd_tcp_set=""
            if [ "$NFS_MOUNTD_TCP_SUPPORT" = no ]; then
               mountd_tcp_set=" -n "
            fi  
            mountd_udp_set=""
            if [ "$NFS_MOUNTD_UDP_SUPPORT" = no ]; then
               mountd_udp_set=" -u "
            fi  
             
            OS_echo "[nasnfs.sh][start rpc.mountd]"
            /OSM/bin/rpc.mountd $mountd_thread_num_set $mountd_port_set $mountd_udp_set $mountd_tcp_set $VERSION_PARAMS &
            num=`ps -ef|grep -w "/OSM/bin/rpc.mountd -p" |grep -v grep |wc -l`
            if [ $num -eq 0 ];then
                OS_echo "[nasnfs.sh] [Nfsserver rpc.mountd start failed.]"
            fi
        fi    
        
        ps -ef |grep rpcbind |grep -v grep >/dev/null
        if [ $? -ne 0 ];then
            export RPCBIND_GETADDR_RETURN_CLIENT_IP=1
            if [ "${KERNEL_VERSION:0:4}" == "4.19" ];then
                OS_EXEC_TO_SRV_VRF rpcbind 2>/dev/kmsg
            else
                rpcbind 2>/dev/kmsg
            fi
            ps -ef |grep rpcbind |grep -v grep
            if [ $? -ne 0 ];then
                OS_echo "[nasnfs.sh] rpcbind start failed"
            fi
        fi
        # rpc.statd
        num=`ps -ef|grep -w "/OSM/bin/rpc.statd -p" |grep -v grep |wc -l`
        if [ $num -eq 0 ]; then
            OS_echo "[nasnfs.sh][Start rpc.statd.]"
            /OSM/bin/rpc.statd $statd_port_set --no-notify & 
            num=`ps -ef|grep -w "/OSM/bin/rpc.statd -p" |grep -v grep |wc -l`
            if [ $num -eq 0 ]; then 
                OS_echo "[nasnfs.sh] [Nfsserver rpc.statd start failed.]"
            fi
        fi
        
        # rpc.nfsd
        OS_echo "[nasnfs.sh][Start rpc.nfsd.]"
        nfs_get_threads_num
        PARAMS="$com_threads_num"
        if [ "`/OSM/bin/nas_proto_pum -m nfs -c get_nfsd_threads`" = "0" ]; then
            $NFSD_BIN $PARAMS $VERSION_PARAMS $nfsd_port_set $acceptedhostname  $nfsd_tcp_set $nfsd_udp_set $nfs_workerthreads_set || {
            OS_echo "[nasnfs.sh] [Nfsserver rpc.nfsd start failed.]"
            }
        fi
        
        # sm-notify needs to be run last
        OS_echo "[nasnfs.sh][Start sm-notify.]"
        sm-notify $SM_NOTIFY_OPTIONS &
        
        /OSM/bin/cgroup_manage.sh -c memory -g protocol end
        pid=`pidof rpcbind`
        /OSM/bin/cgroup_manage.sh -i $pid end
        init_nfs_proc 
        OS_echo "[nasnfs.sh][End ustart service.]" 
        exit 0
        ;;
    
    pre_stop_online)
        $NAS_PROTO_PUM_BIN -m nfs -c set_nfsd_threads -v 0 2>&1     
        rc_status -v
        ;;
        
    pre_stop_offline)
        $NAS_PROTO_PUM_BIN -m nfs -c set_nfsd_threads -v 0 2>&1     
        rc_status -v
        ;;
    
    stop)
        OS_echo "[nasnfs.sh][Begin stop service.]" 
              
        mount | grep pum |grep -v grep >/dev/null
        if [ $? -eq 0 ] ; then
            $NAS_PROTO_PUM_BIN -m nfs -c set_nfsd_threads -v 0 2>&1 
            thread_status_try_time=0
            total_retry_times=0
            nfs_thread_status=`$NAS_PROTO_PUM_BIN -m nfs -c get_nfsd_srv_shutdown_status`
            while ( [ "$nfs_thread_status" != "0" ] && [ $total_retry_times -le 180 ] )
            do
                OS_echo "[nasnfs.sh] [Stop nfsd_work fail.]"
                [ "$thread_status_try_time" -eq 0 ] && nas_proto_pum -m nas_sysctrl -c get_io_hang 2>&1 >/dev/null
                sleep 1
                #check pum filesystem
                mount | grep pum |grep -v grep >/dev/null
                if [ $? -ne 0 ];then
                    OS_echo "[nasnfs.sh] [Can't find pum filesystem.]"
                    break
                fi
                nfs_thread_status=`$NAS_PROTO_PUM_BIN -m nfs -c get_nfsd_srv_shutdown_status`                
                let "total_retry_times+=1"
                let "thread_status_try_time+=1"
                [ "$thread_status_try_time" -eq 5 ] && thread_status_try_time=0
            done

            ps -ef | grep smbd | grep -v grep >/dev/null
            if [ $? -ne 0 ];then
                umount /var/lib/pum
            fi
        fi
        KillProcess rpc.statd
        KillProcess rpc.mountd  
          
        if [ "$NEED_SVCGSSD" = yes ]; then
            KillProcess $SVCGSSD_BIN
        fi
        
        # idmap
        KillProcess $IDMAPD_BIN 

        rm -f $IDMAPD_SERVER_STATE

        umount_rpc_pipefs

        # umount nfsd fs
        check_for_nfsdfs
        if [ "$HAVE_NFSDFS" = "yes" -a -f /proc/fs/nfsd/exports ] ; then
            umount /proc/fs/nfsd
        fi
        
        # rpcbind
        KillProcess rpcbind
		
        # cmr_store cmr_cm
        if [ "$2" = "-a" ];then
            CheckProcess cmr_store
            [ $? -eq 0 ] && KillProcess cmr_store
            CheckProcess cmr_cm
            [ $? -eq 0 ] && KillProcess cmr_cm 
        fi
		
        OS_echo "[nasnfs.sh][End stop service.]"
        exit 0
        ;;
    
    ustop)
        OS_echo "[nasnfs.sh][Begin ustop service.]"
        mount | grep pum >/dev/null
        if [ $? -eq 0 ] ; then
            $NAS_PROTO_PUM_BIN -m nfs -c set_nfsd_threads -v 0 2>&1 
            
            nfs_thread_status=`$NAS_PROTO_PUM_BIN -m nfs -c get_nfsd_srv_shutdown_status`
            if [ $? -ne 0 ]; then
                OS_echo "[nasnfs.sh] [Ustop nfs fail.]"
                nfs_thread_status=`$NAS_PROTO_PUM_BIN -m nfs -c get_nfsd_srv_shutdown_status`

            fi
        fi
        
        KillProcess rpc.statd 
        KillProcess rpc.mountd  
          
        if [ "$NEED_SVCGSSD" = yes ]; then
            KillProcess $SVCGSSD_BIN
        fi
        
        # idmap
        KillProcess $IDMAPD_BIN
        rm -f $IDMAPD_SERVER_STATE
        
        # kill rpcbind
        KillProcess rpcbind

        OS_echo "[nasnfs.sh][End ustop service.]"
        exit 0
        ;;
        
    restart)
        $0 stop
        $0 start 
        rc_status -v
        ;; 
        
    status)
        lsmod|grep -E "\bvfsd\b|\bnas_sysctrl\b|\bauth_rpcgss\b|\bnas_lock\b|\bnal\b|\blockd\b|\bnfsd\b"

        echo -e ""
        mount|grep -E "/var/lib/pum"
        mount|grep -E "/proc/fs/nfsd"
        mount|grep -E "/var/lib/nfs/rpc_pipefs"
        echo -e ""
    
        echo -n " rpcbind" && CheckProcess rpcbind
        rc_status -v
        echo -n " cmr_store" && CheckProcess cmr_store
        rc_status -v
        echo -n " cmr_cm" && CheckProcess cmr_cm
        rc_status -v
        ps -ef |grep nfsd|grep -v grep >/dev/null
        if [ $? -eq 0 ] ;then
            echo -e " [kernel thread]nfsd is running"
        else
            echo -e " [kernel thread]nfsd is dead"
        fi          
        
        echo -n " rpc.statd" && CheckProcess rpc.statd
        rc_status -v
        echo -n " rpc.mountd" && CheckProcess rpc.mountd
        rc_status -v
        echo -n " rpc.idmapd" && CheckProcess rpc.idmapd
        rc_status -v
        
        ;;
        
    *)
        echo "Usage: $0 {start|ustart|stop [-option]|ustop|status|restart|pre_stop_online|pre_stop_offline}"
        echo "[-option]: "
        echo "  -a    with (stop) commond, stop all service, offline"
        exit 1
        ;;
esac

rc_exit
