guanghulab/scripts/pool/join-pool.sh

150 lines
7.9 KiB
Bash

#!/bin/bash
# join-pool.sh · 光湖节点池快速加入工具 v1.0
# 铸渊共享节点池 · TCS-0002∞ · ICE-GL-ZY001
# 用法: bash join-pool.sh --token <token> --team awen --operator "Awen"
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/pool-utils.sh"
ZHUYUAN_BASE="${ZHUYUAN_BASE:-/opt/zhuyuan}"
CONSOLE_URL="${CONSOLE_URL:-https://43.156.237.110:3920}"
MODE=""; JOIN_TOKEN=""; TEAM_ID=""; OPERATOR_NAME=""; NON_INTERACTIVE=false; ROLLBACK_NODE=""; RESUME_REG_ID=""
while [[ $# -gt 0 ]]; do
case "$1" in
--token) JOIN_TOKEN="$2"; shift 2;; --team) TEAM_ID="$2"; shift 2;; --operator) OPERATOR_NAME="$2"; shift 2;;
--non-interactive) NON_INTERACTIVE=true; shift;; --rollback) MODE="rollback"; ROLLBACK_NODE="$2"; shift 2;;
--status) MODE="status"; shift;; --inspect) MODE="inspect"; shift;; --resume) MODE="resume"; RESUME_REG_ID="$2"; shift 2;;
--help|-h) echo "光湖节点池加入工具 v1.0"; echo "用法: bash join-pool.sh --token <令牌> --team <团队> --operator <操作人>"; exit 0;;
*) echo "未知参数: $1"; exit 1;;
esac
done
[[ -z "$MODE" ]] && MODE="join"
# ---- 回滚 ----
if [[ "$MODE" == "rollback" ]]; then
check_root; [[ -z "$ROLLBACK_NODE" ]] && { log_err "缺少节点编码"; exit 1; }
local t=""; case "${ROLLBACK_NODE:0:2}" in AW) t="awen";; FM) t="feimao";; JZ) t="juzi";; YF) t="yanfan";; YY) t="yeye";; ZZ) t="zhizhi";; esac
do_rollback "$ROLLBACK_NODE" "$t"; exit 0
fi
# ---- 状态 ----
if [[ "$MODE" == "status" ]]; then
echo -e "\n${C_BOLD}节点池状态${C_RESET}\n"
local f=0
for conf in "${ZHUYUAN_BASE}"/team/*/.pool-conf.json "${ZHUYUAN_BASE}"/ice/.pool-conf.json; do
[[ -f "$conf" ]] || continue; f=1
local nc=$(grep -o '"node_code"[^,]*' "$conf" | head -1 | grep -o '"[^"]*"$' | tr -d '"')
local s=$(grep -o '"side"[^,]*' "$conf" | head -1 | grep -o '"[^"]*"$' | tr -d '"')
echo " 节点: ${C_BOLD}${nc}${C_RESET} | 侧: ${s} | 配置: $conf"
done
[[ $f -eq 0 ]] && echo -e " ${C_DIM}未加入节点池${C_RESET}"
echo ""; exit 0
fi
# ---- 硬件检查 ----
if [[ "$MODE" == "inspect" ]]; then
print_header; log_step "1" "1" "硬件信息采集"; echo ""
local hw=$(collect_hardware)
local cpu=$(echo "$hw" | grep -o '"cpu_cores":[0-9]*' | grep -o '[0-9]*$' || echo "?")
local mem=$(echo "$hw" | grep -o '"memory_mb":[0-9]*' | grep -o '[0-9]*$' || echo "?")
local disk=$(echo "$hw" | grep -o '"disk_gb":[0-9]*' | grep -o '[0-9]*$' || echo "?")
local os=$(echo "$hw" | grep -o '"os":"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "?")
echo " CPU: ${cpu}核 | 内存: ${mem}MB ($((mem/1024))GB) | 磁盘: ${disk}GB | 系统: ${os}"
[[ -n "$TEAM_ID" ]] && echo " 推荐编码: ${C_BOLD}${C_CYAN}$(generate_node_code "$TEAM_ID")${C_RESET}"
echo ""; exit 0
fi
# ---- 恢复 ----
if [[ "$MODE" == "resume" ]]; then
check_root; await_approval "$RESUME_REG_ID"; exit 0
fi
# ========== 主流程: 标准加入 ==========
main_join() {
print_header; check_root
# 步骤1: 确认环境
log_step "1" "7" "确认环境"; echo ""
local hw=$(collect_hardware)
local hostname=$(echo "$hw" | grep -o '"hostname":"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "?")
local pub_ip=$(echo "$hw" | grep -o '"public_ip":"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "?")
local cpu=$(echo "$hw" | grep -o '"cpu_cores":[0-9]*' | grep -o '[0-9]*$' || echo "?")
local mem=$(echo "$hw" | grep -o '"memory_mb":[0-9]*' | grep -o '[0-9]*$' || echo "?")
local disk=$(echo "$hw" | grep -o '"disk_gb":[0-9]*' | grep -o '[0-9]*$' || echo "?")
local os=$(echo "$hw" | grep -o '"os":"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "?")
echo " 主机名: ${C_BOLD}${hostname}${C_RESET} | 公网IP: ${pub_ip}"
echo " CPU: ${cpu}核 | 内存: ${mem}MB ($((mem/1024))GB) | 磁盘: ${disk}GB"
echo ""
detect_existing_zhuanyuan
if [[ "$NON_INTERACTIVE" != "true" ]]; then
echo -n "这是你要加入节点池的服务器吗?[y/N] "; read confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { log_err "已取消"; exit 1; }
fi; log_ok "环境确认完成"; echo ""
# 步骤2: 凭证
log_step "2" "7" "输入加入凭证"; echo ""
[[ -z "$JOIN_TOKEN" ]] && { echo -n "加入令牌: "; read -rs JOIN_TOKEN; echo ""; }
[[ -z "$JOIN_TOKEN" ]] && { log_err "令牌不能为空"; exit 1; }
[[ -z "$TEAM_ID" ]] && { echo -n "团队标识: "; read -r TEAM_ID; }
[[ -z "$OPERATOR_NAME" ]] && { echo -n "操作人: "; read -r OPERATOR_NAME; }
check_already_registered "$TEAM_ID"
local node_code=$(generate_node_code "$TEAM_ID")
log_ok "团队: ${TEAM_ID} · 节点编码: ${C_BOLD}${node_code}${C_RESET}"; echo ""
# 步骤3: 创建目录
log_step "3" "7" "创建目录结构"; echo ""
local team_dir="${ZHUYUAN_BASE}/team/${TEAM_ID}"
mkdir -p "${team_dir}/logs/pm2" "${team_dir}/apps" "${team_dir}/data" "${team_dir}/nginx"
log_ok "${team_dir}/"; [[ ! -d "${ZHUYUAN_BASE}/ice" ]] && { mkdir -p "${ZHUYUAN_BASE}/ice/logs" "${ZHUYUAN_BASE}/ice/apps" "${ZHUYUAN_BASE}/ice/data"; log_ok "${ZHUYUAN_BASE}/ice/ (冰朔侧预留)"; }
mkdir -p "${ZHUYUAN_BASE}/.rollback"; echo ""
# 步骤4: 注册
log_step "4" "7" "向中枢注册"; echo ""
test_connectivity "$CONSOLE_URL" || { log_err "无法连接中枢"; exit 1; }; log_ok "已连接中枢"
local join_body="{\"join_token\":\"${JOIN_TOKEN}\",\"node_code\":\"${node_code}\",\"node_name\":\"${OPERATOR_NAME}团队节点\",\"side\":\"team\",\"team_id\":\"${TEAM_ID}\",\"operator_name\":\"${OPERATOR_NAME}\",\"hardware\":{\"cpu_cores\":${cpu},\"memory_mb\":${mem},\"disk_gb\":${disk},\"os\":\"${os}\"},\"network\":{\"public_ip\":\"${pub_ip}\"}}"
local resp=$(pool_api_post "/api/pool/join" "$join_body" 15)
echo "$resp" | grep -q '"ok":[[:space:]]*true' || { log_err "注册失败: $resp"; exit 1; }
local registration_id=$(echo "$resp" | grep -o '"registration_id":"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"')
[[ -z "$registration_id" ]] && { log_err "未获取 registration_id"; exit 1; }
log_ok "注册请求已提交 · reg_id: ${registration_id}"
create_rollback_point "$node_code" > /dev/null; echo ""
# 步骤5: 等待审批
await_approval "$registration_id"
# 步骤6: 保存配置
log_step "6" "7" "保存配置"; echo ""
cat > "${team_dir}/.pool-conf.json" <<POOL
{"node_code":"${node_code}","side":"team","team_id":"${TEAM_ID}","pool_token":"${POOL_TOKEN}","report_endpoint":"${CONSOLE_URL}/api/pool/report","joined_at":"$(date -Iseconds)","operator_name":"${OPERATOR_NAME}","script_version":"1.0.0"}
POOL
chmod 600 "${team_dir}/.pool-conf.json"; log_ok "配置已保存"; echo ""
# 步骤7: 验证
log_step "7" "7" "验证连接"; echo ""
local hb="{\"node_code\":\"${node_code}\",\"cpu_load\":0,\"mem_total_mb\":${mem},\"mem_avail_mb\":${mem},\"spec\":{\"cpu\":${cpu},\"mem_gb\":$((mem/1024))},\"pool_token\":\"${POOL_TOKEN}\"}"
pool_api_post "/api/pool/report" "$hb" 10 | grep -q '"ok":true' && log_ok "心跳上报成功" || log_warn "心跳上报失败"
echo ""; echo -e "${C_GREEN}${C_BOLD} ✅ 节点加入完成!${C_RESET}"; echo " 节点编码: ${node_code} | 团队: ${TEAM_ID}"
echo " 路径: ${team_dir}/"; echo " 回滚: bash join-pool.sh --rollback ${node_code}"
echo ""
}
await_approval() {
local elapsed=0 poll_c=0
log_step "5" "7" "等待审批"
while [[ $elapsed -lt $POLL_TIMEOUT ]]; do
poll_c=$((poll_c+1))
local s=$(pool_api_get "/api/pool/join-status/${1}" 10)
if echo "$s" | grep -q '"status":[[:space:]]*"approved"'; then
POOL_TOKEN=$(echo "$s" | grep -o '"pool_token":"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"')
echo ""; echo -e "${C_GREEN}冰朔已批准!${C_RESET}"; echo ""; return 0
fi
echo "$s" | grep -q '"status":[[:space:]]*"rejected"' && { log_err "注册被拒绝"; exit 1; }
log_wait "等待冰朔审批... (${elapsed})"; sleep "$POLL_INTERVAL"; elapsed=$((elapsed+POLL_INTERVAL))
done
log_warn "等待超时"; echo "恢复码: ${1}"; exit 1
}
main_join; unset JOIN_TOKEN POOL_TOKEN