#!/usr/bin/env bash # Prerequisites Check Script # Validates that all required files and directories exist in the source project set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" source "$PROJECT_ROOT/lib/common.sh" 2>/dev/null || { log_info() { echo "[INFO] $1"; } log_success() { echo "[✓] $1"; } log_warn() { echo "[WARNING] $1"; } log_error() { echo "[ERROR] $1"; } } # Source project path SOURCE_PROJECT="${1:-}" if [[ -z "$SOURCE_PROJECT" ]]; then SOURCE_PROJECT="${SOURCE_PROJECT:-/home/intlc/projects/smom-dbis-138}" log_info "Using default source project: $SOURCE_PROJECT" fi # Convert to absolute path if [[ "$SOURCE_PROJECT" != /* ]]; then SOURCE_PROJECT="$(cd "$PROJECT_ROOT" && cd "$SOURCE_PROJECT" && pwd 2>/dev/null || echo "$PROJECT_ROOT/$SOURCE_PROJECT")" fi log_info "=========================================" log_info "Prerequisites Check" log_info "=========================================" log_info "" log_info "Source project: $SOURCE_PROJECT" log_info "" ERRORS=0 WARNINGS=0 # Check source project exists if [[ ! -d "$SOURCE_PROJECT" ]]; then log_error "Source project directory not found: $SOURCE_PROJECT" exit 1 fi log_success "Source project directory exists" # Check for required top-level directories log_info "" log_info "=== Checking Required Directories ===" REQUIRED_DIRS=( "config" "keys/validators" ) for dir in "${REQUIRED_DIRS[@]}"; do if [[ -d "$SOURCE_PROJECT/$dir" ]]; then log_success "✓ $dir/ exists" else log_error "✗ $dir/ missing" ERRORS=$((ERRORS + 1)) fi done # Check for config/nodes/ structure (node-specific directories) HAS_NODE_DIRS=false if [[ -d "$SOURCE_PROJECT/config/nodes" ]]; then log_success "✓ config/nodes/ directory exists" HAS_NODE_DIRS=true # Check for node subdirectories log_info "" log_info "Checking node-specific directories in config/nodes/:" NODE_DIRS=$(find "$SOURCE_PROJECT/config/nodes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l) if [[ $NODE_DIRS -gt 0 ]]; then log_success "✓ Found $NODE_DIRS node directory(ies)" log_info " Sample node directories:" find "$SOURCE_PROJECT/config/nodes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -5 | while read dir; do log_info " - $(basename "$dir")" done else log_warn "⚠ config/nodes/ exists but is empty" WARNINGS=$((WARNINGS + 1)) fi else log_info "config/nodes/ not found (using flat config structure)" fi # Check for required files (flat structure) log_info "" log_info "=== Checking Required Files ===" REQUIRED_FILES=( "config/genesis.json" "config/permissions-nodes.toml" "config/permissions-accounts.toml" ) OPTIONAL_FILES=( "config/static-nodes.json" "config/config-validator.toml" "config/config-sentry.toml" "config/config-rpc-public.toml" "config/config-rpc-core.toml" ) for file in "${REQUIRED_FILES[@]}"; do if [[ -f "$SOURCE_PROJECT/$file" ]]; then log_success "✓ $file exists" else log_error "✗ $file missing (REQUIRED)" ERRORS=$((ERRORS + 1)) fi done for file in "${OPTIONAL_FILES[@]}"; do if [[ -f "$SOURCE_PROJECT/$file" ]]; then log_success "✓ $file exists" else log_warn "⚠ $file not found (optional, may be in config/nodes/)" WARNINGS=$((WARNINGS + 1)) fi done # Check node-specific files if config/nodes/ exists if [[ "$HAS_NODE_DIRS" == "true" ]]; then log_info "" log_info "=== Checking Node-Specific Files ===" # Check first node directory for expected files FIRST_NODE_DIR=$(find "$SOURCE_PROJECT/config/nodes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -1) if [[ -n "$FIRST_NODE_DIR" ]] && [[ -d "$FIRST_NODE_DIR" ]]; then NODE_NAME=$(basename "$FIRST_NODE_DIR") log_info "Checking structure in: config/nodes/$NODE_NAME/" NODE_FILES=( "config.toml" "nodekey" "nodekey.pub" ) for file in "${NODE_FILES[@]}"; do if [[ -f "$FIRST_NODE_DIR/$file" ]]; then log_success "✓ config/nodes/$NODE_NAME/$file exists" else log_warn "⚠ config/nodes/$NODE_NAME/$file not found" WARNINGS=$((WARNINGS + 1)) fi done # List all files in the node directory log_info "" log_info "Files in config/nodes/$NODE_NAME/:" find "$FIRST_NODE_DIR" -type f -maxdepth 1 2>/dev/null | while read file; do log_info " - $(basename "$file")" done fi fi # Check validator keys log_info "" log_info "=== Checking Validator Keys ===" KEYS_DIR="$SOURCE_PROJECT/keys/validators" if [[ -d "$KEYS_DIR" ]]; then KEY_COUNT=$(find "$KEYS_DIR" -mindepth 1 -maxdepth 1 -type d -name "validator-*" 2>/dev/null | wc -l) if [[ $KEY_COUNT -gt 0 ]]; then log_success "✓ Found $KEY_COUNT validator key directory(ies)" log_info " Validator directories:" find "$KEYS_DIR" -mindepth 1 -maxdepth 1 -type d -name "validator-*" 2>/dev/null | while read dir; do log_info " - $(basename "$dir")" done # Try to get expected count from config files, or use default EXPECTED_VALIDATORS=5 # Try multiple possible config file locations CONFIG_PATHS=( "$SCRIPT_DIR/../../smom-dbis-138-proxmox/config/proxmox.conf" # scripts/validation -> smom-dbis-138-proxmox/config "$SCRIPT_DIR/../../config/proxmox.conf" # smom-dbis-138-proxmox/scripts/validation -> smom-dbis-138-proxmox/config "$SCRIPT_DIR/../../../smom-dbis-138-proxmox/config/proxmox.conf" # scripts/validation -> smom-dbis-138-proxmox/config "$PROJECT_ROOT/smom-dbis-138-proxmox/config/proxmox.conf" "$PROJECT_ROOT/config/proxmox.conf" "$(dirname "$SOURCE_PROJECT")/../proxmox/smom-dbis-138-proxmox/config/proxmox.conf" "/home/intlc/projects/proxmox/smom-dbis-138-proxmox/config/proxmox.conf" ) for CONFIG_FILE in "${CONFIG_PATHS[@]}"; do # Resolve relative paths if [[ "$CONFIG_FILE" != /* ]]; then CONFIG_FILE="$(cd "$SCRIPT_DIR" && cd "$(dirname "$CONFIG_FILE")" 2>/dev/null && pwd)/$(basename "$CONFIG_FILE")" 2>/dev/null || echo "$CONFIG_FILE" fi if [[ -f "$CONFIG_FILE" ]]; then # Extract VALIDATOR_COUNT value, handling comments on same line CONFIG_VALIDATOR_COUNT=$(grep "^VALIDATOR_COUNT=" "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/^VALIDATOR_COUNT=//' | sed 's/[[:space:]]*#.*$//' | tr -d ' "' || echo "") if [[ -n "$CONFIG_VALIDATOR_COUNT" ]] && [[ "$CONFIG_VALIDATOR_COUNT" =~ ^[0-9]+$ ]]; then EXPECTED_VALIDATORS="$CONFIG_VALIDATOR_COUNT" log_info " Using VALIDATOR_COUNT=$EXPECTED_VALIDATORS from $(basename "$(dirname "$CONFIG_FILE")")/$(basename "$CONFIG_FILE")" break fi fi done if [[ $KEY_COUNT -eq $EXPECTED_VALIDATORS ]]; then log_success "✓ Validator key count matches expected: $EXPECTED_VALIDATORS" else log_warn "⚠ Validator key count mismatch: expected $EXPECTED_VALIDATORS, found $KEY_COUNT" log_info " Note: This may be acceptable if you're deploying fewer validators than configured" log_info " Update VALIDATOR_COUNT=$KEY_COUNT in config/proxmox.conf if this is intentional" WARNINGS=$((WARNINGS + 1)) fi else log_warn "⚠ keys/validators/ exists but no validator-* directories found" WARNINGS=$((WARNINGS + 1)) fi else log_error "✗ keys/validators/ directory missing" ERRORS=$((ERRORS + 1)) fi # Validate genesis.json structure log_info "" log_info "=== Validating Genesis.json ===" GENESIS_FILE="$SOURCE_PROJECT/config/genesis.json" if [[ -f "$GENESIS_FILE" ]]; then # Check JSON syntax if python3 -m json.tool "$GENESIS_FILE" >/dev/null 2>&1; then log_success "✓ genesis.json syntax valid" # Check for QBFT configuration if python3 -c "import sys, json; data=json.load(open('$GENESIS_FILE')); exit(0 if 'config' in data and 'qbft' in data.get('config', {}) else 1)" 2>/dev/null; then log_success "✓ QBFT configuration present in genesis.json" else log_error "✗ QBFT configuration missing in genesis.json" ERRORS=$((ERRORS + 1)) fi # Check for extraData field if python3 -c "import sys, json; data=json.load(open('$GENESIS_FILE')); exit(0 if 'extraData' in data else 1)" 2>/dev/null; then log_success "✓ extraData field present in genesis.json" # Validate extraData format EXTRA_DATA=$(python3 -c "import sys, json; print(json.load(open('$GENESIS_FILE')).get('extraData', ''))" 2>/dev/null) if [[ "$EXTRA_DATA" =~ ^0x[0-9a-fA-F]*$ ]] || [[ -z "$EXTRA_DATA" ]]; then log_success "✓ extraData format valid" else log_error "✗ extraData format invalid: $EXTRA_DATA" ERRORS=$((ERRORS + 1)) fi else log_error "✗ extraData field missing in genesis.json" ERRORS=$((ERRORS + 1)) fi # For dynamic validators, verify no validators array in QBFT if python3 -c "import sys, json; data=json.load(open('$GENESIS_FILE')); qbft=data.get('config', {}).get('qbft', {}); exit(0 if 'validators' not in qbft else 1)" 2>/dev/null; then log_success "✓ Dynamic validator setup confirmed (no validators array in QBFT)" else log_warn "⚠ Validators array found in QBFT config (expected for dynamic validators)" WARNINGS=$((WARNINGS + 1)) fi else log_error "✗ genesis.json syntax invalid" ERRORS=$((ERRORS + 1)) fi else log_error "✗ genesis.json not found" ERRORS=$((ERRORS + 1)) fi # Summary log_info "" log_info "=========================================" log_info "Prerequisites Check Summary" log_info "=========================================" log_info "Errors: $ERRORS" log_info "Warnings: $WARNINGS" log_info "" if [[ $ERRORS -eq 0 ]]; then if [[ $WARNINGS -eq 0 ]]; then log_success "✓ All prerequisites met!" log_info "" log_info "Recommended next steps:" log_info " 1. Verify storage configuration: sudo ./scripts/validation/verify-storage-config.sh" log_info " 2. Verify network configuration: ./scripts/validation/verify-network-config.sh" log_info " 3. Pre-cache OS template: sudo ./scripts/deployment/pre-cache-os-template.sh" log_info "" log_info "Or run all verifications: ./scripts/validation/verify-all.sh $SOURCE_PROJECT" exit 0 else log_warn "⚠ Prerequisites met with $WARNINGS warning(s)" log_info "Review warnings above, but deployment may proceed" log_info "" log_info "Recommended next steps:" log_info " 1. Review warnings above" log_info " 2. Verify storage configuration: sudo ./scripts/validation/verify-storage-config.sh" log_info " 3. Verify network configuration: ./scripts/validation/verify-network-config.sh" exit 0 fi else log_error "✗ Prerequisites check failed with $ERRORS error(s)" log_info "Please fix the errors before proceeding with deployment" exit 1 fi # Check for CCIP configuration files (if CCIP deployment planned) log_info "" log_info "=== Checking CCIP Configuration Files ===" CCIP_REQUIRED_FILES=( "config/ccip/ops-config.yaml" "config/ccip/commit-config.yaml" "config/ccip/exec-config.yaml" "config/ccip/rmn-config.yaml" ) CCIP_OPTIONAL_FILES=( "config/ccip/monitor-config.yaml" "config/ccip/secrets.yaml" ) CCIP_FILES_EXIST=false if [[ -d "$SOURCE_PROJECT/config/ccip" ]] || [[ -d "$SOURCE_PROJECT/ccip" ]]; then CCIP_FILES_EXIST=true log_info "CCIP configuration directory found" for file in "${CCIP_REQUIRED_FILES[@]}"; do if [[ -f "$SOURCE_PROJECT/$file" ]]; then log_success "✓ $file exists" else # Try alternative location alt_file="${file/config\/ccip/ccip}" if [[ -f "$SOURCE_PROJECT/$alt_file" ]]; then log_success "✓ $alt_file exists (alternative location)" else log_warn "⚠ $file not found (may be optional or in different location)" WARNINGS=$((WARNINGS + 1)) fi fi done for file in "${CCIP_OPTIONAL_FILES[@]}"; do if [[ -f "$SOURCE_PROJECT/$file" ]]; then log_success "✓ $file exists" else log_info " (optional) $file not found" fi done else log_info "CCIP configuration directory not found (CCIP deployment may not be planned)" fi # Check for other service configurations log_info "" log_info "=== Checking Other Service Configuration Files ===" SERVICE_CONFIGS=( "config/blockscout.env" "config/firefly/config.yaml" "config/fabric/network-config.yaml" "config/indy/pool-config.yaml" "config/cacti/config.yaml" ) for config in "${SERVICE_CONFIGS[@]}"; do service_name=$(basename "$(dirname "$config")") if [[ -f "$SOURCE_PROJECT/$config" ]]; then log_success "✓ $config exists" else log_info " (optional) $config not found - $service_name may use different config location" fi done