feat: add automatic cluster sync and IPAM discovery with configurable intervals, firewall log file parsing, and enhanced flow prioritization

Add RuntimeSettingsRead/RuntimeSettingsUpdate schemas with auto_node_sync_enabled/auto_node_sync_interval_minutes/auto_ipam_sync_enabled/auto_ipam_sync_interval_minutes/last_node_auto_sync_at/last_ipam_auto_sync_at fields, implement firewall_log_lines_from_files to parse /var/log/pve-firewall.log with max_lines limit and error collection, extend collect_firewall_log
This commit is contained in:
2026-07-10 08:13:40 +02:00
parent 1531b7ea47
commit 67eee0662a
10 changed files with 493 additions and 65 deletions
+24 -6
View File
@@ -107,7 +107,16 @@ def setup_setting(db: Session) -> SystemSetting:
def runtime_setting(db: Session) -> SystemSetting:
setting = db.get(SystemSetting, "runtime")
if not setting:
setting = SystemSetting(key="runtime", value={"flow_retention_hours": 24})
setting = SystemSetting(
key="runtime",
value={
"flow_retention_hours": 24,
"auto_node_sync_enabled": False,
"auto_node_sync_interval_minutes": 60,
"auto_ipam_sync_enabled": False,
"auto_ipam_sync_interval_minutes": 60,
},
)
db.add(setting)
db.commit()
db.refresh(setting)
@@ -116,7 +125,15 @@ def runtime_setting(db: Session) -> SystemSetting:
def runtime_settings_payload(db: Session) -> RuntimeSettingsRead:
value = runtime_setting(db).value or {}
return RuntimeSettingsRead(flow_retention_hours=int(value.get("flow_retention_hours") or 24))
return RuntimeSettingsRead(
flow_retention_hours=int(value.get("flow_retention_hours") or 24),
auto_node_sync_enabled=bool(value.get("auto_node_sync_enabled", False)),
auto_node_sync_interval_minutes=int(value.get("auto_node_sync_interval_minutes") or 60),
auto_ipam_sync_enabled=bool(value.get("auto_ipam_sync_enabled", False)),
auto_ipam_sync_interval_minutes=int(value.get("auto_ipam_sync_interval_minutes") or 60),
last_node_auto_sync_at=datetime.fromisoformat(value["last_node_auto_sync_at"]) if value.get("last_node_auto_sync_at") else None,
last_ipam_auto_sync_at=datetime.fromisoformat(value["last_ipam_auto_sync_at"]) if value.get("last_ipam_auto_sync_at") else None,
)
def require_super_admin(user: User) -> None:
@@ -1313,7 +1330,7 @@ cat > "$CONFIG_DIR/config.json" <<'JSON'
"node_id": "{node.id}",
"node_name": "{node.name}",
"interval_seconds": 30,
"flow_limit": 500,
"flow_limit": 2000,
"packet_flow_collector": true,
"packet_flow_window_seconds": 10,
"firewall_log_collector": true,
@@ -1448,7 +1465,7 @@ def agent_heartbeat(payload: AgentHeartbeat, authorization: str | None = Header(
): flow
for flow in db.scalars(select(TrafficFlow).where(TrafficFlow.node_id == node.id)).all()
}
for raw_flow in payload.flows[:1000]:
for raw_flow in payload.flows[:5000]:
source_ip = str(raw_flow.get("source_ip") or "")
destination_ip = str(raw_flow.get("destination_ip") or "")
if not source_ip or not destination_ip:
@@ -1517,7 +1534,7 @@ async def workload_insights(workload_id: str, _: CurrentUser, db: Session = Depe
select(TrafficFlow)
.where((TrafficFlow.source_ip.in_(workload_ips)) | (TrafficFlow.destination_ip.in_(workload_ips)))
.order_by((TrafficFlow.state == "blocked").desc(), TrafficFlow.updated_at.desc())
.limit(50)
.limit(1000)
).all()
for flow in flows:
source_owner = ip_owners.get(flow.source_ip)
@@ -2068,7 +2085,8 @@ def update_settings(payload: RuntimeSettingsUpdate, user: CurrentUser, db: Sessi
require_super_admin(user)
setting = runtime_setting(db)
old_values = dict(setting.value or {})
setting.value = {**old_values, "flow_retention_hours": payload.flow_retention_hours}
changes = payload.model_dump(exclude_unset=True, exclude_none=True)
setting.value = {**old_values, **changes}
commit_or_400(db)
write_audit(
db,