#!/bin/bash

octopus_agent_path=/usr/local/etc/octpus-agent
. "$octopus_agent_path/lib/wdd-lib-log.sh"
. "$octopus_agent_path/lib/wdd-lib-sys.sh"

host_arch_version=""
cpu_arch=""
#### CollectSystemInfo ####
server_name=""
server_ip_pb_v4=""
server_ip_in_v4=""
server_ip_pb_v6=""
server_ip_in_v6=""
location=""
provider=""
manage_port=""
cpu_brand=""
cpu_core=""
memory_total=""
disk_total=""
disk_usage=""
os_info=""
os_kernel_info=""
tcp_control=""
virtualization=""
io_speed=""
machine_id=""
arch_info=""
agent_version=""
os_bit=""

### tmp usage
io_speed=""
public_ipv4=""
inner_ipv4=""
public_ipv6=""
inner_ipv6=""
country=""
region=""
city=""
net_provider=""
manage_port=""
machine_number=""
l_bit=""
#### CollectSystemInfo ####

#######################################
# description
# Arguments:
#   1
#######################################
io_test() {
  (LANG=C dd if=/dev/zero of=benchtest_$$ bs=512k count=$1 conv=fdatasync && rm -f benchtest_$$) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
}

#######   获取系统版本及64位或32位信息
check_sys() {
  local sys_bit
  sys_bit=$(uname -m)
  case $sys_bit in
    i[36]86)
      os_bit="32"
      cpu_arch="386"
      ;;
    x86_64)
      os_bit="64"
      cpu_arch="amd64"
      ;;
    *armv6*)
      os_bit="arm"
      cpu_arch="arm6"
      ;;
    *armv7*)
      os_bit="arm"
      cpu_arch="arm7"
      ;;
    *aarch64* | *armv8*)
      os_bit="arm64"
      cpu_arch="arm64"
      ;;
    *)
      error "
       哈哈……这个 辣鸡脚本 不支持你的系统。 (-_-) \n
       备注: 仅支持 Ubuntu 16+ / Debian 8+ / CentOS 7+ 系统
       " && exit 1
      ;;
  esac
  ## 判定Linux的发行版本
  if [ -f /etc/redhat-release ]; then
    host_arch_version="centos"
  elif cat /etc/issue | grep -Eqi "debian"; then
    host_arch_version="debian"
  elif cat /etc/issue | grep -Eqi "ubuntu"; then
    host_arch_version="ubuntu"
  elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then
    host_arch_version="centos"
  elif cat /proc/version | grep -Eqi "debian"; then
    host_arch_version="debian"
  elif cat /proc/version | grep -Eqi "ubuntu"; then
    host_arch_version="ubuntu"
  elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then
    host_arch_version="centos"
  else
    host_arch_version=""
  fi

  return 0
}

#######################################
# description
# Arguments:
#   1
# Returns:
#   <unknown> ...
#######################################
calc_size() {
  local raw=$1
  local total_size=0
  local num=1
  local unit="KB"
  if ! [[ ${raw} =~ ^[0-9]+$ ]]; then
    echo ""
    return
  fi
  if [ "${raw}" -ge 1073741824 ]; then
    num=1073741824
    unit="TB"
  elif [ "${raw}" -ge 1048576 ]; then
    num=1048576
    unit="GB"
  elif [ "${raw}" -ge 1024 ]; then
    num=1024
    unit="MB"
  elif [ "${raw}" -eq 0 ]; then
    echo "${total_size}"
    return
  fi
  total_size=$(awk 'BEGIN{printf "%.1f", '$raw' / '$num'}')
  echo "${total_size} ${unit}"
}

#######################################
# description
# Arguments:
#  None
# Returns:
#   <unknown> ...
#######################################
get_host_arch_info() {
  FunctionStart "开始获取系统架构信息！"

  [ -f /etc/redhat-release ] && awk '{print $0}' /etc/redhat-release && return
  [ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
  [ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return

  FunctionEnd
}

#######################################
# description
# Globals:
#   freespace
#   io1
#   io2
#   io3
#   ioall
#   ioavg
#   ioraw1
#   ioraw2
#   ioraw3
#   writemb
# Arguments:
#  None
#######################################
start_io_test() {
  FunctionStart "开始测试IO速度！"
  freespace=$(df -m . | awk 'NR==2 {print $4}')
  if [ -z "${freespace}" ]; then
    freespace=$(df -m . | awk 'NR==3 {print $3}')
  fi
  if [ ${freespace} -gt 1024 ]; then
    writemb=2048
    io1=$(go_iotest ${writemb})
    log "I/O Speed(1st run) : $io1)"
    io2=$(go_iotest ${writemb})
    log "I/O Speed(2st run) : $io2)"
    io3=$(go_iotest ${writemb})
    log "I/O Speed(3st run) : $io3)"
    ioraw1=$(echo $io1 | awk 'NR==1 {print $1}')
    [ "$(echo $io1 | awk 'NR==1 {print $2}')" == "GB/s" ] && ioraw1=$(awk 'BEGIN{print '$ioraw1' * 1024}')
    ioraw2=$(echo $io2 | awk 'NR==1 {print $1}')
    [ "$(echo $io2 | awk 'NR==1 {print $2}')" == "GB/s" ] && ioraw2=$(awk 'BEGIN{print '$ioraw2' * 1024}')
    ioraw3=$(echo $io3 | awk 'NR==1 {print $1}')
    [ "$(echo $io3 | awk 'NR==1 {print $2}')" == "GB/s" ] && ioraw3=$(awk 'BEGIN{print '$ioraw3' * 1024}')
    ioall=$(awk 'BEGIN{print '$ioraw1' + '$ioraw2' + '$ioraw3'}')
    io_speed=$(awk 'BEGIN{printf "%.1f", '$ioall' / 3}')
    log "I/O Speed(average) : $io_speed MB/s)"
  else
    echo " $(_red "Not enough space for I/O Speed test!")"
  fi

  FunctionEnd
}

#######################################
# description
# Globals:
#   cpu_name
#   sys_manu
#   sys_product
#   sys_ver
#   virt
#   virtual_x
# Arguments:
#  None
#######################################
check_virtualization() {

  FunctionStart "开始收集服务器虚拟化信息！"

  local virtual_x
  if command_exists "dmesg"; then
      virtual_x="$(dmesg 2>/dev/null)"
  fi

  local sys_manu
  local sys_product
  local sys_ver

  if command_exists "dmidecode"; then
    sys_manu="$(dmidecode -s system-manufacturer 2>/dev/null)"
    sys_product="$(dmidecode -s system-product-name 2>/dev/null)"
    sys_ver="$(dmidecode -s system-version 2>/dev/null)"
  else
    sys_manu=""
    sys_product=""
    sys_ver=""
  fi
  if grep -qa docker /proc/1/cgroup; then
    virt="Docker"
  elif grep -qa lxc /proc/1/cgroup; then
    virt="LXC"
  elif grep -qa container=lxc /proc/1/environ; then
    virt="LXC"
  elif [[ -f /proc/user_beancounters ]]; then
    virt="OpenVZ"
  elif [[ ${virtual_x} == *kvm-clock*   ]]; then
    virt="KVM"
  elif [[ ${sys_product} == *KVM*   ]]; then
    virt="KVM"
  elif [[ ${cpu_name} == *KVM*   ]]; then
    virt="KVM"
  elif [[ ${cpu_name} == *QEMU*   ]]; then
    virt="KVM"
  elif [[ ${virtual_x} == *"VMware Virtual Platform"*   ]]; then
    virt="VMware"
  elif [[ ${sys_product} == *"VMware Virtual Platform"*   ]]; then
    virt="VMware"
  elif [[ ${virtual_x} == *"Parallels Software International"*   ]]; then
    virt="Parallels"
  elif [[ ${virtual_x} == *VirtualBox*   ]]; then
    virt="VirtualBox"
  elif [[ -e /proc/xen ]]; then
    if grep -q "control_d" "/proc/xen/capabilities" 2>/dev/null; then
      virt="Xen-Dom0"
    else
      virt="Xen-DomU"
    fi
  elif [ -f "/sys/hypervisor/type" ] && grep -q "xen" "/sys/hypervisor/type"; then
    virt="Xen"
  elif [[ ${sys_manu} == *"Microsoft Corporation"*   ]]; then
    if [[ ${sys_product} == *"Virtual Machine"*   ]]; then
      if [[ ${sys_ver} == *"7.0"* || ${sys_ver} == *"Hyper-V"     ]]; then
        virt="Hyper-V"
      else
        virt="Microsoft Virtual Machine"
      fi
    fi
  else
    virt="Dedicated"
  fi

  FunctionEnd

}
#######################################
# description
# Globals:
#   manage_port
#   tmp_manage_ports
# Arguments:
#  None
#######################################
get_manage_port() {

  FunctionStart "开始收集服务器 管理端口 信息！"
  local tmp_manage_ports
  tmp_manage_ports=$(netstat -ntulp | grep sshd | grep -w tcp | grep -v "127.0.0.1" | awk '{print$4}' | cut -d":" -f2)

  manage_port=$(echo "$tmp_manage_ports" | tr '\n' ' ')

  log "manage Port is => $manage_port"

  FunctionEnd

}

#######################################
# description
# Globals:
#   city
#   country
#   net_provider
#   public_ipv4
#   region
# Arguments:
#  None
#######################################
get_ipv4_info() {

  FunctionStart "开始收集服务器IP信息！"

  # public ip info
  net_provider="$(wget -q --timeout=2 -O- ipinfo.io/org)"
  city="$(wget -q --timeout=2 -O- ipinfo.io/city)"
  country="$(wget -q --timeout=2 -O- ipinfo.io/country)"
  region="$(wget -q --timeout=2 -O- ipinfo.io/region)"
  public_ipv4="$(wget -q --timeout=2 -O- ipinfo.io/ip)"
  public_ipv6="$(curl -q --max-time 2 -6 https://ifconfig.co/ip)"

  if [[ $city -eq "" ]]; then
      city="Chengdu"
  fi

  if [[ $country -eq "" ]]; then
      country="CN"
  fi

  if [[ $region -eq "" ]]; then
      region="Shuangliu"
  fi

  if [ -z "$public_ipv4" ]; then
    public_ipv4=" "
  fi

  if [ -z "$public_ipv6" ]; then
    public_ipv6=" "
  fi

  # inner ipinfo
  local interface_prefix=("eth[0-9]{1,2}" "ens[0-9]{1,3}" "eno[0-9]{1,3}" "enp[0-9]{1,2}" "enp[0-9]{1,2}s[0-9]{1,2}")
  local real_interface="eth90"

  local interface

  if command_exists ifconfig; then
      log "使用ifconfig检测内部IP地址信息！"
      for interface in "${interface_prefix[@]}"; do
        if ifconfig | grep -oqE "${interface}:"; then
          real_interface=$(ifconfig | grep -E "${interface}:" | cut -d ":" -f1)
          break
        fi
      done
  else
    log "使用 ip link show检测内部IP地址信息！"
    for interface in "${interface_prefix[@]}"; do
        if ip link show | grep -oqE "${interface}:"; then
          real_interface=$(ip link show | grep -oE "${interface}:" | head -1 | cut -d" " -f2)
          break
        fi
      done
  fi
  echo "当前主机的真实内网网卡为 => [$real_interface]"

  # 提取IPv4地址（CIDR格式）
  local ipv4_regex="inet[[:space:]](25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/[0-9]{1,2}"

  # 提取IPv6地址（CIDR格式）
  local ipv6_regex="inet6[[:space:]]([0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7})\/[0-9]{1,3}"

  # 查找IPv4地址
  inner_ipv4=$(ip addr show "$real_interface" | grep -oE "$ipv4_regex" | grep -v 127 | cut -d" " -f2)
  echo "Interface: $real_interface, IPv4 Address: $inner_ipv4"

   # 查找IPv6地址
  inner_ipv6=$(ip addr show "$real_interface" | grep -oE "$ipv6_regex" | grep -v "::1" | cut -d" " -f2)
  echo "Interface: $real_interface, IPv4 Address: $inner_ipv6"

  FunctionEnd

}

#######################################
# description
# Globals:
#   LANG
#   arch
#   c_cache
#   cores
#   cpu_aes
#   cpu_name
#   cpu_virt
#   disk_total_size
#   disk_used_size
#   cpu_freq
#   kernel_info
#   lbit
#   load
#   os_info
#   swap
#   tcp_ctrl
#   mem_total
#   unused_ram
#   unused_swap
#   up
# Arguments:
#  None
#######################################
collect_system_info() {
  FunctionStart "开始收集系统信息！"

  check_sys

  cpu_name=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
  cores=$(awk -F: '/processor/ {core++} END {print core}' /proc/cpuinfo)
  cpu_freq=$(awk -F'[ :]' '/cpu MHz/ {print $4;exit}' /proc/cpuinfo)
  local c_cache
  local cpu_aes
  local cpu_virt
  c_cache=$(awk -F: '/cache size/ {cache=$2} END {print cache}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
  cpu_aes=$(grep -i 'aes' /proc/cpuinfo)
  cpu_virt=$(grep -Ei 'vmx|svm' /proc/cpuinfo)
  mem_total=$(
    LANG=C
    free | awk '/Mem/ {print $2}'
  )
  mem_total=$(calc_size "$mem_total")
  local unused_ram
  unused_ram=$(
    LANG=C
    free | awk '/Mem/ {print $3}'
  )
  unused_ram=$(calc_size "$unused_ram")
  local swap
  swap=$(
    LANG=C
    free | awk '/Swap/ {print $2}'
  )
  swap=$(calc_size "$swap")
  local unused_swap
  unused_swap=$(
    LANG=C
    free | awk '/Swap/ {print $3}'
  )
  unused_swap=$(calc_size "$unused_swap")
  local up
  up=$(awk '{a=$1/86400;b=($1%86400)/3600;c=($1%3600)/60} {printf("%d days, %d hour %d min\n",a,b,c)}' /proc/uptime)
  local load
  if command_exists "w"; then
    load=$(
      LANG=C
      w | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//'
    )
  elif command_exists "uptime"; then
    load=$(
      LANG=C
      uptime | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//'
    )
  fi
  os_info=$(get_host_arch_info | tr "\n" " ")
  arch=$(uname -m)
  local l_bit
  if command_exists "getconf"; then
    l_bit=$(getconf LONG_BIT)
  else
    echo "${arch}" | grep -q "64" && l_bit="64" || l_bit="32"
  fi
  kernel_info=$(uname -r)
  disk_total_size=$(
    LANG=C
    df -t simfs -t ext2 -t ext3 -t ext4 -t btrfs -t xfs -t vfat -t ntfs -t swap --total 2>/dev/null | grep total | awk '{ print $2 }'
  )
  disk_total_size=$(calc_size "$disk_total_size")
  disk_used_size=$(
    LANG=C
    df -t simfs -t ext2 -t ext3 -t ext4 -t btrfs -t xfs -t vfat -t ntfs -t swap --total 2>/dev/null | grep total | awk '{ print $3 }'
  )
  disk_used_size=$(calc_size "$disk_used_size")
  tcp_ctrl=$(sysctl net.ipv4.tcp_congestion_control | awk -F ' ' '{print $3}')

  if [[ $(cut -d"-" -f 3 </etc/hostname | grep -c '^[0-9][0-9]') -gt 0 ]]; then
    machine_number=$(cut -d"-" -f 3 </etc/hostname)
  else
    machine_number=99
  fi

   FunctionEnd
}

#######################################
# description
# Arguments:
#  None
#######################################

#######################################
# description
# Globals:
#   agent_version
#   octopus_agent_path
# Arguments:
#  None
#######################################
get_agent_version() {
  FunctionStart "获取Agent的版本信息"

  local file
  for file in "${octopus_agent_path}"/*; do
    if [[ ! -d ${file} ]]; then
      if echo "$file" | grep "octopus-agent_linux_amd64_"; then
         agent_version=$(echo "${file}" | cut -d "_" -f4-)
         break
      fi
    fi
  done

  if [[ $agent_version -eq "" ]]; then
      agent_version=2011-11-11-11-11-11
  fi

  log "获取到的Agent版本信息为 => ${agent_version}"

  FunctionEnd
}

#######################################
# description
# Globals:
#   agent_server_info_file
#   arch
#   city
#   cores
#   country
#   cpu_name
#   disk_total_size
#   disk_used_size
#   cpu_freq
#   cpu_arch
#   inner_ipv4
#   inner_ipv6
#   io_speed
#   kernel_info
#   lbit
#   machine_number
#   manage_port
#   os_info
#   net_provider
#   public_ipv4
#   public_ipv6
#   region
#   tcp_ctrl
#   mem_total
#   virt
# Arguments:
#  None
#######################################
main() {
  # todo
  #  start_iotest

  check_sys

  get_manage_port

  collect_system_info

  get_ipv4_info

  check_virtualization

  get_agent_version

  local agent_server_info_file="$octopus_agent_path/octopus-agent-back.conf"

  touch "$agent_server_info_file"
  cat >"$agent_server_info_file" <<EOF
serverName: "${city}-${cpu_arch}-${machine_number}"
serverIpPbV4: "$public_ipv4"
serverIpInV4: "$inner_ipv4"
serverIpPbV6: "$public_ipv6"
serverIpInV6: "$inner_ipv6"
location: "$city $region $country"
provider: "$net_provider"
managePort: "$manage_port"
cpuCore: "$cores @ $cpu_freq MHz"
cpuBrand: "$cpu_name"
memoryTotal: "$mem_total"
diskTotal: "$disk_total_size"
diskUsage: "$disk_used_size"
archInfo: "$arch ($os_bit Bit)"
osInfo: "$os_info"
osKernelInfo: "$kernel_info"
tcpControl: "$tcp_ctrl"
virtualization: "$virt"
ioSpeed: "$io_speed MB/s"
machineId: "$(cat /etc/machine-id)"
agentVersion: "${agent_version}"
EOF

  log "agent server info has collect complete!"
  log "file is => $agent_server_info_file"
  echo ""

  SplitGreen "查看Agent的环境信息！"
  cat - 1>&2  <<EOF

      cat $agent_server_info_file

EOF
}

main
