252 lines
8.0 KiB
Bash
Executable File
252 lines
8.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Practical fix for enode URLs: Extract first 128 chars and map to correct IPs
|
|
# Based on Besu requirements: enode IDs must be exactly 128 hex characters
|
|
|
|
set -euo pipefail
|
|
|
|
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
|
|
WORK_DIR="/tmp/fix-enodes-$$"
|
|
mkdir -p "$WORK_DIR"
|
|
|
|
cleanup() { rm -rf "$WORK_DIR"; }
|
|
trap cleanup EXIT
|
|
|
|
# Container IP mapping
|
|
declare -A CONTAINER_IPS=(
|
|
[106]="192.168.11.13" # besu-validator-1
|
|
[107]="192.168.11.14" # besu-validator-2
|
|
[108]="192.168.11.15" # besu-validator-3
|
|
[109]="192.168.11.16" # besu-validator-4
|
|
[110]="192.168.11.18" # besu-validator-5
|
|
[111]="192.168.11.19" # besu-sentry-2
|
|
[112]="192.168.11.20" # besu-sentry-3
|
|
[113]="192.168.11.21" # besu-sentry-4
|
|
[114]="192.168.11.22" # besu-sentry-5
|
|
[115]="192.168.11.23" # besu-rpc-1
|
|
[116]="192.168.11.24" # besu-rpc-2
|
|
[117]="192.168.11.25" # besu-rpc-3
|
|
)
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# Extract and fix enodes from a container's current static-nodes.json
|
|
extract_and_fix_enodes() {
|
|
local vmid="$1"
|
|
local container_ip="${CONTAINER_IPS[$vmid]}"
|
|
|
|
log_info "Processing container $vmid ($container_ip)..."
|
|
|
|
# Get current static-nodes.json
|
|
local current_json
|
|
current_json=$(ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" \
|
|
"pct exec $vmid -- cat /etc/besu/static-nodes.json 2>/dev/null" || echo '[]')
|
|
|
|
if [[ "$current_json" == "[]" ]] || [[ -z "$current_json" ]]; then
|
|
log_warn "Container $vmid: No static-nodes.json found"
|
|
return 1
|
|
fi
|
|
|
|
# Extract node IDs (first 128 chars) and create corrected enodes
|
|
python3 << PYEOF
|
|
import json
|
|
import re
|
|
|
|
try:
|
|
static_nodes = json.loads('''$current_json''')
|
|
except:
|
|
static_nodes = []
|
|
|
|
fixed_enodes = []
|
|
node_ids_seen = set()
|
|
|
|
for i, enode in enumerate(static_nodes):
|
|
# Extract hex part
|
|
match = re.search(r'enode://([a-fA-F0-9]+)@', enode)
|
|
if not match:
|
|
continue
|
|
|
|
full_hex = match.group(1).lower()
|
|
# Take first 128 chars (removes trailing zeros padding)
|
|
node_id = full_hex[:128]
|
|
|
|
if len(node_id) != 128:
|
|
print(f"SKIP: Node ID {i+1} has length {len(node_id)}, not 128", file=sys.stderr)
|
|
continue
|
|
|
|
# Validate hex
|
|
if not re.match(r'^[0-9a-f]{128}$', node_id):
|
|
print(f"SKIP: Node ID {i+1} contains invalid hex", file=sys.stderr)
|
|
continue
|
|
|
|
# Map first 5 to validator IPs (106-110), others keep original IP for now
|
|
if i < 5:
|
|
vmid_map = 106 + i
|
|
if vmid_map in ${!CONTAINER_IPS[@]}:
|
|
ip = "${CONTAINER_IPS[$vmid_map]}"
|
|
else:
|
|
# Extract original IP
|
|
ip_match = re.search(r'@([0-9.]+):', enode)
|
|
ip = ip_match.group(1) if ip_match else "$container_ip"
|
|
else:
|
|
# Extract original IP
|
|
ip_match = re.search(r'@([0-9.]+):', enode)
|
|
ip = ip_match.group(1) if ip_match else "$container_ip"
|
|
|
|
fixed_enode = f"enode://{node_id}@{ip}:30303"
|
|
|
|
# Avoid duplicates
|
|
if node_id not in node_ids_seen:
|
|
fixed_enodes.append(fixed_enode)
|
|
node_ids_seen.add(node_id)
|
|
|
|
# Save to file
|
|
with open('$WORK_DIR/static-nodes-${vmid}.json', 'w') as f:
|
|
json.dump(fixed_enodes, f, indent=2)
|
|
|
|
print(f"Fixed {len(fixed_enodes)} enode URLs for container $vmid")
|
|
PYEOF
|
|
|
|
return 0
|
|
}
|
|
|
|
# Generate corrected permissions-nodes.toml from all containers
|
|
generate_permissions_toml() {
|
|
log_info "Generating corrected permissions-nodes.toml..."
|
|
|
|
# Collect all unique enodes from all containers
|
|
python3 << 'PYEOF'
|
|
import json
|
|
import re
|
|
import glob
|
|
|
|
all_enodes = set()
|
|
|
|
# Read all fixed static-nodes.json files
|
|
for json_file in glob.glob('$WORK_DIR/static-nodes-*.json'):
|
|
try:
|
|
with open(json_file, 'r') as f:
|
|
enodes = json.load(f)
|
|
for enode in enodes:
|
|
all_enodes.add(enode)
|
|
except:
|
|
pass
|
|
|
|
# Sort for consistency
|
|
sorted_enodes = sorted(all_enodes)
|
|
|
|
# Generate TOML
|
|
toml_content = """# Node Permissioning Configuration
|
|
# Lists nodes that are allowed to connect to this node
|
|
# Generated from actual container enodes (first 128 chars of node IDs)
|
|
# All validators, sentries, and RPC nodes are included
|
|
|
|
nodes-allowlist=[
|
|
"""
|
|
|
|
for enode in sorted_enodes:
|
|
toml_content += f' "{enode}",\n'
|
|
|
|
# Remove trailing comma
|
|
toml_content = toml_content.rstrip(',\n') + '\n]'
|
|
|
|
with open('$WORK_DIR/permissions-nodes.toml', 'w') as f:
|
|
f.write(toml_content)
|
|
|
|
print(f"Generated permissions-nodes.toml with {len(sorted_enodes)} unique nodes")
|
|
PYEOF
|
|
|
|
log_success "Generated permissions-nodes.toml"
|
|
}
|
|
|
|
# Deploy corrected files
|
|
deploy_files() {
|
|
log_info "Deploying corrected files to all containers..."
|
|
|
|
# First, copy permissions-nodes.toml to host
|
|
scp -o StrictHostKeyChecking=accept-new \
|
|
"$WORK_DIR/permissions-nodes.toml" \
|
|
"root@${PROXMOX_HOST}:/tmp/permissions-nodes-fixed.toml"
|
|
|
|
for vmid in 106 107 108 109 110 111 112 113 114 115 116 117; do
|
|
if ! ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" \
|
|
"pct status $vmid 2>/dev/null | grep -q running"; then
|
|
log_warn "Container $vmid: not running, skipping"
|
|
continue
|
|
fi
|
|
|
|
log_info "Deploying to container $vmid..."
|
|
|
|
# Copy static-nodes.json (container-specific)
|
|
if [[ -f "$WORK_DIR/static-nodes-${vmid}.json" ]]; then
|
|
scp -o StrictHostKeyChecking=accept-new \
|
|
"$WORK_DIR/static-nodes-${vmid}.json" \
|
|
"root@${PROXMOX_HOST}:/tmp/static-nodes-${vmid}.json"
|
|
|
|
ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" << REMOTE_SCRIPT
|
|
pct push $vmid /tmp/static-nodes-${vmid}.json /etc/besu/static-nodes.json
|
|
pct exec $vmid -- chown besu:besu /etc/besu/static-nodes.json
|
|
rm -f /tmp/static-nodes-${vmid}.json
|
|
REMOTE_SCRIPT
|
|
fi
|
|
|
|
# Copy permissions-nodes.toml (same for all)
|
|
ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" << REMOTE_SCRIPT
|
|
pct push $vmid /tmp/permissions-nodes-fixed.toml /etc/besu/permissions-nodes.toml
|
|
pct exec $vmid -- chown besu:besu /etc/besu/permissions-nodes.toml
|
|
REMOTE_SCRIPT
|
|
|
|
log_success "Container $vmid: files deployed"
|
|
done
|
|
|
|
# Cleanup
|
|
ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" \
|
|
"rm -f /tmp/permissions-nodes-fixed.toml"
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
echo "╔════════════════════════════════════════════════════════════════╗"
|
|
echo "║ FIX ENODE CONFIGS (EXTRACT FIRST 128 CHARS) ║"
|
|
echo "╚════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
|
|
# Process all containers
|
|
for vmid in 106 107 108 109 110 111 112 113 114 115 116 117; do
|
|
extract_and_fix_enodes "$vmid" || true
|
|
done
|
|
|
|
generate_permissions_toml
|
|
|
|
echo ""
|
|
log_info "Preview of generated files:"
|
|
echo ""
|
|
echo "=== static-nodes.json (container 106) ==="
|
|
cat "$WORK_DIR/static-nodes-106.json" 2>/dev/null | head -10 || echo "Not generated"
|
|
echo ""
|
|
echo "=== permissions-nodes.toml (first 20 lines) ==="
|
|
cat "$WORK_DIR/permissions-nodes.toml" | head -20
|
|
echo ""
|
|
|
|
read -p "Deploy corrected files to all containers? [y/N]: " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
deploy_files
|
|
log_success "All files deployed!"
|
|
log_info "Next: Restart Besu services on all containers"
|
|
else
|
|
log_info "Files available in $WORK_DIR for review"
|
|
fi
|
|
}
|
|
|
|
main "$@"
|