- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains - Omit embedded publish git dirs and empty placeholders from index Made-with: Cursor
506 lines
18 KiB
Bash
Executable File
506 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Deploy Validated Set - Complete Deployment Orchestrator
|
|
# Script-based deployment for Besu validated set (no boot node required)
|
|
#
|
|
# This script orchestrates the complete deployment of Besu nodes:
|
|
# 1. Deploy containers (validators, sentries, RPC nodes)
|
|
# 2. Copy configuration files and keys
|
|
# 3. Bootstrap network (generate static-nodes.json)
|
|
# 4. Validate deployment
|
|
#
|
|
# Features:
|
|
# - Progress tracking with ETA
|
|
# - Comprehensive error handling
|
|
# - Rollback support
|
|
# - Detailed logging
|
|
# - Timeout protection
|
|
# - Container status validation
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
# Source libraries with error handling
|
|
source "$PROJECT_ROOT/lib/common.sh" || {
|
|
echo "ERROR: Failed to load common.sh library" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Optional: Load progress tracking if available
|
|
if [[ -f "$PROJECT_ROOT/lib/progress-tracking.sh" ]]; then
|
|
source "$PROJECT_ROOT/lib/progress-tracking.sh"
|
|
USE_ADVANCED_PROGRESS=true
|
|
else
|
|
USE_ADVANCED_PROGRESS=false
|
|
fi
|
|
|
|
# Parse command line arguments
|
|
SKIP_DEPLOYMENT="${SKIP_DEPLOYMENT:-false}"
|
|
SKIP_CONFIG="${SKIP_CONFIG:-false}"
|
|
SKIP_BOOTSTRAP="${SKIP_BOOTSTRAP:-false}"
|
|
SKIP_VALIDATION="${SKIP_VALIDATION:-false}"
|
|
SOURCE_PROJECT="${SOURCE_PROJECT:-}"
|
|
TIMEOUT_DEPLOYMENT="${TIMEOUT_DEPLOYMENT:-3600}" # 1 hour default
|
|
TIMEOUT_CONFIG="${TIMEOUT_CONFIG:-1800}" # 30 minutes default
|
|
TIMEOUT_BOOTSTRAP="${TIMEOUT_BOOTSTRAP:-300}" # 5 minutes default
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--skip-deployment)
|
|
SKIP_DEPLOYMENT=true
|
|
shift
|
|
;;
|
|
--skip-config)
|
|
SKIP_CONFIG=true
|
|
shift
|
|
;;
|
|
--skip-bootstrap)
|
|
SKIP_BOOTSTRAP=true
|
|
shift
|
|
;;
|
|
--skip-validation)
|
|
SKIP_VALIDATION=true
|
|
shift
|
|
;;
|
|
--source-project)
|
|
SOURCE_PROJECT="$2"
|
|
shift 2
|
|
;;
|
|
--timeout-deployment)
|
|
TIMEOUT_DEPLOYMENT="$2"
|
|
shift 2
|
|
;;
|
|
--timeout-config)
|
|
TIMEOUT_CONFIG="$2"
|
|
shift 2
|
|
;;
|
|
--help)
|
|
cat << EOF
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Deploy Validated Set - Complete Besu Network Deployment Orchestrator
|
|
|
|
Options:
|
|
--skip-deployment Skip container deployment (assume containers exist)
|
|
--skip-config Skip configuration file copying
|
|
--skip-bootstrap Skip network bootstrap
|
|
--skip-validation Skip validation
|
|
--source-project PATH Path to source project with config files
|
|
(default: ../smom-dbis-138 relative to project root)
|
|
--timeout-deployment SEC Timeout for deployment phase (default: 3600)
|
|
--timeout-config SEC Timeout for config phase (default: 1800)
|
|
--timeout-bootstrap SEC Timeout for bootstrap phase (default: 300)
|
|
--help Show this help message
|
|
|
|
Examples:
|
|
# Full deployment
|
|
$0 --source-project /opt/smom-dbis-138
|
|
|
|
# Skip deployment, only configure
|
|
$0 --skip-deployment --source-project /opt/smom-dbis-138
|
|
|
|
# Only validate existing deployment
|
|
$0 --skip-deployment --skip-config --skip-bootstrap
|
|
EOF
|
|
exit 0
|
|
;;
|
|
*)
|
|
log_error "Unknown option: $1"
|
|
log_info "Use --help for usage information"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Load configuration
|
|
load_config || {
|
|
log_warn "Failed to load main configuration, using defaults"
|
|
}
|
|
load_config "$PROJECT_ROOT/config/network.conf" || {
|
|
log_warn "network.conf not found, using defaults"
|
|
}
|
|
|
|
# Track deployment start time
|
|
DEPLOYMENT_START_TIME=$(date +%s)
|
|
|
|
# Display header
|
|
log_info "========================================="
|
|
log_info "Deploy Validated Set - Script-Based Approach"
|
|
log_info "========================================="
|
|
log_info "Started: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
log_info ""
|
|
|
|
# Calculate total steps based on what's being executed
|
|
TOTAL_STEPS=0
|
|
[[ "$SKIP_DEPLOYMENT" != "true" ]] && TOTAL_STEPS=$((TOTAL_STEPS + 1))
|
|
[[ "$SKIP_CONFIG" != "true" ]] && TOTAL_STEPS=$((TOTAL_STEPS + 1))
|
|
[[ "$SKIP_BOOTSTRAP" != "true" ]] && TOTAL_STEPS=$((TOTAL_STEPS + 1))
|
|
[[ "$SKIP_VALIDATION" != "true" ]] && TOTAL_STEPS=$((TOTAL_STEPS + 1))
|
|
|
|
CURRENT_STEP=0
|
|
|
|
# Enhanced progress tracking function
|
|
show_progress() {
|
|
local step_name="$1"
|
|
local phase_start_time="${2:-$(date +%s)}"
|
|
CURRENT_STEP=$((CURRENT_STEP + 1))
|
|
local percent=$((CURRENT_STEP * 100 / TOTAL_STEPS))
|
|
|
|
if [[ "$USE_ADVANCED_PROGRESS" == "true" ]] && command_exists update_progress 2>/dev/null; then
|
|
update_progress "$CURRENT_STEP" "$step_name"
|
|
else
|
|
log_info "Progress: [$percent%] [$CURRENT_STEP/$TOTAL_STEPS] - $step_name"
|
|
fi
|
|
}
|
|
|
|
# Time tracking function
|
|
track_phase_time() {
|
|
local phase_name="$1"
|
|
local start_time="$2"
|
|
local end_time=$(date +%s)
|
|
local duration=$((end_time - start_time))
|
|
local minutes=$((duration / 60))
|
|
local seconds=$((duration % 60))
|
|
log_info "$phase_name completed in ${minutes}m ${seconds}s"
|
|
}
|
|
|
|
# Run command with timeout
|
|
run_with_timeout() {
|
|
local timeout_sec="$1"
|
|
shift
|
|
local cmd=("$@")
|
|
|
|
if command_exists timeout; then
|
|
timeout "$timeout_sec" "${cmd[@]}" || {
|
|
local exit_code=$?
|
|
if [[ $exit_code -eq 124 ]]; then
|
|
log_error "Command timed out after ${timeout_sec} seconds: ${cmd[*]}"
|
|
return 124
|
|
fi
|
|
return $exit_code
|
|
}
|
|
else
|
|
# Fallback: run without timeout if timeout command not available
|
|
"${cmd[@]}"
|
|
fi
|
|
}
|
|
|
|
# Check prerequisites
|
|
log_info "=== Pre-Deployment Validation ==="
|
|
|
|
if ! command_exists pct; then
|
|
error_exit "pct command not found. This script must be run on Proxmox host."
|
|
fi
|
|
|
|
if [[ $EUID -ne 0 ]]; then
|
|
error_exit "This script must be run as root"
|
|
fi
|
|
|
|
# Validate project structure
|
|
if [[ ! -d "$PROJECT_ROOT/scripts" ]]; then
|
|
error_exit "Invalid project structure: scripts directory not found"
|
|
fi
|
|
|
|
if [[ ! -d "$PROJECT_ROOT/config" ]]; then
|
|
log_warn "config directory not found, some features may not work"
|
|
fi
|
|
|
|
log_success "Prerequisites checked"
|
|
|
|
# Ensure OS template exists
|
|
log_info "Checking OS template..."
|
|
ensure_os_template "${CONTAINER_OS_TEMPLATE:-local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst}" || {
|
|
error_exit "OS template not available. Please download it first: pveam download local ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
|
|
}
|
|
|
|
# Create log directory early
|
|
mkdir -p "$PROJECT_ROOT/logs"
|
|
LOG_FILE="$PROJECT_ROOT/logs/deploy-validated-set-$(date +%Y%m%d-%H%M%S).log"
|
|
log_info "Deployment log: $LOG_FILE"
|
|
|
|
# Setup logging - preserve stdout/stderr for interactive use, also log to file
|
|
# Use exec to redirect, but preserve original descriptors
|
|
exec 3>&1 4>&2
|
|
exec 1> >(tee -a "$LOG_FILE")
|
|
exec 2> >(tee -a "$LOG_FILE" >&2)
|
|
|
|
# Create snapshot helper function
|
|
create_snapshot_if_needed() {
|
|
local vmid=$1
|
|
local reason=$2
|
|
if command -v pct >/dev/null 2>&1 && [[ -f "$PROJECT_ROOT/scripts/manage/snapshot-before-change.sh" ]]; then
|
|
log_info "Creating snapshot for container $vmid before $reason..."
|
|
"$PROJECT_ROOT/scripts/manage/snapshot-before-change.sh" "$vmid" "pre-$reason-$(date +%Y%m%d-%H%M%S)" || {
|
|
log_warn "Snapshot creation failed (continuing anyway)"
|
|
}
|
|
fi
|
|
}
|
|
|
|
# Initialize rollback tracking
|
|
if command_exists init_rollback 2>/dev/null; then
|
|
ROLLBACK_LOG="$PROJECT_ROOT/logs/rollback-$(date +%Y%m%d-%H%M%S).log"
|
|
init_rollback "$ROLLBACK_LOG"
|
|
set_rollback_trap
|
|
log_info "Rollback tracking enabled: $ROLLBACK_LOG"
|
|
fi
|
|
|
|
# Initialize advanced progress tracking if available
|
|
if [[ "$USE_ADVANCED_PROGRESS" == "true" ]] && command_exists init_progress_tracking 2>/dev/null; then
|
|
init_progress_tracking "$TOTAL_STEPS" "Deployment"
|
|
fi
|
|
|
|
# Resolve SOURCE_PROJECT path early if provided
|
|
if [[ -n "$SOURCE_PROJECT" ]]; then
|
|
# Resolve absolute path for SOURCE_PROJECT if relative
|
|
if [[ "$SOURCE_PROJECT" != /* ]]; then
|
|
SOURCE_PROJECT="$(cd "$PROJECT_ROOT" && cd "$SOURCE_PROJECT" 2>/dev/null && pwd || echo "$PROJECT_ROOT/$SOURCE_PROJECT")"
|
|
fi
|
|
|
|
if [[ ! -d "$SOURCE_PROJECT" ]]; then
|
|
log_error "Source project directory not found: $SOURCE_PROJECT"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Source project: $SOURCE_PROJECT"
|
|
fi
|
|
|
|
log_info ""
|
|
|
|
# Phase 1: Deploy Containers
|
|
if [[ "$SKIP_DEPLOYMENT" != "true" ]]; then
|
|
PHASE_START_1=$(date +%s)
|
|
show_progress "Deploy Containers" "$PHASE_START_1"
|
|
log_info ""
|
|
log_info "========================================="
|
|
log_info "Phase 1: Deploy Containers"
|
|
log_info "========================================="
|
|
log_info "Timeout: ${TIMEOUT_DEPLOYMENT}s"
|
|
log_info ""
|
|
|
|
if [[ -f "$SCRIPT_DIR/deploy-besu-nodes.sh" ]]; then
|
|
log_info "Deploying Besu nodes..."
|
|
|
|
if ! run_with_timeout "$TIMEOUT_DEPLOYMENT" bash "$SCRIPT_DIR/deploy-besu-nodes.sh"; then
|
|
log_error "Besu nodes deployment failed or timed out"
|
|
log_error "Check logs for details: $LOG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
track_phase_time "Container deployment" "$PHASE_START_1"
|
|
log_success "Besu nodes deployed"
|
|
else
|
|
log_error "Besu deployment script not found: $SCRIPT_DIR/deploy-besu-nodes.sh"
|
|
exit 1
|
|
fi
|
|
else
|
|
log_info "Skipping container deployment (--skip-deployment)"
|
|
log_info "Assuming containers already exist"
|
|
fi
|
|
|
|
# Phase 2: Copy Configuration Files
|
|
if [[ "$SKIP_CONFIG" != "true" ]]; then
|
|
PHASE_START_2=$(date +%s)
|
|
show_progress "Copy Configuration Files" "$PHASE_START_2"
|
|
log_info ""
|
|
log_info "========================================="
|
|
log_info "Phase 2: Copy Configuration Files"
|
|
log_info "========================================="
|
|
log_info "Timeout: ${TIMEOUT_CONFIG}s"
|
|
log_info ""
|
|
|
|
if [[ -z "$SOURCE_PROJECT" ]]; then
|
|
# Try default location
|
|
DEFAULT_SOURCE="$PROJECT_ROOT/../smom-dbis-138"
|
|
if [[ -d "$DEFAULT_SOURCE" ]]; then
|
|
SOURCE_PROJECT="$DEFAULT_SOURCE"
|
|
log_info "Using default source project: $SOURCE_PROJECT"
|
|
else
|
|
log_warn "Source project not specified and default not found: $DEFAULT_SOURCE"
|
|
log_warn "Skipping configuration copy"
|
|
log_info "Specify with: --source-project PATH"
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$SOURCE_PROJECT" ]] && [[ -d "$SOURCE_PROJECT" ]]; then
|
|
# Run prerequisites check first
|
|
if [[ -f "$PROJECT_ROOT/scripts/validation/check-prerequisites.sh" ]]; then
|
|
log_info "Checking prerequisites..."
|
|
if ! bash "$PROJECT_ROOT/scripts/validation/check-prerequisites.sh" "$SOURCE_PROJECT"; then
|
|
log_error "Prerequisites check failed"
|
|
log_error "Review the output above and fix issues before continuing"
|
|
exit 1
|
|
fi
|
|
log_success "Prerequisites validated"
|
|
fi
|
|
|
|
export SOURCE_PROJECT
|
|
copy_success=false
|
|
|
|
# Try enhanced copy script first (supports config/nodes/ structure), then fallback
|
|
if [[ -f "$PROJECT_ROOT/scripts/copy-besu-config-with-nodes.sh" ]]; then
|
|
log_info "Copying Besu configuration files (with nodes/ structure support)..."
|
|
if run_with_timeout "$TIMEOUT_CONFIG" bash "$PROJECT_ROOT/scripts/copy-besu-config-with-nodes.sh" "$SOURCE_PROJECT"; then
|
|
copy_success=true
|
|
log_success "Configuration files copied (with nodes/ structure)"
|
|
else
|
|
log_warn "Enhanced copy script failed, trying standard copy script..."
|
|
fi
|
|
fi
|
|
|
|
# Fallback to standard copy script
|
|
if [[ "$copy_success" != "true" ]] && [[ -f "$PROJECT_ROOT/scripts/copy-besu-config.sh" ]]; then
|
|
log_info "Copying Besu configuration files (standard method)..."
|
|
if ! run_with_timeout "$TIMEOUT_CONFIG" bash "$PROJECT_ROOT/scripts/copy-besu-config.sh" "$SOURCE_PROJECT"; then
|
|
log_error "Configuration copy failed"
|
|
log_error "Check logs for details: $LOG_FILE"
|
|
exit 1
|
|
fi
|
|
copy_success=true
|
|
log_success "Configuration files copied"
|
|
fi
|
|
|
|
if [[ "$copy_success" != "true" ]]; then
|
|
log_error "No working copy script available"
|
|
log_error "Checked:"
|
|
log_error " - $PROJECT_ROOT/scripts/copy-besu-config-with-nodes.sh"
|
|
log_error " - $PROJECT_ROOT/scripts/copy-besu-config.sh"
|
|
exit 1
|
|
fi
|
|
|
|
track_phase_time "Configuration copy" "$PHASE_START_2"
|
|
else
|
|
log_warn "Source project not available, skipping configuration copy"
|
|
log_info "You can copy configuration files manually or run:"
|
|
log_info " $PROJECT_ROOT/scripts/copy-besu-config.sh $SOURCE_PROJECT"
|
|
fi
|
|
else
|
|
log_info "Skipping configuration copy (--skip-config)"
|
|
fi
|
|
|
|
# Phase 3: Bootstrap Network
|
|
if [[ "$SKIP_BOOTSTRAP" != "true" ]]; then
|
|
PHASE_START_3=$(date +%s)
|
|
show_progress "Bootstrap Network" "$PHASE_START_3"
|
|
log_info ""
|
|
log_info "========================================="
|
|
log_info "Phase 3: Bootstrap Network"
|
|
log_info "========================================="
|
|
log_info "Timeout: ${TIMEOUT_BOOTSTRAP}s"
|
|
log_info ""
|
|
|
|
if [[ -f "$PROJECT_ROOT/scripts/network/bootstrap-network.sh" ]]; then
|
|
log_info "Bootstrapping network (generating static-nodes.json)..."
|
|
|
|
if ! run_with_timeout "$TIMEOUT_BOOTSTRAP" bash "$PROJECT_ROOT/scripts/network/bootstrap-network.sh"; then
|
|
log_error "Network bootstrap failed or timed out"
|
|
log_error "Check logs for details: $LOG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
track_phase_time "Network bootstrap" "$PHASE_START_3"
|
|
log_success "Network bootstrapped"
|
|
else
|
|
log_error "Bootstrap script not found: $PROJECT_ROOT/scripts/network/bootstrap-network.sh"
|
|
exit 1
|
|
fi
|
|
else
|
|
log_info "Skipping network bootstrap (--skip-bootstrap)"
|
|
fi
|
|
|
|
# Phase 4: Validate Deployment
|
|
if [[ "$SKIP_VALIDATION" != "true" ]]; then
|
|
PHASE_START_4=$(date +%s)
|
|
show_progress "Validate Deployment" "$PHASE_START_4"
|
|
log_info ""
|
|
log_info "========================================="
|
|
log_info "Phase 4: Validate Deployment"
|
|
log_info "========================================="
|
|
log_info ""
|
|
|
|
# Comprehensive deployment validation
|
|
if [[ -f "$PROJECT_ROOT/scripts/validation/validate-deployment-comprehensive.sh" ]]; then
|
|
log_info "Running comprehensive deployment validation..."
|
|
if ! bash "$PROJECT_ROOT/scripts/validation/validate-deployment-comprehensive.sh"; then
|
|
log_error "Comprehensive validation failed (check output above)"
|
|
log_error "This validation ensures:"
|
|
log_error " 1. All config files are in correct locations"
|
|
log_error " 2. Genesis.json is valid and consistent"
|
|
log_error " 3. Correct number of nodes deployed"
|
|
log_error " 4. Correct templates used for each node type"
|
|
log_error " 5. No inconsistencies or gaps"
|
|
log_info ""
|
|
log_info "Review validation output and fix issues before proceeding"
|
|
exit 1
|
|
fi
|
|
track_phase_time "Deployment validation" "$PHASE_START_4"
|
|
log_success "Comprehensive validation passed"
|
|
else
|
|
log_warn "Comprehensive validation script not found, running basic validation..."
|
|
|
|
# Fallback to basic validation
|
|
if [[ -f "$PROJECT_ROOT/scripts/validation/validate-validator-set.sh" ]]; then
|
|
log_info "Validating validator set..."
|
|
if bash "$PROJECT_ROOT/scripts/validation/validate-validator-set.sh"; then
|
|
log_success "Validator set validation passed"
|
|
else
|
|
log_warn "Validator set validation had issues (check output above)"
|
|
fi
|
|
else
|
|
log_warn "Validator validation script not found, skipping validation"
|
|
fi
|
|
fi
|
|
else
|
|
log_info "Skipping validation (--skip-validation)"
|
|
fi
|
|
|
|
# Calculate total deployment time
|
|
DEPLOYMENT_END_TIME=$(date +%s)
|
|
TOTAL_DURATION=$((DEPLOYMENT_END_TIME - DEPLOYMENT_START_TIME))
|
|
TOTAL_MINUTES=$((TOTAL_DURATION / 60))
|
|
TOTAL_SECONDS=$((TOTAL_DURATION % 60))
|
|
|
|
# Complete progress tracking if using advanced tracking
|
|
if [[ "$USE_ADVANCED_PROGRESS" == "true" ]] && command_exists complete_progress 2>/dev/null; then
|
|
complete_progress
|
|
fi
|
|
|
|
# Final Summary
|
|
log_info ""
|
|
log_info "========================================="
|
|
log_success "Deployment Complete!"
|
|
log_info "========================================="
|
|
log_info "Completed: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
log_info "Total duration: ${TOTAL_MINUTES}m ${TOTAL_SECONDS}s"
|
|
log_info ""
|
|
log_info "Deployment Summary:"
|
|
log_info " - Containers: $([ "$SKIP_DEPLOYMENT" != "true" ] && echo "✓ Deployed" || echo "⊘ Skipped")"
|
|
log_info " - Configuration: $([ "$SKIP_CONFIG" != "true" ] && echo "✓ Copied" || echo "⊘ Skipped")"
|
|
log_info " - Bootstrap: $([ "$SKIP_BOOTSTRAP" != "true" ] && echo "✓ Completed" || echo "⊘ Skipped")"
|
|
log_info " - Validation: $([ "$SKIP_VALIDATION" != "true" ] && echo "✓ Completed" || echo "⊘ Skipped")"
|
|
log_info ""
|
|
log_info "Next Steps:"
|
|
log_info "1. Verify all services are running:"
|
|
log_info " for vmid in 1000 1001 1002 1003 1004 1500 1501 1502 1503 2101 2102 2103 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403 2420 2430 2440 2460 2470 2480; do"
|
|
log_info " pct exec \$vmid -- systemctl status besu-validator besu-sentry besu-rpc 2>/dev/null"
|
|
log_info " done"
|
|
log_info ""
|
|
log_info "2. Start Besu services (if not already started):"
|
|
log_info " $PROJECT_ROOT/scripts/fix-besu-services.sh"
|
|
log_info ""
|
|
log_info "3. Check consensus is active (blocks being produced):"
|
|
log_info " pct exec 1000 -- curl -X POST -H 'Content-Type: application/json' \\"
|
|
log_info " --data '{\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1}' \\"
|
|
log_info " http://localhost:8545"
|
|
log_info ""
|
|
log_info "4. Monitor logs for any issues:"
|
|
log_info " pct exec 1000 -- journalctl -u besu-validator -f"
|
|
log_info ""
|
|
log_info "Deployment log: $LOG_FILE"
|
|
if [[ -n "${ROLLBACK_LOG:-}" ]]; then
|
|
log_info "Rollback log: $ROLLBACK_LOG"
|
|
fi
|
|
log_info ""
|
|
|
|
exit 0
|