#!/bin/bash
# ============================================================================
# Sun HPC 系统初始化脚本
# 功能：系统安装完成后自动配置 HPC 计算节点环境
# 版本：1.0
# ============================================================================

set -e

# ============================================================================
# 配置变量（根据实际环境修改）
# ============================================================================

# 日志文件
LOG_FILE="/var/log/sunhpc-init.log"

FRONTEND_IP='@osipaddr@'

# HTTP 服务器地址
HTTP_SERVER="http://${FRONTEND_IP}"

# YUM 仓库配置
YUM_REPO_NAME="sunhpc-local"
YUM_REPO_BASEURL="${HTTP_SERVER}/@ospath@"
YUM_REPO_GPGCHECK=0

# 主机名映射文件（在 HTTP 服务器上）
HOSTNAME_MAP_URL="${HTTP_SERVER}/ks/hostname-map.txt"

# MOTD 文件 URL
MOTD_URL="${HTTP_SERVER}/ks/motd"

# NTP 服务器
NTP_SERVER="ntp.aliyun.com"

# DNS 服务器
DNS_SERVERS="114.114.114.114 223.5.5.5"

# ============================================================================
# 颜色输出函数
# ============================================================================

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

# ============================================================================
# 基础环境准备
# ============================================================================

init_log() {
    # 创建日志文件
    touch $LOG_FILE
    chmod 644 $LOG_FILE
    log_info "=========================================="
    log_info "Sun HPC Node Initialization Started"
    log_info "=========================================="
}

check_network() {
    log_step "Checking network connectivity..."
    
    # 测试网络连接
    if ping -c 1 -W 3 FRONTEND_IP &>/dev/null; then
        log_info "Network connectivity: OK"
        return 0
    else
        log_warn "Cannot reach HTTP server, will retry later"
        return 1
    fi
}

# ============================================================================
# 1. 创建 .sunhpc-release 文件
# ============================================================================

create_release_file() {
    log_step "Creating .sunhpc-release file..."
    
    cat > /.sunhpc-release << EOF
Sun HPC Platform Release 1.0
Build Date: $(date '+%Y-%m-%d %H:%M:%S')
Hostname: $(hostname)
Kernel: $(uname -r)
Architecture: $(uname -m)
EOF
    
    chmod 644 /.sunhpc-release
    log_info "Created /.sunhpc-release file"
}

# ============================================================================
# 2. 配置主机名和 /etc/hosts
# ============================================================================

configure_hostname() {
    log_step "Configuring hostname and /etc/hosts..."
    
    local mac=$(ip link show | grep -oP 'ether \K[0-9a-f:]+' | head -1 | tr '[:upper:]' '[:lower:]')
    local hostname=""
    
    # 从 HTTP 服务器获取主机名映射
    if check_network; then
        # 下载主机名映射文件
        local map_file="/tmp/hostname-map.txt"
        curl -s -o "$map_file" "$HOSTNAME_MAP_URL" 2>/dev/null
        
        if [[ -f "$map_file" ]]; then
            # 根据 MAC 地址查找主机名
            hostname=$(grep -i "$mac" "$map_file" | awk '{print $2}' | head -1)
            
            # 如果没有找到，根据 IP 最后一段生成
            if [[ -z "$hostname" ]]; then
                local ip_addr=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
                local ip_last=$(echo $ip_addr | awk -F'.' '{print $4}')
                hostname="cn$(printf "%03d" $ip_last)"
                log_warn "No hostname mapping for MAC $mac, using generated: $hostname"
            fi
        else
            log_warn "Cannot download hostname map, using default"
            local ip_addr=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
            local ip_last=$(echo $ip_addr | awk -F'.' '{print $4}')
            hostname="cn$(printf "%03d" $ip_last)"
        fi
    else
        # 网络不通时使用默认主机名
        hostname="node-$(hostname -s)"
    fi
    
    # 设置主机名
    hostnamectl set-hostname "$hostname"
    log_info "Hostname set to: $hostname"
    
    # 备份原始 hosts 文件
    cp /etc/hosts /etc/hosts.bak.$(date +%Y%m%d)
    
    # 构建新的 hosts 文件
    cat > /etc/hosts << EOF
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

# Sun HPC Node Configuration
$ip_addr   $hostname

# Management Node
$FRONTEND_IP   cluster

# Optional: Add other compute nodes here
EOF
    
    # 尝试下载完整的集群 hosts 文件
    if check_network; then
        local cluster_hosts="${HTTP_SERVER}/ks/cluster-hosts.txt"
        if wget --spider -q "$cluster_hosts" 2>/dev/null; then
            wget -q -O /tmp/cluster-hosts.txt "$cluster_hosts"
            cat /tmp/cluster-hosts.txt >> /etc/hosts
            log_info "Downloaded cluster hosts configuration"
        else
            log_warn "$cluster_hosts not found on server."
        fi
    fi
    
    log_info "Updated /etc/hosts"
}

# ============================================================================
# 3. 配置 MOTD (Message of The Day)
# ============================================================================

configure_motd() {
    log_step "Configuring MOTD..."
    
    # 备份原始 MOTD
    if [[ -f /etc/motd ]]; then
        cp /etc/motd /etc/motd.bak.$(date +%Y%m%d)
    fi
    
    # 尝试从服务器下载 MOTD
    if check_network; then
        if wget --spider -q "$MOTD_URL" 2>/dev/null; then
            wget -q -O /etc/motd "$MOTD_URL"
            log_info "Downloaded MOTD from server"
        else
            log_warn "Cannot download MOTD, creating default"
            create_default_motd
        fi
    else
        create_default_motd
    fi
    
    chmod 644 /etc/motd
}

create_default_motd() {
    cat > /etc/motd << EOF
===========================================================
    Sun HPC Platform - Compute Node
===========================================================
  Welcome to Sun High Performance Computing Cluster

  System Information:
  --------------------
  Hostname....: $(hostname)
  IP Address..: $(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
  OS Version..: $(cat /etc/redhat-release 2>/dev/null || echo "Rocky Linux")
  Kernel......: $(uname -r)
  Architecture: $(uname -m)
  CPU Cores...: $(nproc)
  Memory......: $(free -h | awk '/^Mem:/{print $2}')

  Important URLs:
  --------------------
  • Documentation    : http://172.16.9.254/docs
  • Job Submission   : http://172.16.9.254/slurm
  • Monitoring: http : http://172.16.9.254/monitor

  Slurm Commands:
  --------------------
  sinfo        - View partition information
  squeue       - View job queue
  srun         - Run interactive job
  sbatch       - Submit batch job
  scancel      - Cancel job

===========================================================
  * Unauthorized access is prohibited
  * All activities are logged and monitored
  * For support: hpc@sun.com or ext. 12345
===========================================================
EOF
}

# ============================================================================
# 4. 配置 YUM 本地仓库
# ============================================================================

configure_yum_repo() {
    log_step "Configuring YUM repository..."
    
    local repo_file="/etc/yum.repos.d/${YUM_REPO_NAME}.repo"
    
    # 备份现有 repo 文件
    if [[ -f "$repo_file" ]]; then
        cp "$repo_file" "${repo_file}.bak.$(date +%Y%m%d)"
    fi
    
    # 创建仓库配置文件
    cat > "$repo_file" << EOF
[${YUM_REPO_NAME}]
name=Sun HPC Local Repository
baseurl=${YUM_REPO_BASEURL}
enabled=1
gpgcheck=${YUM_REPO_GPGCHECK}
priority=1
EOF

    # 如果是 Rocky 8/9，可能需要配置 appstream
    if [[ -d "/etc/yum.repos.d" ]]; then
        local appstream_repo="/etc/yum.repos.d/${YUM_REPO_NAME}-appstream.repo"
        cat > "$appstream_repo" << EOF
[${YUM_REPO_NAME}-appstream]
name=Sun HPC Local AppStream Repository
baseurl=${YUM_REPO_BASEURL}-appstream
enabled=1
gpgcheck=${YUM_REPO_GPGCHECK}
priority=1
EOF
    fi
    
    # 清理 YUM 缓存并测试
    yum clean all &>/dev/null
    yum makecache &>/dev/null
    
    if [[ $? -eq 0 ]]; then
        log_info "YUM repository configured successfully"
    else
        log_warn "YUM repository configured but cache generation failed (network may be down)"
    fi
    
    # 显示启用的仓库
    log_info "Enabled repositories:"
    yum repolist 2>/dev/null | grep -E "^${YUM_REPO_NAME}" | tee -a $LOG_FILE
}

# ============================================================================
# 5. 配置 DNS 解析
# ============================================================================

configure_dns() {
    log_step "Configuring DNS resolution..."
    
    # 备份 resolv.conf
    cp /etc/resolv.conf /etc/resolv.conf.bak.$(date +%Y%m%d) 2>/dev/null || true
    
    # 配置 DNS
    cat > /etc/resolv.conf << EOF
# Sun HPC DNS Configuration
nameserver ${DNS_SERVERS%% *}
$(for dns in ${DNS_SERVERS}; do echo "nameserver $dns"; done | tail -n +2)

# Local domain
search sunhpc.local local
EOF
    
    # 防止 NetworkManager 覆盖 resolv.conf
    if [[ -f /etc/NetworkManager/NetworkManager.conf ]]; then
        if ! grep -q "dns=none" /etc/NetworkManager/NetworkManager.conf; then
            sed -i '/^\[main\]/a dns=none' /etc/NetworkManager/NetworkManager.conf
            systemctl restart NetworkManager 2>/dev/null || true
        fi
    fi
    
    log_info "DNS configured: ${DNS_SERVERS}"
}

# ============================================================================
# 6. 配置 NTP 时间同步
# ============================================================================

configure_ntp() {
    log_step "Configuring NTP time synchronization..."
    
    # 使用 chrony (Rocky 8/9 默认)
    if command -v chronyd &>/dev/null; then
        # 备份配置
        cp /etc/chrony.conf /etc/chrony.conf.bak.$(date +%Y%m%d)
        
        # 配置 chrony
        cat > /etc/chrony.conf << EOF
# Sun HPC NTP Configuration
server ${NTP_SERVER} iburst
pool 2.rocky.pool.ntp.org iburst

# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift

# Allow the system clock to be stepped in the first three updates
makestep 1.0 3

# Enable kernel synchronization of the real-time clock (RTC)
rtcsync

# Specify file containing keys for NTP authentication
keyfile /etc/chrony.keys

# Specify directory for log files
logdir /var/log/chrony
EOF
        
        # 重启 chrony
        systemctl restart chronyd &>/dev/null
        systemctl enable chronyd &>/dev/null
        
        log_info "Chrony NTP configured with server: ${NTP_SERVER}"
    else
        # 使用 ntpd (旧系统)
        if command -v ntpd &>/dev/null; then
            cat > /etc/ntp.conf << EOF
server ${NTP_SERVER} iburst
restrict default nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict ::1
driftfile /var/lib/ntp/drift
EOF
            systemctl restart ntpd &>/dev/null
            systemctl enable ntpd &>/dev/null
            log_info "NTP configured with server: ${NTP_SERVER}"
        else
            log_warn "No NTP service found (chronyd or ntpd)"
        fi
    fi
}

# ============================================================================
# 7. 配置 SSH 服务
# ============================================================================

configure_ssh() {
    log_step "Configuring SSH service..."
    
    # 备份配置
    cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
    
    # 优化 SSH 配置
    sed -i 's/#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
    sed -i 's/#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
    sed -i 's/#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
    sed -i 's/#UseDNS.*/UseDNS no/' /etc/ssh/sshd_config
    sed -i 's/#GSSAPIAuthentication.*/GSSAPIAuthentication no/' /etc/ssh/sshd_config
    
    # 重启 SSH 服务
    systemctl restart sshd &>/dev/null
    
    log_info "SSH service configured"
}

# ============================================================================
# 8. 配置防火墙
# ============================================================================

configure_firewall() {
    log_step "Configuring firewall..."
    
    # 检查 firewalld 是否运行
    if systemctl is-active firewalld &>/dev/null; then
        # 开放常用端口
        firewall-cmd --permanent --add-service=ssh &>/dev/null
        firewall-cmd --permanent --add-service=dhcp &>/dev/null
        firewall-cmd --permanent --add-port=873/tcp &>/dev/null  # rsync
        firewall-cmd --permanent --add-port=111/udp &>/dev/null  # rpcbind
        
        # 重新加载
        firewall-cmd --reload &>/dev/null
        
        log_info "Firewall configured"
    else
        log_warn "Firewalld not running, skipping configuration"
    fi
}

# ============================================================================
# 9. 安装常用软件包
# ============================================================================

install_packages() {
    log_step "Installing common packages..."
    
    local packages=(
        wget curl vim nano
        htop iotop iftop
        net-tools bind-utils
        telnet nc tcpdump
        rsync tree lsof
        gcc make autoconf automake
        openssl-devel zlib-devel
        nfs-utils cifs-utils
        ntpdate
    )
    
    if check_network; then
        for pkg in "${packages[@]}"; do
            if rpm -q "$pkg" &>/dev/null; then
                log_info "Package already installed: $pkg"
            else
                log_info "Installing package: $pkg"
                yum install -y "$pkg" &>> $LOG_FILE || log_warn "Failed to install: $pkg"
            fi
        done
    else
        log_warn "Network unavailable, skipping package installation"
    fi
}

# ============================================================================
# 11. 配置用户环境
# ============================================================================

configure_user_env() {
    log_step "Configuring user environment..."
    
    # 创建共享目录
    mkdir -p /share/{apps,home}
    mkdir -p /state/partition1/{tmp,work}
    
    # 设置权限
    chmod 755 /share
    chmod 1777 /state/partition1/tmp
    
    # 配置全局环境变量
    cat > /etc/profile.d/sunhpc.sh << 'EOF'
# Sun HPC Environment Variables
export SHARE_HOME=/share
export STATE_HOME=/state/partition1
EOF
    
    chmod 644 /etc/profile.d/sunhpc.sh
    log_info "User environment configured"
}

# ============================================================================
# 12. 配置系统优化参数
# ============================================================================

configure_sysctl() {
    log_step "Configuring system optimization..."
    
    cat > /etc/sysctl.d/99-sunhpc.conf << EOF
# Sun HPC System Optimization

# Network optimization
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_sack = 1
net.ipv4.tcp_timestamps = 1

# Memory optimization
vm.swappiness = 10
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50

# File system
fs.file-max = 1048576
fs.inotify.max_user_watches = 1048576

# Process scheduler
kernel.sched_autogroup_enabled = 0
kernel.sched_migration_cost_ns = 5000000
EOF
    
    sysctl -p /etc/sysctl.d/99-sunhpc.conf &>/dev/null
    log_info "System optimization configured"
}

# ============================================================================
# 13. 配置系统限制
# ============================================================================

configure_limits() {
    log_step "Configuring system limits..."
    
    cat > /etc/security/limits.d/99-sunhpc.conf << EOF
# Sun HPC System Limits
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 131072
* hard nproc 131072
* soft memlock unlimited
* hard memlock unlimited
root soft nofile 1048576
root hard nofile 1048576
EOF
    
    log_info "System limits configured"
}

# ============================================================================
# 14. 配置定时任务
# ============================================================================

configure_crontab() {
    log_step "Configuring cron jobs..."
    
    cat > /etc/cron.d/sunhpc << EOF
# Sun HPC Cron Jobs

# Sync time every hour
0 * * * * root /usr/sbin/chronyc -a makestep &>/dev/null

# Clean old logs daily
0 2 * * * root find /var/log -name "*.log" -mtime +30 -delete 2>/dev/null

# Report node status every 5 minutes
*/5 * * * * root /usr/local/bin/node-status-report &>/dev/null
EOF
    
    chmod 644 /etc/cron.d/sunhpc
    log_info "Cron jobs configured"
}

# ============================================================================
# 15. 创建节点状态上报脚本
# ============================================================================

create_report_script() {
    log_step "Creating node status report script..."
    
    cat > /usr/local/bin/node-status-report << 'EOF'
#!/bin/bash
# Node status report script for Sun HPC

HTTP_SERVER="http://172.16.9.254"
NODE_NAME=$(hostname)
IP_ADDR=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
LOAD_AVG=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1)
MEM_TOTAL=$(free -g | awk '/^Mem:/{print $2}')
MEM_USED=$(free -g | awk '/^Mem:/{print $3}')
DISK_USED=$(df -h / | awk 'NR==2{print $5}' | sed 's/%//')
SLURM_STATUS=$(systemctl is-active slurm-slurmd 2>/dev/null || echo "unknown")

# Build status JSON
STATUS_JSON="{\"node\":\"$NODE_NAME\",\"ip\":\"$IP_ADDR\",\"load\":$LOAD_AVG,\"mem_total\":$MEM_TOTAL,\"mem_used\":$MEM_USED,\"disk_used\":$DISK_USED,\"slurm\":\"$SLURM_STATUS\",\"timestamp\":\"$(date -Iseconds)\"}"

# Send to management node
curl -s -X POST -H "Content-Type: application/json" -d "$STATUS_JSON" ${HTTP_SERVER}/api/node-status &>/dev/null
EOF
    
    chmod +x /usr/local/bin/node-status-report
    log_info "Node status report script created"
}

# ============================================================================
# 16. 配置日志轮转
# ============================================================================

configure_logrotate() {
    log_step "Configuring log rotation..."
    
    cat > /etc/logrotate.d/sunhpc << EOF
/var/log/sunhpc-init.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 root root
}
EOF
    
    log_info "Log rotation configured"
}

# ============================================================================
# 17. 清理临时文件
# ============================================================================

cleanup() {
    log_step "Cleaning up temporary files..."
    
    # 删除临时文件
    rm -f /tmp/hostname-map.txt 2>/dev/null
    rm -f /tmp/cluster-hosts.txt 2>/dev/null
    
    # 清除 YUM 缓存
    yum clean all &>/dev/null
    
    log_info "Cleanup completed"
}

# ============================================================================
# 18. 生成初始化完成报告
# ============================================================================

generate_report() {
    log_step "Generating initialization report..."
    
    cat > /root/init-report.txt << EOF
===========================================
Sun HPC Node Initialization Report
===========================================
Init Time: $(date '+%Y-%m-%d %H:%M:%S')
Hostname: $(hostname)
IP Address: $(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
MAC Address: $(ip link show | grep -oP 'ether \K[0-9a-f:]+' | head -1)

Services Status:
- NetworkManager: $(systemctl is-active NetworkManager)
- chronyd: $(systemctl is-active chronyd 2>/dev/null || echo "stopped")
- sshd: $(systemctl is-active sshd)
- slurm-slurmd: $(systemctl is-active slurm-slurmd 2>/dev/null || echo "stopped")
- firewalld: $(systemctl is-active firewalld)

YUM Repositories:
$(yum repolist)

Files Created:
- /.sunhpc-release
- /etc/hosts (updated)
- /etc/motd (updated)
- /etc/yum.repos.d/sunhpc-local.repo
- /etc/chrony.conf (updated)
- /etc/security/limits.d/99-sunhpc.conf
- /etc/sysctl.d/99-sunhpc.conf

===========================================
EOF
    
    cat /root/init-report.txt >> $LOG_FILE
    log_info "Initialization report saved to /root/init-report.txt"
}

# ============================================================================
# 主函数
# ============================================================================

main() {
    log_info "Starting Sun HPC node initialization..."
    
    # 执行所有初始化步骤
    init_log
    check_network
    create_release_file
    configure_hostname
    configure_motd
    configure_yum_repo
    configure_dns
    configure_ntp
    configure_ssh
    configure_firewall
    install_packages
    configure_slurm
    configure_user_env
    configure_sysctl
    configure_limits
    configure_crontab
    create_report_script
    configure_logrotate
    cleanup
    generate_report
    
    log_info "=========================================="
    log_info "Sun HPC node initialization completed!"
    log_info "=========================================="
    
    # 显示关键信息
    echo ""
    echo -e "${GREEN}=== Initialization Complete ===${NC}"
    echo -e "Hostname: $(hostname)"
    echo -e "Release file: $(cat /.sunhpc-release | head -1)"
    echo -e "Log file: $LOG_FILE"
    echo -e "Report: /root/init-report.txt"
    echo ""
}

# ============================================================================
# 脚本入口
# ============================================================================

# 检查是否需要重启
if [[ "$1" == "--reboot" ]]; then
    main
    log_info "Rebooting in 5 seconds..."
    sleep 5
    reboot
else
    main
    log_info "Initialization completed. You may reboot if needed."
fi
