Remove obsolete files and scripts related to the BGP server setup, including .gitignore, Dockerfile, and various documentation files. Update docker-compose.yml to streamline the configuration for the FRRouting BGP server. This cleanup enhances project maintainability and focuses on the current implementation.

This commit is contained in:
2025-07-11 18:41:15 +07:00
parent 58f1405fef
commit af197d8953
27 changed files with 443 additions and 3471 deletions
-95
View File
@@ -1,95 +0,0 @@
#!/usr/bin/env python3
"""
Скрипт для генерации конфигурации FRR из переменных окружения
"""
import os
import sys
from pathlib import Path
def get_env_var(name, default):
"""Получение переменной окружения с значением по умолчанию"""
return os.environ.get(name, default)
def generate_frr_config():
"""Генерация конфигурации FRR"""
# Получение настроек из переменных окружения
local_as = get_env_var('BGP_LOCAL_AS', '65000')
router_id = get_env_var('BGP_ROUTER_ID', '192.168.100.99')
neighbor_ip = get_env_var('BGP_NEIGHBOR_IP', '192.168.0.254')
neighbor_as = get_env_var('BGP_NEIGHBOR_AS', '65001')
hold_time = get_env_var('BGP_HOLD_TIME', '90')
keepalive = get_env_var('BGP_KEEPALIVE', '30')
log_level = get_env_var('BGP_LOG_LEVEL', 'info')
# Конфигурация FRR
config = f"""# FRR Configuration File
# Generated automatically from environment variables
# Глобальные настройки
frr version 8.5.2
frr defaults traditional
hostname bgp-server
log syslog {log_level}
service integrated-vtysh-config
# Настройки BGP
router bgp {local_as}
bgp router-id {router_id}
bgp log-neighbor-changes
neighbor {neighbor_ip} remote-as {neighbor_as}
neighbor {neighbor_ip} description RouterOS Client
neighbor {neighbor_ip} timers {keepalive} {hold_time}
neighbor {neighbor_ip} capability graceful-restart
neighbor {neighbor_ip} soft-reconfiguration inbound
!
address-family ipv4 unicast
neighbor {neighbor_ip} activate
neighbor {neighbor_ip} route-map OUTBOUND out
neighbor {neighbor_ip} route-map INBOUND in
exit-address-family
!
# Route maps для фильтрации
route-map OUTBOUND permit 10
description Allow all outbound routes
!
route-map INBOUND deny 10
description Deny all inbound routes (receive-only mode)
!
# Настройки интерфейса
interface eth0
ip address {router_id}/24
!
# Статические маршруты (будут добавлены динамически)
# ip route 192.168.1.0/24 Null0
"""
return config
def main():
"""Основная функция"""
try:
# Генерация конфигурации
config = generate_frr_config()
# Запись в файл
config_path = Path('/etc/frr/frr.conf')
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, 'w') as f:
f.write(config)
print(f"FRR configuration generated: {config_path}")
print("Configuration content:")
print(config)
except Exception as e:
print(f"Error generating FRR configuration: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
-245
View File
@@ -1,245 +0,0 @@
#!/usr/bin/env python3
"""
Скрипт для загрузки префиксов из текстовых файлов в FRR
"""
import sys
import os
import time
import subprocess
import ipaddress
from pathlib import Path
from typing import List, Set
# Настройки
DATA_DIR = "/app/data"
LOG_FILE = "/app/logs/prefixes.log"
PREFIX_FILES = ["prefixes.txt", "additional_prefixes.txt"]
def log_message(message: str):
"""Запись сообщения в лог"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}"
# Вывод в stdout
print(log_entry, flush=True)
# Запись в файл (с обработкой ошибок)
try:
with open(LOG_FILE, "a") as f:
f.write(log_entry + "\n")
except (PermissionError, OSError) as e:
# Если не можем записать в файл, просто выводим в stderr
print(f"Warning: Could not write to log file: {e}", file=sys.stderr, flush=True)
def log_error(message: str):
"""Запись ошибки в лог"""
log_message(f"ERROR: {message}")
def validate_prefix(prefix: str) -> bool:
"""Валидация IP префикса"""
try:
ipaddress.ip_network(prefix, strict=False)
return True
except ValueError:
return False
def load_prefixes_from_file(file_path: Path) -> Set[str]:
"""Загрузка префиксов из файла"""
prefixes = set()
if not file_path.exists():
log_message(f"File not found: {file_path}")
return prefixes
try:
with open(file_path, 'r') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
# Пропуск пустых строк и комментариев
if not line or line.startswith('#'):
continue
# Валидация префикса
if validate_prefix(line):
prefixes.add(line)
else:
log_message(f"Invalid prefix in {file_path}:{line_num}: {line}")
except Exception as e:
log_message(f"Error reading {file_path}: {e}")
return prefixes
def load_all_prefixes() -> Set[str]:
"""Загрузка всех префиксов из всех файлов"""
all_prefixes = set()
for filename in PREFIX_FILES:
file_path = Path(DATA_DIR) / filename
prefixes = load_prefixes_from_file(file_path)
all_prefixes.update(prefixes)
log_message(f"Loaded {len(prefixes)} prefixes from {filename}")
return all_prefixes
def run_vtysh_command(command: str) -> bool:
"""Выполнение команды через vtysh"""
try:
result = subprocess.run(
['vtysh', '-c', command],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
log_error(f"vtysh command failed: {command}")
log_error(f"stderr: {result.stderr}")
return False
return True
except subprocess.TimeoutExpired:
log_error(f"vtysh command timeout: {command}")
return False
except Exception as e:
log_error(f"Error running vtysh command '{command}': {e}")
return False
def announce_prefixes(prefixes: Set[str]):
"""Анонсирование префиксов через FRR"""
log_message(f"Announcing {len(prefixes)} prefixes...")
for prefix in sorted(prefixes):
# Добавление статического маршрута в FRR
command = f"ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Announced prefix: {prefix}")
else:
log_error(f"Failed to announce prefix: {prefix}")
def withdraw_prefixes(prefixes: Set[str]):
"""Отзыв префиксов через FRR"""
log_message(f"Withdrawing {len(prefixes)} prefixes...")
for prefix in sorted(prefixes):
# Удаление статического маршрута из FRR
command = f"no ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Withdrew prefix: {prefix}")
else:
log_error(f"Failed to withdraw prefix: {prefix}")
def check_frr_status() -> bool:
"""Проверка статуса FRR"""
try:
result = subprocess.run(
['vtysh', '-c', 'show version'],
capture_output=True,
text=True,
timeout=10
)
return result.returncode == 0
except Exception:
return False
def wait_for_frr():
"""Ожидание запуска FRR"""
log_message("Waiting for FRR to start...")
max_attempts = 30
attempt = 0
while attempt < max_attempts:
if check_frr_status():
log_message("FRR is ready")
return True
attempt += 1
time.sleep(2)
if attempt % 5 == 0:
log_message(f"Still waiting for FRR... (attempt {attempt}/{max_attempts})")
log_error("FRR did not start within expected time")
return False
def main():
"""Основная функция"""
# Создание директории для логов в начале
try:
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
except (PermissionError, OSError):
pass # Игнорируем ошибки создания директории
# Проверка тестового режима
if len(sys.argv) > 1 and sys.argv[1] == '--test':
print("Testing prefix loader...")
prefixes = load_all_prefixes()
print(f"Found {len(prefixes)} prefixes: {list(prefixes)}")
return
# Проверка режима отзыва
if len(sys.argv) > 1 and sys.argv[1] == '--withdraw':
log_message("Withdraw mode: loading and withdrawing all prefixes...")
prefixes = load_all_prefixes()
if wait_for_frr():
withdraw_prefixes(prefixes)
return
log_message("Starting prefix loader...")
# Ожидание запуска FRR
if not wait_for_frr():
log_error("Cannot proceed without FRR")
return
# Загрузка префиксов
prefixes = load_all_prefixes()
log_message(f"Total prefixes loaded: {len(prefixes)}")
if not prefixes:
log_message("No valid prefixes found. Exiting.")
return
# Анонсирование префиксов
announce_prefixes(prefixes)
log_message("All prefixes announced successfully")
# Мониторинг изменений в файлах
log_message("Starting file monitoring...")
try:
while True:
time.sleep(30) # Проверка каждые 30 секунд
# Перезагрузка префиксов
new_prefixes = load_all_prefixes()
# Определение изменений
added = new_prefixes - prefixes
removed = prefixes - new_prefixes
if added:
log_message(f"Adding {len(added)} new prefixes: {list(added)}")
announce_prefixes(added)
if removed:
log_message(f"Removing {len(removed)} prefixes: {list(removed)}")
withdraw_prefixes(removed)
if added or removed:
prefixes = new_prefixes
log_message(f"Updated prefix count: {len(prefixes)}")
except KeyboardInterrupt:
log_message("Received interrupt signal")
except Exception as e:
log_message(f"Error in main loop: {e}")
finally:
# Отзыв всех префиксов при завершении
log_message("Withdrawing all prefixes...")
withdraw_prefixes(prefixes)
log_message("Prefix loader stopped")
if __name__ == "__main__":
main()
-194
View File
@@ -1,194 +0,0 @@
#!/usr/bin/env python3
"""
Скрипт мониторинга FRR BGP сервера
"""
import sys
import os
import time
import subprocess
import json
from pathlib import Path
from typing import Dict, Any
# Настройки
LOG_FILE = "/app/logs/monitor.log"
STATUS_FILE = "/app/logs/status.json"
def log_message(message: str):
"""Запись сообщения в лог"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}"
print(log_entry, flush=True)
try:
with open(LOG_FILE, "a") as f:
f.write(log_entry + "\n")
except (PermissionError, OSError):
pass
def run_vtysh_command(command: str) -> str:
"""Выполнение команды через vtysh"""
try:
result = subprocess.run(
['vtysh', '-c', command],
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
return result.stdout.strip()
else:
log_message(f"vtysh command failed: {command}")
return ""
except Exception as e:
log_message(f"Error running vtysh command '{command}': {e}")
return ""
def get_bgp_summary() -> Dict[str, Any]:
"""Получение сводки BGP"""
summary = run_vtysh_command("show ip bgp summary")
if not summary:
return {"error": "Could not get BGP summary"}
# Парсинг вывода BGP summary
lines = summary.split('\n')
neighbors = []
for line in lines:
if 'BGP neighbor' in line and 'remote AS' in line:
parts = line.split()
if len(parts) >= 8:
neighbor = {
"ip": parts[2].rstrip(','),
"remote_as": parts[7],
"state": parts[-1] if len(parts) > 7 else "Unknown"
}
neighbors.append(neighbor)
return {
"neighbors": neighbors,
"raw_output": summary
}
def get_bgp_routes() -> Dict[str, Any]:
"""Получение BGP маршрутов"""
routes = run_vtysh_command("show ip bgp")
if not routes:
return {"error": "Could not get BGP routes"}
# Подсчет маршрутов
route_count = 0
for line in routes.split('\n'):
if line.strip() and not line.startswith('BGP table') and not line.startswith('*>'):
if any(char.isdigit() for char in line):
route_count += 1
return {
"route_count": route_count,
"raw_output": routes
}
def get_frr_status() -> Dict[str, Any]:
"""Получение статуса FRR"""
version = run_vtysh_command("show version")
if not version:
return {"error": "Could not get FRR version"}
return {
"version": version.split('\n')[0] if version else "Unknown",
"raw_output": version
}
def get_system_status() -> Dict[str, Any]:
"""Получение системного статуса"""
try:
# Проверка процессов FRR
zebra_running = subprocess.run(['pgrep', 'zebra'], capture_output=True).returncode == 0
bgpd_running = subprocess.run(['pgrep', 'bgpd'], capture_output=True).returncode == 0
# Проверка использования памяти
memory_info = {}
try:
with open('/proc/meminfo', 'r') as f:
for line in f:
if 'MemTotal:' in line:
memory_info['total'] = line.split()[1]
elif 'MemAvailable:' in line:
memory_info['available'] = line.split()[1]
except:
pass
return {
"zebra_running": zebra_running,
"bgpd_running": bgpd_running,
"memory": memory_info
}
except Exception as e:
return {"error": f"Could not get system status: {e}"}
def save_status(status: Dict[str, Any]):
"""Сохранение статуса в файл"""
try:
with open(STATUS_FILE, 'w') as f:
json.dump(status, f, indent=2)
except Exception as e:
log_message(f"Error saving status: {e}")
def main():
"""Основная функция"""
log_message("Starting FRR monitor...")
# Создание директории для логов
try:
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
os.makedirs(os.path.dirname(STATUS_FILE), exist_ok=True)
except (PermissionError, OSError):
pass
while True:
try:
# Сбор статуса
status = {
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"frr": get_frr_status(),
"bgp_summary": get_bgp_summary(),
"bgp_routes": get_bgp_routes(),
"system": get_system_status()
}
# Сохранение статуса
save_status(status)
# Логирование важной информации
bgp_summary = status["bgp_summary"]
if "neighbors" in bgp_summary:
for neighbor in bgp_summary["neighbors"]:
log_message(f"BGP neighbor {neighbor['ip']} (AS {neighbor['remote_as']}): {neighbor['state']}")
bgp_routes = status["bgp_routes"]
if "route_count" in bgp_routes:
log_message(f"BGP routes: {bgp_routes['route_count']}")
system = status["system"]
if "zebra_running" in system and "bgpd_running" in system:
if not system["zebra_running"] or not system["bgpd_running"]:
log_message("WARNING: FRR daemons not running properly")
# Ожидание перед следующей проверкой
time.sleep(60) # Проверка каждую минуту
except KeyboardInterrupt:
log_message("Monitor stopped by user")
break
except Exception as e:
log_message(f"Error in monitor loop: {e}")
time.sleep(30) # Короткая пауза при ошибке
if __name__ == "__main__":
main()
-206
View File
@@ -1,206 +0,0 @@
#!/usr/bin/env python3
"""
Скрипт для перезагрузки префиксов в FRR
"""
import sys
import os
import time
import subprocess
import ipaddress
from pathlib import Path
from typing import Set
# Настройки
DATA_DIR = "/app/data"
LOG_FILE = "/app/logs/reload.log"
PREFIX_FILES = ["prefixes.txt", "additional_prefixes.txt"]
def log_message(message: str):
"""Запись сообщения в лог"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}"
print(log_entry, flush=True)
try:
with open(LOG_FILE, "a") as f:
f.write(log_entry + "\n")
except (PermissionError, OSError):
pass
def validate_prefix(prefix: str) -> bool:
"""Валидация IP префикса"""
try:
ipaddress.ip_network(prefix, strict=False)
return True
except ValueError:
return False
def load_prefixes_from_file(file_path: Path) -> Set[str]:
"""Загрузка префиксов из файла"""
prefixes = set()
if not file_path.exists():
log_message(f"File not found: {file_path}")
return prefixes
try:
with open(file_path, 'r') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
# Пропуск пустых строк и комментариев
if not line or line.startswith('#'):
continue
# Валидация префикса
if validate_prefix(line):
prefixes.add(line)
else:
log_message(f"Invalid prefix in {file_path}:{line_num}: {line}")
except Exception as e:
log_message(f"Error reading {file_path}: {e}")
return prefixes
def load_all_prefixes() -> Set[str]:
"""Загрузка всех префиксов из всех файлов"""
all_prefixes = set()
for filename in PREFIX_FILES:
file_path = Path(DATA_DIR) / filename
prefixes = load_prefixes_from_file(file_path)
all_prefixes.update(prefixes)
log_message(f"Loaded {len(prefixes)} prefixes from {filename}")
return all_prefixes
def get_current_routes() -> Set[str]:
"""Получение текущих статических маршрутов из FRR"""
try:
result = subprocess.run(
['vtysh', '-c', 'show ip route static'],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
log_message("Could not get current routes from FRR")
return set()
routes = set()
for line in result.stdout.split('\n'):
line = line.strip()
if line and 'via Null0' in line:
# Парсинг строки маршрута
parts = line.split()
if len(parts) >= 2:
route = parts[1]
if validate_prefix(route):
routes.add(route)
return routes
except Exception as e:
log_message(f"Error getting current routes: {e}")
return set()
def run_vtysh_command(command: str) -> bool:
"""Выполнение команды через vtysh"""
try:
result = subprocess.run(
['vtysh', '-c', command],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
log_message(f"vtysh command failed: {command}")
return False
return True
except Exception as e:
log_message(f"Error running vtysh command '{command}': {e}")
return False
def announce_prefixes(prefixes: Set[str]):
"""Анонсирование префиксов через FRR"""
log_message(f"Announcing {len(prefixes)} prefixes...")
for prefix in sorted(prefixes):
command = f"ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Announced prefix: {prefix}")
else:
log_message(f"Failed to announce prefix: {prefix}")
def withdraw_prefixes(prefixes: Set[str]):
"""Отзыв префиксов через FRR"""
log_message(f"Withdrawing {len(prefixes)} prefixes...")
for prefix in sorted(prefixes):
command = f"no ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Withdrew prefix: {prefix}")
else:
log_message(f"Failed to withdraw prefix: {prefix}")
def check_frr_status() -> bool:
"""Проверка статуса FRR"""
try:
result = subprocess.run(
['vtysh', '-c', 'show version'],
capture_output=True,
text=True,
timeout=10
)
return result.returncode == 0
except Exception:
return False
def main():
"""Основная функция"""
log_message("Starting prefix reload...")
# Проверка статуса FRR
if not check_frr_status():
log_message("ERROR: FRR is not running")
return 1
# Загрузка новых префиксов
new_prefixes = load_all_prefixes()
log_message(f"Loaded {len(new_prefixes)} prefixes from files")
# Получение текущих маршрутов
current_routes = get_current_routes()
log_message(f"Found {len(current_routes)} current routes in FRR")
# Определение изменений
to_add = new_prefixes - current_routes
to_remove = current_routes - new_prefixes
log_message(f"Changes: {len(to_add)} to add, {len(to_remove)} to remove")
# Применение изменений
if to_remove:
withdraw_prefixes(to_remove)
if to_add:
announce_prefixes(to_add)
# Финальная проверка
final_routes = get_current_routes()
log_message(f"Final route count: {len(final_routes)}")
if len(final_routes) == len(new_prefixes):
log_message("Reload completed successfully!")
return 0
else:
log_message("WARNING: Route count mismatch after reload")
return 1
if __name__ == "__main__":
sys.exit(main())
-123
View File
@@ -1,123 +0,0 @@
# Скрипт запуска BGP Server (FRR)
param(
[string]$ContainerName = "bgp-server",
[string]$DataPath = "./data",
[string]$LogsPath = "./logs",
[switch]$Build,
[switch]$Force
)
Write-Host "=== BGP Server (FRR) Startup Script ===" -ForegroundColor Green
# Проверка существования контейнера
$containerExists = docker ps -a --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
if ($containerExists) {
Write-Host "Found existing container: $ContainerName" -ForegroundColor Yellow
if (-not $Force) {
$response = Read-Host "Do you want to stop and remove the existing container? (y/N)"
if ($response -ne "y" -and $response -ne "Y") {
Write-Host "Operation cancelled." -ForegroundColor Red
exit 0
}
}
# Остановка и удаление старого контейнера
Write-Host "Stopping container..." -ForegroundColor Yellow
docker stop $ContainerName
Write-Host "Removing container..." -ForegroundColor Yellow
docker rm $ContainerName
}
# Создание директорий если не существуют
if (-not (Test-Path $DataPath)) {
Write-Host "Creating data directory: $DataPath" -ForegroundColor Yellow
New-Item -ItemType Directory -Path $DataPath -Force | Out-Null
}
if (-not (Test-Path $LogsPath)) {
Write-Host "Creating logs directory: $LogsPath" -ForegroundColor Yellow
New-Item -ItemType Directory -Path $LogsPath -Force | Out-Null
}
# Создание файла с префиксами если не существует
$prefixesFile = Join-Path $DataPath "prefixes.txt"
if (-not (Test-Path $prefixesFile)) {
Write-Host "Creating default prefixes file..." -ForegroundColor Yellow
@"
# Default prefixes file
# Add your prefixes here, one per line
192.168.100.0/24
10.0.0.0/8
172.16.0.0/12
"@ | Out-File -FilePath $prefixesFile -Encoding UTF8
}
# Сборка образа если требуется
if ($Build) {
Write-Host "Building Docker image..." -ForegroundColor Yellow
docker build -t bgp-server-frr .
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to build image. Exiting." -ForegroundColor Red
exit 1
}
}
# Запуск контейнера
Write-Host "Starting BGP Server container..." -ForegroundColor Yellow
$currentPath = Get-Location
$dataVolume = "${currentPath}\${DataPath}:/app/data:ro"
$logsVolume = "${currentPath}\${LogsPath}:/app/logs"
docker run -d `
--name $ContainerName `
--restart unless-stopped `
-p 179:179 `
-v $dataVolume `
-v $logsVolume `
--cap-add NET_ADMIN `
--privileged `
bgp-server-frr
if ($LASTEXITCODE -eq 0) {
Write-Host "Container started successfully!" -ForegroundColor Green
# Ожидание запуска
Write-Host "Waiting for container to start..." -ForegroundColor Yellow
Start-Sleep -Seconds 10
# Проверка статуса
$status = docker ps --filter "name=$ContainerName" --format "table {{.Status}}"
Write-Host "Container status: $status" -ForegroundColor Cyan
# Проверка FRR статуса
Write-Host "Checking FRR status..." -ForegroundColor Cyan
docker exec $ContainerName vtysh -c "show version" 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host "FRR is running successfully!" -ForegroundColor Green
# Показ BGP статуса
Write-Host "BGP Summary:" -ForegroundColor Cyan
docker exec $ContainerName vtysh -c "show ip bgp summary" 2>$null
# Показ логов
Write-Host "Recent logs:" -ForegroundColor Cyan
docker logs --tail=10 $ContainerName
Write-Host "`nBGP Server (FRR) is ready!" -ForegroundColor Green
Write-Host "To view logs: docker logs -f $ContainerName" -ForegroundColor Cyan
Write-Host "To check BGP status: docker exec $ContainerName vtysh -c 'show ip bgp summary'" -ForegroundColor Cyan
Write-Host "To access FRR CLI: docker exec -it $ContainerName vtysh" -ForegroundColor Cyan
} else {
Write-Host "FRR failed to start properly. Check logs:" -ForegroundColor Red
docker logs $ContainerName
}
} else {
Write-Host "Failed to start container. Check the error above." -ForegroundColor Red
exit 1
}
-189
View File
@@ -1,189 +0,0 @@
#!/bin/bash
# Скрипт запуска BGP сервера на FRR
set -e
echo "Starting BGP Server (FRR)..."
# Создание директорий если не существуют
mkdir -p /app/logs
mkdir -p /app/run
mkdir -p /app/data
mkdir -p /var/run/frr
mkdir -p /etc/frr
# Установка правильных прав доступа
chmod 755 /app/logs
chmod 755 /app/run
chmod 755 /app/data
chmod 755 /var/run/frr
chmod 755 /etc/frr
# Проверка наличия файлов с префиксами
if [ ! -f "/app/data/prefixes.txt" ]; then
echo "Warning: /app/data/prefixes.txt not found. Creating empty file."
echo "# Default prefixes file" > /app/data/prefixes.txt
echo "192.168.1.0/24" >> /app/data/prefixes.txt
fi
# Создание лог-файлов с правильными правами
echo "Creating log files with proper permissions..."
touch /app/logs/prefixes.log
touch /app/logs/frr.log
chmod 666 /app/logs/prefixes.log
chmod 666 /app/logs/frr.log
echo "Prefixes file content:"
cat /app/data/prefixes.txt
echo "---"
# Проверка прав доступа к файлам
echo "Checking file permissions:"
ls -la /app/data/
ls -la /app/scripts/
echo "---"
# Генерация конфигурации из переменных окружения
echo "Generating FRR configuration from environment variables..."
echo "Environment variables:"
env | grep BGP_ || echo "No BGP_ variables found"
echo "---"
python3 /app/scripts/generate_config.py
# Проверка конфигурации
echo "Validating FRR configuration..."
echo "Configuration file content:"
cat /etc/frr/frr.conf
echo "---"
# Проверка синтаксиса конфигурации FRR
if vtysh -c "show running-config" > /dev/null 2>&1; then
echo "FRR configuration validation passed"
else
echo "FRR configuration validation failed"
echo "Full config content:"
cat /etc/frr/frr.conf
exit 1
fi
# Тестовый запуск скрипта загрузки префиксов
echo "Testing prefix loader script..."
python3 /app/scripts/load_prefixes.py --test 2>&1 || echo "Prefix loader test failed (this is normal)"
echo "---"
# Проверка сетевого подключения
echo "Checking network connectivity..."
NEIGHBOR_IP=${BGP_NEIGHBOR_IP:-192.168.1.1}
if ping -c 1 $NEIGHBOR_IP > /dev/null 2>&1; then
echo "Network connectivity to $NEIGHBOR_IP: OK"
else
echo "Warning: Cannot reach $NEIGHBOR_IP. BGP session may not establish."
fi
# Запуск FRR демонов
echo "Starting FRR daemons..."
# Запуск zebra (обязательный демон для FRR)
echo "Starting zebra daemon..."
zebra -d -f /etc/frr/frr.conf -A 127.0.0.1 -z /var/run/frr/zebra.api
sleep 2
# Запуск bgpd
echo "Starting bgpd daemon..."
bgpd -d -f /etc/frr/frr.conf -A 127.0.0.1 -z /var/run/frr/zebra.api
sleep 2
# Проверка что демоны запустились
echo "Checking if FRR daemons are running..."
ps aux | grep -E "(zebra|bgpd)" | grep -v grep || echo "No FRR daemons found in ps"
# Сохранение PID файлов
echo "Saving PID files..."
pgrep zebra > /app/logs/zebra.pid 2>/dev/null || echo "zebra PID not found"
pgrep bgpd > /app/logs/bgpd.pid 2>/dev/null || echo "bgpd PID not found"
# Ожидание запуска
sleep 5
# Проверка статуса через vtysh
echo "Checking FRR status via vtysh..."
if vtysh -c "show version" > /dev/null 2>&1; then
echo "FRR started successfully"
echo "FRR version:"
vtysh -c "show version" 2>/dev/null || echo "Could not get version"
echo "BGP neighbors:"
vtysh -c "show ip bgp neighbors" 2>/dev/null || echo "Could not get BGP neighbors"
echo "BGP summary:"
vtysh -c "show ip bgp summary" 2>/dev/null || echo "Could not get BGP summary"
else
echo "Failed to start FRR. Checking logs:"
cat /app/logs/frr.log 2>/dev/null || echo "No FRR logs found"
exit 1
fi
# Запуск скрипта загрузки префиксов в фоновом режиме
echo "Starting prefix loader in background..."
python3 /app/scripts/load_prefixes.py > /app/logs/prefixes.log 2>&1 &
PREFIX_LOADER_PID=$!
echo $PREFIX_LOADER_PID > /app/logs/prefix_loader.pid
# Запуск монитора в фоновом режиме
echo "Starting monitor in background..."
python3 /app/scripts/monitor.py > /app/logs/monitor.log 2>&1 &
MONITOR_PID=$!
echo $MONITOR_PID > /app/logs/monitor.pid
echo "All services started successfully!"
echo "Recent logs:"
tail -10 /app/logs/prefixes.log 2>/dev/null || echo "No prefix logs yet"
echo "---"
# Функция для graceful shutdown
cleanup() {
echo "Received shutdown signal. Cleaning up..."
# Остановка скриптов
if [ -f "/app/logs/prefix_loader.pid" ]; then
kill $(cat /app/logs/prefix_loader.pid) 2>/dev/null || true
fi
if [ -f "/app/logs/monitor.pid" ]; then
kill $(cat /app/logs/monitor.pid) 2>/dev/null || true
fi
# Отзыв всех префиксов
echo "Withdrawing all prefixes..."
python3 /app/scripts/load_prefixes.py --withdraw > /dev/null 2>&1 || true
# Остановка FRR демонов
echo "Stopping FRR daemons..."
killall bgpd 2>/dev/null || true
killall zebra 2>/dev/null || true
echo "Cleanup completed."
exit 0
}
# Установка обработчиков сигналов
trap cleanup SIGTERM SIGINT
# Ожидание завершения
echo "BGP Server is running. Press Ctrl+C to stop."
while true; do
sleep 10
# Проверка что демоны все еще работают
if ! pgrep zebra > /dev/null; then
echo "ERROR: zebra daemon stopped unexpectedly"
exit 1
fi
if ! pgrep bgpd > /dev/null; then
echo "ERROR: bgpd daemon stopped unexpectedly"
exit 1
fi
done
-66
View File
@@ -1,66 +0,0 @@
# Скрипт остановки BGP Server (FRR)
param(
[string]$ContainerName = "bgp-server",
[switch]$Force
)
Write-Host "=== BGP Server (FRR) Stop Script ===" -ForegroundColor Green
# Проверка существования контейнера
$containerExists = docker ps -a --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
if (-not $containerExists) {
Write-Host "Container $ContainerName not found." -ForegroundColor Yellow
exit 0
}
# Проверка статуса контейнера
$containerRunning = docker ps --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
if ($containerRunning) {
Write-Host "Container $ContainerName is running. Stopping..." -ForegroundColor Yellow
if (-not $Force) {
$response = Read-Host "Do you want to stop the container? (y/N)"
if ($response -ne "y" -and $response -ne "Y") {
Write-Host "Operation cancelled." -ForegroundColor Red
exit 0
}
}
# Graceful shutdown - отзыв префиксов
Write-Host "Withdrawing prefixes..." -ForegroundColor Yellow
docker exec $ContainerName python3 /app/scripts/load_prefixes.py --withdraw 2>$null
# Остановка контейнера
Write-Host "Stopping container..." -ForegroundColor Yellow
docker stop $ContainerName
if ($LASTEXITCODE -eq 0) {
Write-Host "Container stopped successfully!" -ForegroundColor Green
} else {
Write-Host "Failed to stop container." -ForegroundColor Red
exit 1
}
} else {
Write-Host "Container $ContainerName is not running." -ForegroundColor Yellow
}
# Удаление контейнера если требуется
if ($Force) {
Write-Host "Removing container..." -ForegroundColor Yellow
docker rm $ContainerName 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host "Container removed successfully!" -ForegroundColor Green
} else {
Write-Host "Container was already removed or removal failed." -ForegroundColor Yellow
}
} else {
Write-Host "Container stopped but not removed." -ForegroundColor Cyan
Write-Host "To remove container, run: docker rm $ContainerName" -ForegroundColor Cyan
Write-Host "Or use -Force parameter to stop and remove in one command." -ForegroundColor Cyan
}
Write-Host "BGP Server (FRR) stopped successfully!" -ForegroundColor Green
-92
View File
@@ -1,92 +0,0 @@
# Скрипт для безопасного обновления BGP Server контейнера
param(
[string]$ContainerName = "bgp-server",
[string]$ImageName = "git.shts.su/infra/bgp-server:latest",
[string]$DataPath = "./data",
[string]$LogsPath = "./logs",
[switch]$Force
)
Write-Host "=== BGP Server Container Update Script ===" -ForegroundColor Green
# Проверка существования контейнера
$containerExists = docker ps -a --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
if ($containerExists) {
Write-Host "Found existing container: $ContainerName" -ForegroundColor Yellow
if (-not $Force) {
$response = Read-Host "Do you want to update the container? (y/N)"
if ($response -ne "y" -and $response -ne "Y") {
Write-Host "Update cancelled." -ForegroundColor Red
exit 0
}
}
# Остановка и удаление старого контейнера
Write-Host "Stopping container..." -ForegroundColor Yellow
docker stop $ContainerName
Write-Host "Removing container..." -ForegroundColor Yellow
docker rm $ContainerName
} else {
Write-Host "No existing container found. Creating new one..." -ForegroundColor Green
}
# Создание директорий если не существуют
if (-not (Test-Path $DataPath)) {
Write-Host "Creating data directory: $DataPath" -ForegroundColor Yellow
New-Item -ItemType Directory -Path $DataPath -Force | Out-Null
}
if (-not (Test-Path $LogsPath)) {
Write-Host "Creating logs directory: $LogsPath" -ForegroundColor Yellow
New-Item -ItemType Directory -Path $LogsPath -Force | Out-Null
}
# Загрузка нового образа
Write-Host "Pulling latest image..." -ForegroundColor Yellow
docker pull $ImageName
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to pull image. Exiting." -ForegroundColor Red
exit 1
}
# Запуск нового контейнера
Write-Host "Starting new container..." -ForegroundColor Yellow
$currentPath = Get-Location
$dataVolume = "${currentPath}\${DataPath}:/app/data:ro"
$logsVolume = "${currentPath}\${LogsPath}:/app/logs"
docker run -d `
--name $ContainerName `
--restart unless-stopped `
-p 179:179 `
-v $dataVolume `
-v $logsVolume `
$ImageName
if ($LASTEXITCODE -eq 0) {
Write-Host "Container started successfully!" -ForegroundColor Green
# Ожидание запуска
Write-Host "Waiting for container to start..." -ForegroundColor Yellow
Start-Sleep -Seconds 5
# Проверка статуса
$status = docker ps --filter "name=$ContainerName" --format "table {{.Status}}"
Write-Host "Container status: $status" -ForegroundColor Cyan
# Показ логов
Write-Host "Recent logs:" -ForegroundColor Cyan
docker logs --tail=10 $ContainerName
Write-Host "`nContainer update completed successfully!" -ForegroundColor Green
Write-Host "To view logs: docker logs -f $ContainerName" -ForegroundColor Cyan
Write-Host "To check status: docker ps" -ForegroundColor Cyan
} else {
Write-Host "Failed to start container. Check the error above." -ForegroundColor Red
exit 1
}