20260326 完成数据库model迁移;20260327 增加一键replay脚本
This commit is contained in:
45
scripts/replay_verify/README.md
Normal file
45
scripts/replay_verify/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Replay Verify Scripts
|
||||
|
||||
## `run_multi_rir_ccr_replay_verify.sh`
|
||||
|
||||
用途:
|
||||
- 通用 multi-RIR CCR replay verify 入口
|
||||
- 通过 `--rir` 指定一个或多个 RIR,按顺序执行
|
||||
- 通过 `--mode` 指定 `snapshot`、`delta` 或 `both`
|
||||
- 默认每个 RIR 的 RocksDB 目录在 compare/verify 结束后自动删除;传 `--keep-db` 才保留
|
||||
- 同一次执行的所有产物都会先落到 `rpki/target/replay/<timestamp>/`
|
||||
- 该时间戳目录下再按 RIR 分目录:
|
||||
- `<rir>_ccr_replay_<timestamp>`
|
||||
|
||||
默认输入:
|
||||
- bundle root: `/home/yuyr/dev/rust_playground/routinator/bench/multi_rir_demo/runs/20260316-112341-multi-final3`
|
||||
- 每个 RIR 的 TAL / TA / validation time / record CSV 由 `scripts/payload_replay/multi_rir_case_info.py` 解析
|
||||
|
||||
用法:
|
||||
- 单个 RIR:
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir apnic --mode both`
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir apnic --mode snapshot`
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir apnic --mode delta`
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir apnic --mode both`
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir apnic,ripe --mode snapshot`
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir afrinic,apnic,arin,lacnic,ripe --mode both`
|
||||
- `./scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh --rir apnic --mode delta --keep-db`
|
||||
|
||||
可覆盖环境变量:
|
||||
- `BUNDLE_ROOT`
|
||||
- `OUT_ROOT`(默认:`rpki/target/replay`)
|
||||
- `RUN_TAG`
|
||||
|
||||
主要产物:
|
||||
- 单次执行根目录:
|
||||
- `rpki/target/replay/<timestamp>/`
|
||||
- 每个 RIR 子目录下:
|
||||
- `<rir>_snapshot.ccr`
|
||||
- `<rir>_delta.ccr`
|
||||
- `<rir>_*_report.json`
|
||||
- `<rir>_*_ccr_vrps.csv`
|
||||
- `<rir>_*_ccr_compare_summary.md`
|
||||
- `<rir>_*_ccr_verify.json`
|
||||
- 同次执行总汇总:
|
||||
- `multi_rir_ccr_replay_verify_<timestamp>_summary.md`
|
||||
- `multi_rir_ccr_replay_verify_<timestamp>_summary.json`
|
||||
284
scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh
Executable file
284
scripts/replay_verify/run_multi_rir_ccr_replay_verify.sh
Executable file
@@ -0,0 +1,284 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage:
|
||||
run_multi_rir_ccr_replay_verify.sh --rir <rir[,rir...]> [--mode snapshot|delta|both] [--keep-db]
|
||||
|
||||
Options:
|
||||
--rir <list> Comma-separated RIR list, e.g. apnic or apnic,ripe
|
||||
--mode <mode> snapshot | delta | both (default: both)
|
||||
--keep-db Keep per-run RocksDB directories (default: remove after verify)
|
||||
--bundle-root <p> Override bundle root
|
||||
--out-root <p> Override output root (default: rpki/target/replay)
|
||||
--run-tag <tag> Override timestamp suffix for all RIR runs
|
||||
USAGE
|
||||
}
|
||||
|
||||
MODE="both"
|
||||
KEEP_DB=0
|
||||
RIR_LIST=""
|
||||
BUNDLE_ROOT="${BUNDLE_ROOT:-/home/yuyr/dev/rust_playground/routinator/bench/multi_rir_demo/runs/20260316-112341-multi-final3}"
|
||||
OUT_ROOT="${OUT_ROOT:-$ROOT_DIR/target/replay}"
|
||||
RUN_TAG="${RUN_TAG:-$(date -u +%Y%m%dT%H%M%SZ)}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--rir)
|
||||
shift
|
||||
RIR_LIST="${1:-}"
|
||||
;;
|
||||
--mode)
|
||||
shift
|
||||
MODE="${1:-}"
|
||||
;;
|
||||
--keep-db)
|
||||
KEEP_DB=1
|
||||
;;
|
||||
--bundle-root)
|
||||
shift
|
||||
BUNDLE_ROOT="${1:-}"
|
||||
;;
|
||||
--out-root)
|
||||
shift
|
||||
OUT_ROOT="${1:-}"
|
||||
;;
|
||||
--run-tag)
|
||||
shift
|
||||
RUN_TAG="${1:-}"
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "unknown argument: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
shift || true
|
||||
done
|
||||
|
||||
if [[ -z "$RIR_LIST" ]]; then
|
||||
echo "--rir is required" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
case "$MODE" in
|
||||
snapshot|delta|both) ;;
|
||||
*)
|
||||
echo "invalid --mode: $MODE" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
CASE_INFO_SCRIPT="$ROOT_DIR/scripts/payload_replay/multi_rir_case_info.py"
|
||||
mkdir -p "$OUT_ROOT"
|
||||
RUN_ROOT="$OUT_ROOT/$RUN_TAG"
|
||||
mkdir -p "$RUN_ROOT"
|
||||
|
||||
cargo build --release --bin rpki --bin ccr_to_routinator_csv --bin ccr_verify >/dev/null
|
||||
|
||||
summary_md="$RUN_ROOT/multi_rir_ccr_replay_verify_${RUN_TAG}_summary.md"
|
||||
summary_json="$RUN_ROOT/multi_rir_ccr_replay_verify_${RUN_TAG}_summary.json"
|
||||
|
||||
python3 - <<'PY' >/dev/null
|
||||
PY
|
||||
|
||||
summary_json_tmp="$(mktemp)"
|
||||
printf '[]' > "$summary_json_tmp"
|
||||
|
||||
run_one_mode() {
|
||||
local rir="$1"
|
||||
local mode="$2"
|
||||
local run_dir="$3"
|
||||
local trust_anchor="$4"
|
||||
local tal_path="$5"
|
||||
local ta_path="$6"
|
||||
local base_archive="$7"
|
||||
local base_locks="$8"
|
||||
local base_csv="$9"
|
||||
local delta_archive="${10}"
|
||||
local delta_locks="${11}"
|
||||
local delta_csv="${12}"
|
||||
local snapshot_validation_time="${13}"
|
||||
local delta_validation_time="${14}"
|
||||
|
||||
local db_dir="$run_dir/${rir}_${mode}_db"
|
||||
local report_json="$run_dir/${rir}_${mode}_report.json"
|
||||
local run_log="$run_dir/${rir}_${mode}_run.log"
|
||||
local ccr_path="$run_dir/${rir}_${mode}.ccr"
|
||||
local csv_path="$run_dir/${rir}_${mode}_ccr_vrps.csv"
|
||||
local compare_md="$run_dir/${rir}_${mode}_ccr_compare_summary.md"
|
||||
local only_ours="$run_dir/${rir}_${mode}_ccr_only_in_ours.csv"
|
||||
local only_record="$run_dir/${rir}_${mode}_ccr_only_in_record.csv"
|
||||
local verify_json="$run_dir/${rir}_${mode}_ccr_verify.json"
|
||||
local meta_json="$run_dir/${rir}_${mode}_meta.json"
|
||||
|
||||
rm -rf "$db_dir"
|
||||
|
||||
local -a cmd=(target/release/rpki --db "$db_dir" --tal-path "$tal_path" --ta-path "$ta_path")
|
||||
if [[ "$mode" == "snapshot" ]]; then
|
||||
cmd+=(--payload-replay-archive "$base_archive" --payload-replay-locks "$base_locks" --validation-time "$snapshot_validation_time")
|
||||
else
|
||||
cmd+=(
|
||||
--payload-base-archive "$base_archive"
|
||||
--payload-base-locks "$base_locks"
|
||||
--payload-base-validation-time "$snapshot_validation_time"
|
||||
--payload-delta-archive "$delta_archive"
|
||||
--payload-delta-locks "$delta_locks"
|
||||
--validation-time "$delta_validation_time"
|
||||
)
|
||||
fi
|
||||
cmd+=(--report-json "$report_json" --ccr-out "$ccr_path")
|
||||
|
||||
local start_s end_s duration_s
|
||||
start_s="$(date +%s)"
|
||||
(
|
||||
echo "# ${rir} ${mode} command:"
|
||||
printf '%q ' "${cmd[@]}"
|
||||
echo
|
||||
echo
|
||||
"${cmd[@]}"
|
||||
) 2>&1 | tee "$run_log" >/dev/null
|
||||
end_s="$(date +%s)"
|
||||
duration_s="$((end_s - start_s))"
|
||||
|
||||
target/release/ccr_to_routinator_csv \
|
||||
--ccr "$ccr_path" \
|
||||
--out "$csv_path" \
|
||||
--trust-anchor "$trust_anchor" >/dev/null
|
||||
|
||||
local record_csv
|
||||
if [[ "$mode" == "snapshot" ]]; then
|
||||
record_csv="$base_csv"
|
||||
else
|
||||
record_csv="$delta_csv"
|
||||
fi
|
||||
./scripts/payload_replay/compare_with_routinator_record.sh \
|
||||
"$csv_path" \
|
||||
"$record_csv" \
|
||||
"$compare_md" \
|
||||
"$only_ours" \
|
||||
"$only_record" >/dev/null
|
||||
|
||||
target/release/ccr_verify \
|
||||
--ccr "$ccr_path" \
|
||||
--db "$db_dir" > "$verify_json"
|
||||
|
||||
python3 - "$report_json" "$meta_json" "$mode" "$duration_s" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
report = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
|
||||
meta = {
|
||||
'mode': sys.argv[3],
|
||||
'duration_seconds': int(sys.argv[4]),
|
||||
'validation_time': report.get('validation_time_rfc3339_utc'),
|
||||
'publication_points_processed': report['tree']['instances_processed'],
|
||||
'publication_points_failed': report['tree']['instances_failed'],
|
||||
'vrps': len(report['vrps']),
|
||||
'aspas': len(report['aspas']),
|
||||
}
|
||||
Path(sys.argv[2]).write_text(json.dumps(meta, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
|
||||
PY
|
||||
|
||||
if [[ "$KEEP_DB" -eq 0 ]]; then
|
||||
rm -rf "$db_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
IFS=',' read -r -a RIRS <<< "$RIR_LIST"
|
||||
for rir in "${RIRS[@]}"; do
|
||||
rir="$(echo "$rir" | xargs)"
|
||||
[[ -n "$rir" ]] || continue
|
||||
eval "$(python3 "$CASE_INFO_SCRIPT" --bundle-root "$BUNDLE_ROOT" --rir "$rir" --format env)"
|
||||
|
||||
run_dir="$RUN_ROOT/${rir}_ccr_replay_${RUN_TAG}"
|
||||
mkdir -p "$run_dir"
|
||||
|
||||
if [[ "$MODE" == "snapshot" || "$MODE" == "both" ]]; then
|
||||
run_one_mode \
|
||||
"$rir" snapshot "$run_dir" "$TRUST_ANCHOR" "$TAL_PATH" "$TA_PATH" \
|
||||
"$PAYLOAD_REPLAY_ARCHIVE" "$PAYLOAD_REPLAY_LOCKS" "$ROUTINATOR_BASE_RECORD_CSV" \
|
||||
"$PAYLOAD_DELTA_ARCHIVE" "$PAYLOAD_DELTA_LOCKS" "$ROUTINATOR_DELTA_RECORD_CSV" \
|
||||
"$SNAPSHOT_VALIDATION_TIME" "$DELTA_VALIDATION_TIME"
|
||||
fi
|
||||
if [[ "$MODE" == "delta" || "$MODE" == "both" ]]; then
|
||||
run_one_mode \
|
||||
"$rir" delta "$run_dir" "$TRUST_ANCHOR" "$TAL_PATH" "$TA_PATH" \
|
||||
"$PAYLOAD_REPLAY_ARCHIVE" "$PAYLOAD_REPLAY_LOCKS" "$ROUTINATOR_BASE_RECORD_CSV" \
|
||||
"$PAYLOAD_DELTA_ARCHIVE" "$PAYLOAD_DELTA_LOCKS" "$ROUTINATOR_DELTA_RECORD_CSV" \
|
||||
"$SNAPSHOT_VALIDATION_TIME" "$DELTA_VALIDATION_TIME"
|
||||
fi
|
||||
|
||||
python3 - "$summary_json_tmp" "$run_dir" "$rir" "$MODE" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
summary_path = Path(sys.argv[1])
|
||||
run_dir = Path(sys.argv[2])
|
||||
rir = sys.argv[3]
|
||||
mode = sys.argv[4]
|
||||
rows = json.loads(summary_path.read_text(encoding='utf-8'))
|
||||
for submode in ['snapshot','delta']:
|
||||
if mode not in ('both', submode):
|
||||
continue
|
||||
compare = run_dir / f'{rir}_{submode}_ccr_compare_summary.md'
|
||||
meta = run_dir / f'{rir}_{submode}_meta.json'
|
||||
verify = run_dir / f'{rir}_{submode}_ccr_verify.json'
|
||||
if not compare.exists() or not meta.exists() or not verify.exists():
|
||||
continue
|
||||
compare_text = compare.read_text(encoding='utf-8')
|
||||
meta_obj = json.loads(meta.read_text(encoding='utf-8'))
|
||||
verify_obj = json.loads(verify.read_text(encoding='utf-8'))
|
||||
def metric(name):
|
||||
prefix = f'| {name} | '
|
||||
for line in compare_text.splitlines():
|
||||
if line.startswith(prefix):
|
||||
return int(line.split('|')[2].strip())
|
||||
raise SystemExit(f'missing metric {name} in {compare}')
|
||||
rows.append({
|
||||
'rir': rir,
|
||||
'mode': submode,
|
||||
'run_dir': str(run_dir),
|
||||
'duration_seconds': meta_obj['duration_seconds'],
|
||||
'vrps': meta_obj['vrps'],
|
||||
'aspas': meta_obj['aspas'],
|
||||
'only_in_ours': metric('only_in_ours'),
|
||||
'only_in_record': metric('only_in_record'),
|
||||
'intersection': metric('intersection'),
|
||||
'state_hashes_ok': verify_obj.get('state_hashes_ok'),
|
||||
})
|
||||
summary_path.write_text(json.dumps(rows, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
|
||||
PY
|
||||
|
||||
done
|
||||
|
||||
python3 - "$summary_json_tmp" "$summary_json" "$summary_md" "$RUN_TAG" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
rows = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
|
||||
out_json = Path(sys.argv[2])
|
||||
out_md = Path(sys.argv[3])
|
||||
run_tag = sys.argv[4]
|
||||
out_json.write_text(json.dumps(rows, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
|
||||
parts = []
|
||||
parts.append('# Multi-RIR CCR Replay Verify Summary\n\n')
|
||||
parts.append(f'- run_tag: `{run_tag}`\n\n')
|
||||
parts.append('| rir | mode | duration_s | vrps | aspas | only_in_ours | only_in_record | state_hashes_ok |\n')
|
||||
parts.append('|---|---|---:|---:|---:|---:|---:|---|\n')
|
||||
for row in rows:
|
||||
parts.append(f"| {row['rir']} | {row['mode']} | {row['duration_seconds']} | {row['vrps']} | {row['aspas']} | {row['only_in_ours']} | {row['only_in_record']} | {row['state_hashes_ok']} |\n")
|
||||
out_md.write_text(''.join(parts), encoding='utf-8')
|
||||
PY
|
||||
|
||||
rm -f "$summary_json_tmp"
|
||||
|
||||
echo "== multi-rir replay verify complete ==" >&2
|
||||
echo "- summary: $summary_md" >&2
|
||||
echo "- summary json: $summary_json" >&2
|
||||
Reference in New Issue
Block a user