Files
ISCM_agent/main.py

111 lines
3.4 KiB
Python
Raw Normal View History

2026-03-17 07:46:35 +00:00
"""
MTG Agent лёгкий HTTP агент для каждой ноды.
Читает метрики MTG контейнеров через Docker SDK и отдаёт через REST API.
Порт: 8081 (внутри docker сети)
"""
import os
from fastapi import FastAPI, HTTPException, Header
from fastapi.responses import JSONResponse
import docker
app = FastAPI(title="MTG Agent", version="1.0.0")
AGENT_TOKEN = os.environ.get("AGENT_TOKEN", "mtg-agent-secret")
client = docker.from_env()
def get_mtg_containers():
try:
return [c for c in client.containers.list(all=True) if c.name.startswith("mtg-") and c.name != "mtg-agent"]
except Exception:
return []
def get_connections(container) -> int:
try:
container.reload()
pid = container.attrs.get("State", {}).get("Pid", 0)
if not pid:
return 0
MTG_PORT_HEX = "0C38" # 3128 in hex
tcp6_path = f"/proc/{pid}/net/tcp6"
try:
with open(tcp6_path) as f:
lines = f.readlines()[1:]
except Exception:
tcp_path = f"/proc/{pid}/net/tcp"
with open(tcp_path) as f:
lines = f.readlines()[1:]
remote_ips = set()
for line in lines:
parts = line.split()
if len(parts) < 4:
continue
state = parts[3]
local_addr = parts[1]
remote_addr = parts[2]
local_port = local_addr.split(":")[1] if ":" in local_addr else ""
if state == "01" and local_port == MTG_PORT_HEX:
remote_ip = remote_addr.rsplit(":", 1)[0] if ":" in remote_addr else remote_addr
remote_ips.add(remote_ip)
return len(remote_ips)
except Exception:
return 0
def get_traffic(container) -> dict:
try:
stats = container.stats(stream=False)
nets = stats.get("networks", {})
total_rx = sum(v.get("rx_bytes", 0) for v in nets.values())
total_tx = sum(v.get("tx_bytes", 0) for v in nets.values())
def fmt(b: int) -> str:
if b >= 1_073_741_824:
return f"{b / 1_073_741_824:.2f}GB"
if b >= 1_048_576:
return f"{b / 1_048_576:.2f}MB"
if b >= 1024:
return f"{b / 1024:.2f}KB"
return f"{b}B"
return {"rx": fmt(total_rx), "tx": fmt(total_tx), "rx_bytes": total_rx, "tx_bytes": total_tx}
except Exception:
return {"rx": "", "tx": "", "rx_bytes": 0, "tx_bytes": 0}
@app.get("/health")
def health():
return {"status": "ok", "version": "1.0.0"}
@app.get("/metrics")
def metrics(x_agent_token: str = Header(default="")):
if x_agent_token != AGENT_TOKEN:
raise HTTPException(status_code=401, detail="Unauthorized")
containers = get_mtg_containers()
result = []
for c in containers:
name = c.name
running = c.status == "running"
devices = get_connections(c) if running else 0
traffic = get_traffic(c) if running else {"rx": "", "tx": "", "rx_bytes": 0, "tx_bytes": 0}
result.append({
"name": name,
"running": running,
"status": c.status,
"connections": devices,
"devices": devices,
"is_online": devices > 0,
"traffic": traffic,
})
return JSONResponse({"containers": result, "total": len(result)})