294 lines
10 KiB
Bash
Executable File
294 lines
10 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
TEST_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
REPO_ROOT="$(cd "$TEST_ROOT/../../.." && pwd)"
|
||
|
||
PRIVATE_CORE="$TEST_ROOT/private"
|
||
PRIVATE_NODEA="$TEST_ROOT/private-nodea"
|
||
PRIVATE_NODEB="$TEST_ROOT/private-nodeb"
|
||
TMP_DIR="$TEST_ROOT/tmp"
|
||
|
||
source "$REPO_ROOT/scripts/common/build_user.sh"
|
||
load_build_user
|
||
|
||
ensure_image() {
|
||
local image="$1"
|
||
if ! docker image inspect "$image" >/dev/null 2>&1; then
|
||
echo "[ERROR] Missing image: $image. Please run ./build/build_images.sh" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
echo "[INFO] Preparing directories..."
|
||
ensure_writable_dir() {
|
||
local path="$1"
|
||
local parent
|
||
parent="$(dirname "$path")"
|
||
mkdir -p "$parent" 2>/dev/null || true
|
||
mkdir -p "$path" 2>/dev/null || true
|
||
if [[ ! -w "$path" ]]; then
|
||
docker run --rm -v "$parent:/target" ubuntu:24.04 bash -lc "chown -R $(id -u):$(id -g) /target" >/dev/null 2>&1 || true
|
||
fi
|
||
mkdir -p "$path"
|
||
}
|
||
|
||
# preflight: make base dirs writable if inherited from root-owned mounts
|
||
ensure_writable_dir "$PRIVATE_CORE/argus"
|
||
ensure_writable_dir "$PRIVATE_CORE/argus/metric"
|
||
ensure_writable_dir "$PRIVATE_CORE/argus/metric/grafana"
|
||
ensure_writable_dir "$PRIVATE_CORE/argus/metric/prometheus"
|
||
|
||
mkdir -p \
|
||
"$PRIVATE_CORE/argus/etc" \
|
||
"$PRIVATE_CORE/argus/bind" \
|
||
"$PRIVATE_CORE/argus/master" \
|
||
"$PRIVATE_CORE/argus/metric/prometheus" \
|
||
"$PRIVATE_CORE/argus/alert/alertmanager" \
|
||
"$PRIVATE_CORE/argus/metric/ftp/share" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/data" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/logs" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/plugins" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/provisioning/datasources" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/provisioning/dashboards" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/data/sessions" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/data/dashboards" \
|
||
"$PRIVATE_CORE/argus/metric/grafana/config" \
|
||
"$PRIVATE_CORE/argus/metric/prometheus/data" \
|
||
"$PRIVATE_CORE/argus/metric/prometheus/rules" \
|
||
"$PRIVATE_CORE/argus/metric/prometheus/targets" \
|
||
"$PRIVATE_CORE/argus/agent" \
|
||
"$PRIVATE_CORE/argus/log/elasticsearch" \
|
||
"$PRIVATE_CORE/argus/log/kibana" \
|
||
"$PRIVATE_NODEA/argus/agent/dev-yyrshare-nbnyx10-cp2f-pod-0/health" \
|
||
"$PRIVATE_NODEB/argus/agent/dev-yyrshare-uuuu10-ep2f-pod-0/health" \
|
||
"$TMP_DIR"
|
||
|
||
# Align ownership for supervisor-managed services (ES/Kibana/Grafana expect UID/GID inside container)
|
||
echo "[INFO] Fixing ownership for core private directories..."
|
||
chown -R "${ARGUS_BUILD_UID}:${ARGUS_BUILD_GID}" \
|
||
"$PRIVATE_CORE/argus/log/elasticsearch" \
|
||
"$PRIVATE_CORE/argus/log/kibana" \
|
||
"$PRIVATE_CORE/argus/metric/grafana" \
|
||
"$PRIVATE_CORE/argus/metric/prometheus" \
|
||
"$PRIVATE_CORE/argus/alert" \
|
||
"$PRIVATE_CORE/argus/metric/ftp" \
|
||
"$PRIVATE_CORE/argus/agent" \
|
||
"$PRIVATE_CORE/argus/etc" 2>/dev/null || true
|
||
|
||
# 确保 alert 与 etc 目录组可写,便于非 root 且仅匹配 GID 的服务写入运行文件
|
||
chmod -R g+w "$PRIVATE_CORE/argus/alert" "$PRIVATE_CORE/argus/etc" 2>/dev/null || true
|
||
|
||
echo "[INFO] Using compose-managed network (auto-created by docker compose)"
|
||
|
||
echo "[INFO] Distributing update-dns.sh for core services (bind/master/es/kibana)"
|
||
BIND_UPDATE_SRC="$REPO_ROOT/src/bind/build/update-dns.sh"
|
||
BIND_UPDATE_DEST="$PRIVATE_CORE/argus/etc/update-dns.sh"
|
||
if [[ -f "$BIND_UPDATE_SRC" ]]; then
|
||
cp "$BIND_UPDATE_SRC" "$BIND_UPDATE_DEST"
|
||
chmod +x "$BIND_UPDATE_DEST"
|
||
else
|
||
echo "[WARN] bind update-dns.sh not found at $BIND_UPDATE_SRC"
|
||
fi
|
||
|
||
echo "[INFO] Ensuring images present..."
|
||
ensure_image "argus-elasticsearch:latest"
|
||
ensure_image "argus-kibana:latest"
|
||
ensure_image "argus-bind9:latest"
|
||
ensure_image "argus-master:latest"
|
||
ensure_image "argus-metric-ftp:latest"
|
||
ensure_image "argus-metric-prometheus:latest"
|
||
ensure_image "argus-metric-grafana:latest"
|
||
ensure_image "argus-web-frontend:latest"
|
||
ensure_image "argus-web-proxy:latest"
|
||
ensure_image "argus-alertmanager:latest"
|
||
|
||
echo "[INFO] Preparing Fluent Bit local dependency packages..."
|
||
FLB_BUILD_PACKAGES_DIR="$REPO_ROOT/src/log/fluent-bit/build/packages"
|
||
mkdir -p "$FLB_BUILD_PACKAGES_DIR"
|
||
for deb in \
|
||
"$REPO_ROOT/src/metric/client-plugins/all-in-one-full/plugins/fluent-bit/bin/libyaml-0-2_"*_amd64.deb \
|
||
"$REPO_ROOT/src/metric/client-plugins/all-in-one-full/plugins/fluent-bit/bin/libpq5_"*_amd64.deb ; do
|
||
if ls $deb >/dev/null 2>&1; then
|
||
for f in $deb; do
|
||
base="$(basename "$f")"
|
||
if [[ ! -f "$FLB_BUILD_PACKAGES_DIR/$base" ]]; then
|
||
cp "$f" "$FLB_BUILD_PACKAGES_DIR/"
|
||
echo " [+] copied $base"
|
||
fi
|
||
done
|
||
fi
|
||
done
|
||
|
||
# 额外:从 all-in-one-full 的 ubuntu22/curl.tar.gz 解包必要依赖(libsasl2/ldap),便于离线安装
|
||
CURLOPT_TAR="$REPO_ROOT/src/metric/client-plugins/all-in-one-full/deps/ubuntu22/curl.tar.gz"
|
||
if [[ -f "$CURLOPT_TAR" ]]; then
|
||
tmpdir=$(mktemp -d)
|
||
if tar -xzf "$CURLOPT_TAR" -C "$tmpdir" 2>/dev/null; then
|
||
for p in \
|
||
libsasl2-2_*_amd64.deb \
|
||
libsasl2-modules-db_*_amd64.deb \
|
||
libldap-2.5-0_*_amd64.deb \
|
||
libidn2-0_*_amd64.deb \
|
||
libbrotli1_*_amd64.deb \
|
||
libssl3_*_amd64.deb ; do
|
||
src=$(ls "$tmpdir"/curl/$p 2>/dev/null | head -n1 || true)
|
||
if [[ -n "$src" ]]; then
|
||
base="$(basename "$src")"
|
||
[[ -f "$FLB_BUILD_PACKAGES_DIR/$base" ]] || cp "$src" "$FLB_BUILD_PACKAGES_DIR/" && echo " [+] staged $base"
|
||
fi
|
||
done
|
||
fi
|
||
rm -rf "$tmpdir"
|
||
fi
|
||
|
||
echo "[INFO] Building agent binary..."
|
||
pushd "$REPO_ROOT/src/agent" >/dev/null
|
||
./scripts/build_binary.sh
|
||
popd >/dev/null
|
||
|
||
AGENT_BIN="$REPO_ROOT/src/agent/dist/argus-agent"
|
||
if [[ ! -x "$AGENT_BIN" ]]; then
|
||
echo "[ERROR] Agent binary not found at $AGENT_BIN" >&2
|
||
exit 1
|
||
fi
|
||
echo "$AGENT_BIN" > "$TMP_DIR/agent_binary_path"
|
||
|
||
# 检测GPU环境
|
||
REQUEST_GPU=${ARGUS_SYS_ENABLE_GPU:-false}
|
||
GPU_CHECK_SCRIPT="$REPO_ROOT/src/metric/tests/scripts/common/check-gpu.sh"
|
||
if [[ "$REQUEST_GPU" == "true" ]]; then
|
||
echo "[INFO] --enable-gpu 已启用,开始检测GPU环境..."
|
||
if [[ -f "$GPU_CHECK_SCRIPT" ]]; then
|
||
if bash "$GPU_CHECK_SCRIPT" >/dev/null 2>&1; then
|
||
echo "[INFO] GPU环境可用,将在 compose 中启用 test-gpu-node"
|
||
GPU_AVAILABLE=true
|
||
else
|
||
echo "[ERROR] 未检测到可用 GPU,但指定了 --enable-gpu" >&2
|
||
exit 1
|
||
fi
|
||
else
|
||
echo "[ERROR] 未找到 GPU 检测脚本: $GPU_CHECK_SCRIPT" >&2
|
||
exit 1
|
||
fi
|
||
else
|
||
GPU_AVAILABLE=false
|
||
echo "[INFO] GPU 支持未启用,跳过 GPU 检测"
|
||
fi
|
||
|
||
echo "[INFO] Writing .env with UID/GID and metric configuration"
|
||
#############################################
|
||
# 动态分配宿主机端口并写入 .env
|
||
#############################################
|
||
|
||
# 读取现有 .env(若存在),用于保留密码/域名等
|
||
EXIST_DOTENV="$TEST_ROOT/.env"
|
||
if [[ -f "$EXIST_DOTENV" ]]; then
|
||
EXISTING_FTP_PASSWORD="$(grep -E '^FTP_PASSWORD=' "$EXIST_DOTENV" | tail -n1 | sed 's/^FTP_PASSWORD=//')"
|
||
EXISTING_FTP_DOMAIN="$(grep -E '^FTP_DOMAIN=' "$EXIST_DOTENV" | tail -n1 | sed 's/^FTP_DOMAIN=//')"
|
||
EXISTING_USE_INTRANET="$(grep -E '^USE_INTRANET=' "$EXIST_DOTENV" | tail -n1 | sed 's/^USE_INTRANET=//')"
|
||
else
|
||
EXISTING_FTP_PASSWORD=""
|
||
EXISTING_FTP_DOMAIN=""
|
||
EXISTING_USE_INTRANET=""
|
||
fi
|
||
|
||
is_port_free() {
|
||
local p="$1"
|
||
ss -ltnH 2>/dev/null | awk -v pat=":${p}$" '$4 ~ pat{f=1} END{exit f?1:0}'
|
||
}
|
||
|
||
find_free_port() {
|
||
local prefer="$1"; local start_scan="${2:-20000}"; local max="${3:-65000}"
|
||
if is_port_free "$prefer"; then echo "$prefer"; return 0; fi
|
||
local p
|
||
for (( p=start_scan; p<=max; p++ )); do
|
||
if is_port_free "$p"; then echo "$p"; return 0; fi
|
||
done
|
||
return 1
|
||
}
|
||
|
||
find_free_range() {
|
||
local begin="$1"; local end="$2"; local need_count=$((end-begin+1))
|
||
local try_start="$begin"
|
||
while (( try_start + need_count - 1 <= 65000 )); do
|
||
local ok=1
|
||
for (( p=try_start; p<try_start+need_count; p++ )); do
|
||
if ! is_port_free "$p"; then ok=0; break; fi
|
||
done
|
||
if (( ok==1 )); then
|
||
echo "${try_start}-$((try_start+need_count-1))"; return 0
|
||
fi
|
||
((try_start++))
|
||
done
|
||
return 1
|
||
}
|
||
|
||
# 优先端口(若占用则回退到 20000+ 的空闲)
|
||
MASTER_PORT_VAL=$(find_free_port 32300)
|
||
ES_HTTP_PORT_VAL=$(find_free_port 9200)
|
||
KIBANA_PORT_VAL=$(find_free_port 5601)
|
||
NODE_A_PORT_VAL=$(find_free_port 2020)
|
||
NODE_B_PORT_VAL=$(find_free_port 2021)
|
||
PROMETHEUS_PORT_VAL=$(find_free_port 9090)
|
||
GRAFANA_PORT_VAL=$(find_free_port 3000)
|
||
ALERTMANAGER_PORT_VAL=$(find_free_port 9093)
|
||
WEB_PROXY_PORT_8080_VAL=$(find_free_port 8080 18080 65000)
|
||
WEB_PROXY_PORT_8081_VAL=$(find_free_port 8081 18081 65000)
|
||
WEB_PROXY_PORT_8082_VAL=$(find_free_port 8082 18082 65000)
|
||
WEB_PROXY_PORT_8083_VAL=$(find_free_port 8083 18083 65000)
|
||
WEB_PROXY_PORT_8084_VAL=$(find_free_port 8084 18084 65000)
|
||
WEB_PROXY_PORT_8085_VAL=$(find_free_port 8085 18085 65000)
|
||
|
||
# FTP 控制/数据端口:若 21/20 被占用则回退到空闲
|
||
FTP_PORT_VAL=$(find_free_port 21 2121 65000)
|
||
FTP_DATA_PORT_VAL=$(find_free_port 20 2120 65000)
|
||
|
||
# FTP 被动端口范围:优先 21100-21110,若被占用则向后平移
|
||
FTP_PASV_RANGE_VAL="$(find_free_range 21100 21110 || echo 22100-22110)"
|
||
|
||
# 变量持久化到 .env
|
||
cat > "$TEST_ROOT/.env" <<EOF
|
||
ARGUS_BUILD_UID=$ARGUS_BUILD_UID
|
||
ARGUS_BUILD_GID=$ARGUS_BUILD_GID
|
||
|
||
# GPU 配置
|
||
ENABLE_GPU=$GPU_AVAILABLE
|
||
|
||
# 测试节点(CPU/GPU)默认标识与实例
|
||
METRIC_TEST_HOSTNAME_CPU=test-metric-node-001
|
||
METRIC_TEST_INSTANCE_CPU=172.31.0.50:9100
|
||
METRIC_TEST_HOSTNAME_GPU=test-metric-gpu-node-001
|
||
METRIC_TEST_INSTANCE_GPU=172.31.0.51:9100
|
||
METRIC_TEST_DCGM_GPU=172.31.0.51:9400
|
||
|
||
# Master/日志/监控等服务的宿主机端口(自动分配)
|
||
MASTER_PORT=$MASTER_PORT_VAL
|
||
ES_HTTP_PORT=$ES_HTTP_PORT_VAL
|
||
KIBANA_PORT=$KIBANA_PORT_VAL
|
||
NODE_A_PORT=$NODE_A_PORT_VAL
|
||
NODE_B_PORT=$NODE_B_PORT_VAL
|
||
PROMETHEUS_PORT=$PROMETHEUS_PORT_VAL
|
||
GRAFANA_PORT=$GRAFANA_PORT_VAL
|
||
ALERTMANAGER_PORT=$ALERTMANAGER_PORT_VAL
|
||
WEB_PROXY_PORT_8080=$WEB_PROXY_PORT_8080_VAL
|
||
WEB_PROXY_PORT_8081=$WEB_PROXY_PORT_8081_VAL
|
||
WEB_PROXY_PORT_8082=$WEB_PROXY_PORT_8082_VAL
|
||
WEB_PROXY_PORT_8083=$WEB_PROXY_PORT_8083_VAL
|
||
WEB_PROXY_PORT_8084=$WEB_PROXY_PORT_8084_VAL
|
||
WEB_PROXY_PORT_8085=$WEB_PROXY_PORT_8085_VAL
|
||
|
||
# FTP 配置(自动分配:若21/20占用则使用高位端口)
|
||
FTP_PORT=$FTP_PORT_VAL
|
||
FTP_DATA_PORT=$FTP_DATA_PORT_VAL
|
||
FTP_PASSIVE_HOST_RANGE=$FTP_PASV_RANGE_VAL
|
||
FTP_PASSWORD=${EXISTING_FTP_PASSWORD:-ZGClab1234!}
|
||
FTP_DOMAIN=${EXISTING_FTP_DOMAIN:-ftp.metric.argus.com}
|
||
|
||
# 网络配置
|
||
USE_INTRANET=${EXISTING_USE_INTRANET:-false}
|
||
EOF
|
||
|
||
echo "[OK] Bootstrap completed. Ports written to $TEST_ROOT/.env"
|