Переписан BGP сервер на FRR
This commit is contained in:
+174
-73
@@ -1,93 +1,194 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Скрипт мониторинга BGP сервера
|
||||
Скрипт мониторинга FRR BGP сервера
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
import json
|
||||
import time
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any
|
||||
|
||||
def run_command(cmd):
|
||||
"""Выполнение команды и возврат результата"""
|
||||
# Настройки
|
||||
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:
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
return result.returncode == 0, result.stdout, result.stderr
|
||||
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:
|
||||
return False, "", str(e)
|
||||
log_message(f"Error running vtysh command '{command}': {e}")
|
||||
return ""
|
||||
|
||||
def check_container_status():
|
||||
"""Проверка статуса Docker контейнера"""
|
||||
success, output, error = run_command("docker ps --filter name=bgp-server --format '{{.Status}}'")
|
||||
if success and output.strip():
|
||||
return True, output.strip()
|
||||
return False, "Container not running"
|
||||
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 check_bgp_session():
|
||||
"""Проверка BGP сессии"""
|
||||
success, output, error = run_command("docker exec bgp-server exabgpcli show neighbor")
|
||||
if success:
|
||||
return True, output
|
||||
return False, "Cannot check BGP session"
|
||||
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 check_prefixes():
|
||||
"""Проверка загруженных префиксов"""
|
||||
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:
|
||||
with open("/app/logs/prefixes.log", "r") as f:
|
||||
lines = f.readlines()
|
||||
return True, f"Found {len(lines)} log entries"
|
||||
except FileNotFoundError:
|
||||
return False, "Prefix log not found"
|
||||
# Проверка процессов 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 check_network_connectivity():
|
||||
"""Проверка сетевого подключения"""
|
||||
success, output, error = run_command("docker exec bgp-server ping -c 1 192.168.1.1")
|
||||
return success, "Network connectivity OK" if success else "Network connectivity failed"
|
||||
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():
|
||||
"""Основная функция мониторинга"""
|
||||
print("=== BGP Server Monitoring ===")
|
||||
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print()
|
||||
"""Основная функция"""
|
||||
log_message("Starting FRR monitor...")
|
||||
|
||||
# Проверка контейнера
|
||||
print("1. Container Status:")
|
||||
status, details = check_container_status()
|
||||
print(f" Status: {'✓ Running' if status else '✗ Stopped'}")
|
||||
print(f" Details: {details}")
|
||||
print()
|
||||
# Создание директории для логов
|
||||
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
|
||||
|
||||
# Проверка сети
|
||||
print("2. Network Connectivity:")
|
||||
net_ok, net_details = check_network_connectivity()
|
||||
print(f" Status: {'✓ OK' if net_ok else '✗ Failed'}")
|
||||
print(f" Details: {net_details}")
|
||||
print()
|
||||
|
||||
# Проверка BGP сессии
|
||||
print("3. BGP Session:")
|
||||
bgp_ok, bgp_details = check_bgp_session()
|
||||
print(f" Status: {'✓ Active' if bgp_ok else '✗ Inactive'}")
|
||||
if bgp_ok:
|
||||
print(f" Details: {bgp_details[:200]}...")
|
||||
else:
|
||||
print(f" Details: {bgp_details}")
|
||||
print()
|
||||
|
||||
# Проверка префиксов
|
||||
print("4. Prefixes:")
|
||||
prefix_ok, prefix_details = check_prefixes()
|
||||
print(f" Status: {'✓ Loaded' if prefix_ok else '✗ Not loaded'}")
|
||||
print(f" Details: {prefix_details}")
|
||||
print()
|
||||
|
||||
# Общий статус
|
||||
overall_status = status and net_ok and bgp_ok and prefix_ok
|
||||
print("=== Overall Status ===")
|
||||
print(f"Status: {'✓ HEALTHY' if overall_status else '✗ UNHEALTHY'}")
|
||||
|
||||
return 0 if overall_status else 1
|
||||
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__":
|
||||
sys.exit(main())
|
||||
main()
|
||||
Reference in New Issue
Block a user