#!/usr/bin/env bash
###使用说明########
# 单节点
#多节点 master节点  ./Environmentcheck.sh  multi master
#       node节点    ./Environmentcheck.sh  multi node
#       存储节点    ./Environmentcheck.sh  multi storage

 # 单节点 检测项
       # 检测操作系统 说明支持centos7.X和ubuntu20.04
       #cpu检测       要大于32核
       # 内存检测     大于64G，
       # 系统盘检测  100G以上，
       # 数据盘检测  500G以上，
       # 系统文件格式检测 是否支持docker的overlay格式 lsmod |grep over，
       # 显卡检测
 #多节点检测项
#    master节点检测
        # 检测操作系统 说明支持centos7.X和ubuntu20.04
        #cpu检测       master节点要大于16核，node节点大于16核
       # 内存检测     master不小于32G，，node节点不小于32G
       # 系统盘检测  100G以上，
       # 数据盘检测  500G以上，
       # 系统文件格式检测 是否支持docker的overlay格式 #apt install xfsprogs || ，
       # 显卡检测
#   node节点检测
       # 检测操作系统 说明支持centos7.X和ubuntu20.04
       #cpu检测    node节点大于16核
       # 内存检测    node节点不小于32G
       # 系统盘检测  100G以上，
       # 系统文件格式检测 是否支持docker的overlay格式 #apt install xfsprogs || ，
       # 显卡检测
#storage
##allinone 机器的最小配置

systemdisk=100
allinone_core=32
allinone_memory=60
allinone_datadisk=200
#####多节点master的最小配置
master_core=14
master_memory=14
master_systemdisk=100
#########多节点node的最小配置
node_core=14
node_memory=30
node_datadisk=200
######存储节点的最小配置
storage_core=14
storage_memory=30
storage_datadisk=200
data_disk=$3
flag=5
function logger() {
  TIMESTAMP=$(date +'%Y-%m-%d %H:%M:%S')
  case "$1" in
    debug)
      echo -e "$TIMESTAMP DEBUG$2"
      ;;
    info)
      echo -e "$TIMESTAMP INFO $2"
      ;;
    warn)
      echo -e "$TIMESTAMP WARN $2"
      ;;
    error)
      echo -e "$TIMESTAMP ERROR$2"
      ;;
    *)
      ;;
  esac
}
###获取cpu逻辑核数并检测##########
CpuCheck(){
  cpucore=`cat /proc/cpuinfo| grep "processor"| wc -l`
   case $1 in
    allinone)
      if [  $cpucore -ge $allinone_core   ]; then
         logger info  "该节点cpu核数${cpucore}适合部署"
      else
         logger warn  "该节点cpu核数为${cpucore}，小于预设的${allinone_core}核，不适合部署单机版AI平台"
         # shellcheck disable=SC2219
         let "flag--"
    fi
     ;;
    multi)
      if [ $2 == master ] ; then
          if [ $cpucore -gt $master_core ]; then
                logger info "master 节点cpu核数${cpucore}适合部署"
          else
                logger warn "master 节点cpu核数为${cpucore}，小于预设${master_core}核，不适合部署"
                let "flag--"
          fi
      fi
      if [ $2 == node ];then
        if [ $cpucore -gt $node_core  ]; then
                logger info "node 节点cpu核数${cpucore}适合部署"

        else
                logger warn  "node节点cpu核数为${cpucore}，小于预设${node_core}核，不适合部署"
                let "flag--"
        fi
      fi
      if [ $2 == storage ];then
           if [ $cpucore -gt $storage_core   ]; then
               logger info "storage 节点cpu核数${cpucore}适合部署"
           else
                logger warn  "storage节点cpu核数为${cpucore},小于预设${storage_core}核，不适合部署"
                let "flag--"
            fi
      fi
      ;;
    *)
      echo "第一个参数请输入allinone或者multi，如果是multi，还需要第二个参数 master|node|storage"
     ;;
   esac
}
MemoryCheck(){
    Memory=`cat /proc/meminfo  | grep MemTotal | awk -F" " '{print $2}'`
    let  Memorytotal=Memory/1024/1024
     case $1 in
    allinone)
      if [  $Memorytotal -gt $allinone_memory   ]; then
         logger info "该节点内存${Memorytotal}G满足部署条件"
      else
         logger warn "该节点内存为${Memorytotal}G，小于${allinone_memory}G，不满足预设条件"
         let "flag--"
    fi
     ;;
    multi)
      if [ $2 == master ]; then
          if [ $Memorytotal -gt $master_memory   ]; then
                logger info "master 节点内存${Memorytotal}G满足部署条件"
          else
                logger warn "master 节点内存为${Memorytotal}G,小于${master_memory}G，不满足预设条件"
                let "flag--"
          fi
      fi
      if [ $2 == node ];then
            if [ $Memorytotal -gt $node_memory  ]; then
               logger info "node 节点内存${Memorytotal}G满足部署条件"
            else
                logger warn "node节点内存为${Memorytotal}G，${node_memory}G，不满足预设条件"
                let "flag--"
            fi
      fi
      if [ $2 == storage ];then
            if [ $Memorytotal -gt $storage_memory   ]; then
                logger info "storage 节点内存${Memorytotal}G满足部署条件"
            else
                logger warn "storage节点内存为${Memorytotal}G，小于${storage_memory}G，不满足预设条件"
                 let "flag--"
            fi
      fi
      ;;
    *)
      logger info "第一个参数请输入allinone或者multi，如果是multi，还需要第二个参数 master|node|storage"
     ;;
   esac
}
SystemdiskCheck() {
    capacity=$(df -B 1G | grep   ^/dev/[s/m/v/n] | grep /$| awk -F" " '{print $2}')
    if [ $capacity -gt $master_systemdisk ]; then
       logger info "系统盘${capacity}G符合部署条件"
    else
       logger warn "系统盘${capacity}G，小于${master_systemdisk}G,不满足预设条件"
       let "flag--"
    fi
}
StorageSystemdiskCheck() {
    capacity=0
    for value in $(df -B 1g | grep -E "/dev/mapper|/dev/sd|/dev/vd|/dev/nvm" | grep -v /boot | grep -v /dev/sdb | awk '{print $2}' | awk -F"G" '{print $1}'); do
        valueabs=${value%.*}
        capacity=$(($capacity + $valueabs))
    done
    if [ $capacity -gt $master_systemdisk ]; then
       logger info "系统盘${capacity}G符合部署条件"
    else
       logger warn "系统盘${capacity}G，小于${master_systemdisk}G,不满足预设条件"
       let "flag--"
    fi
}
SystemDataDiskCheck(){
  #获取$3的值为data_disk
  data_disk=$1
  #如果data_disk里面包含/dev/，则把/dev/去掉
  if [[ $data_disk == /dev/* ]]; then
    diskid=${data_disk#*dev/}
  else
    diskid=$data_disk
  fi
  lsblk  |grep  $diskid >/dev/null 2>&1
  if [ $? -eq 0 ]; then
        datatotalsize=`lsblk -b |grep  $diskid | head -n 1 | awk -F" " '{print $4}'`

        let "datatotalabs=datatotalsize/1024/1024/1024"
         if [ $datatotalabs -lt $storage_datadisk ]; then
          logger warn "数据盘只有${datatotalabs}G,不满足预设条件${storage_datadisk}G的要求"
        else
         logger info "数据盘${data_disk},${datatotalabs}G"
         fi
         #判断磁盘是否需要执行wipefs -af $diskid
        if wipefs --no-act "$diskid" | grep -q -E '[0-9a-f]+.*(ext[0-9]|xfs|swap|ntfs|fat|vfat)' \
        || parted -s "$diskid" print 2>/dev/null | grep -q 'Partition Table' \
        || (which pvck &>/dev/null && pvck "$diskid" 2>&1 | grep -q "Found LVM2"); then
          logger warn "警告：设备存在残留数据或分区表"
          echo "如需清理可执行：wipefs -af $diskid"
        else
          logger info "状态：设备干净"
        fi   
    else
      logger error "${diskid}是文件目录不是裸盘,不能使用glusterfs作为存储服务,请选择kadalu或者longhorn的方式"
       let "flag--"
  fi


}
SystemOsVersionCheck() {
    ID=`cat /etc/os-release  | grep -E "^ID="|awk -F"=" '{print $2}' |xargs`
    VERSION_ID=`cat /etc/os-release  | grep -E "^VERSION_ID="|awk -F"=" '{print $2}' |xargs`
    # shellcheck disable=SC2077
    if [ $ID==centos -a  $VERSION_ID==7 ] || [ $ID==ubuntu -a  $VERSION_ID==20.04 ] ; then
       logger info "当前操作系统的版本支持"

    else
      logger error "当前操作系统的版本不支持，请替换为centos7.X Server64 或者ubuntu20.04 Server64"
      let "flag--"
    fi
}
OverlaySupportCheck(){
 df -Th | grep xfs >/dev/null
  if [ $? -eq 0 ]; then
       type=`df   -T   -h  | grep xfs |awk -F" " '{print $7}' |xargs -L1 xfs_info  | grep ftype | awk -F" " '{print $6}' | awk -F"=" '{print $2}' | uniq`
      if [ $type -eq 0 ]; then
          logger warn  "当前系统不支持docker overlay"
          let "flag--"
       else
           logger info "支持docker overlay 安装"
      fi
  else
      logger info  "支持docker overlay 安装"
  fi

}
GPUCheck(){
  lspci  | grep NVIDIA >>/dev/null
  if [ $? == 1 ]; then
      logger warn "当前系统没有英伟达显卡"
      let "flag--"
      #检测驱动是否安装，并且获取驱动的版本
      if [ -f /usr/bin/nvidia-smi ]; then
        driver_version=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader | head -n 1)
        logger info "当前系统已安装nvidia驱动，版本为${driver_version}"
        #驱动的版本大于550.37.01，不支持mgpu，提示请使用550.37.01以下的版本
        if [ $(echo "$driver_version > 550.37.01" | bc -l) -eq 1 ]; then
          logger warn "当前系统nvidia驱动版本大于550.37.01，不支持mgpu，请使用550.37.01以下的版本"
          let "flag--"
        fi
      else
        logger warn "当前系统未安装nvidia驱动"
        let "flag--"
      fi
  else
     logger info  "当前系统有英伟达显卡"

  fi

}
main(){
  case $1 in
  allinone)
      SystemOsVersionCheck
      CpuCheck $1
      MemoryCheck $1
      StorageSystemdiskCheck $1 $2
      SystemDataDiskCheck $3
      OverlaySupportCheck
      GPUCheck
  ;;
  multi)
       if [ $2 = master ]; then
           SystemOsVersionCheck
           CpuCheck $1 $2
           MemoryCheck $1 $2
           SystemdiskCheck
           OverlaySupportCheck
           GPUCheck
        elif [ $2 = node ]; then
           SystemOsVersionCheck
           CpuCheck $1 $2
           MemoryCheck $1 $2
           SystemdiskCheck
           OverlaySupportCheck
           GPUCheck
        else
           SystemOsVersionCheck
           CpuCheck $1 $2
           MemoryCheck $1 $2
           StorageSystemdiskCheck $1 $2
           OverlaySupportCheck
           SystemDataDiskCheck  $3
           GPUCheck
       fi
    ;;
  esac
}
main "$@"
if [ $flag -lt 5 ]; then
    logger warn "============================\n
                  \t|| 该节点不满足预设安装条件 ||\n
                  \t=============================\n"
else
    logger info "============================\n
                  \t|| 该节点满足预设安装条件 ||\n
                  \t=============================\n"
fi


