New supervision

- using fastAPI
- offline/online working
- warning if ZABBIX API is too long
- showing settings
- showing last ack message
- showing procedure
- menu split by SU team
This commit is contained in:
sylvain.chateau
2024-02-05 15:44:27 +01:00
parent f493406b5b
commit f2235d4b45
60 changed files with 10017 additions and 221 deletions

131
routes/alerts.py Normal file
View File

@ -0,0 +1,131 @@
import time
import asyncio
from typing import List, Optional
from fastapi import Request
from schemas import ServerStatuses
from schemas.notes import NoteManager
from schemas.alerts import ContextModel
from schemas.zabbix_client import ZabbixApiNotResponding
from settings import settings
from super_server import app, get_zabbix_client, templates
from utils import read_json_file
from utils.hostgroups import get_hostgroups
from utils.log import logger
from utils.problems import get_problems
def get_ttl_hash(seconds=45):
return round(time.time() / seconds)
async def display_alerts(
request: Request,
team: Optional[str] = None,
tv_mode: bool = False,
):
try:
global zabbix_client
zabbix_client = await get_zabbix_client()
start = asyncio.get_event_loop().time()
if team:
team_list = team.lower().split("+")
else:
team_list = [team.lower() for team in (await get_hostgroups(zabbix_client))]
problems = await get_problems(zabbix_client, ttl_hash=get_ttl_hash())
problems = [
problem for problem in problems if problem.get("hostgroup").lower() in team_list
]
problems = sorted(
problems, key=lambda i: (i["priority"], i["lastchange"]), reverse=True
)
logger.info("[NB ALERTS] - {}".format(len(problems)))
content = await read_json_file(
f"{settings.DATA_DIR}/{settings.ZABBIX_SERVERS_JSON}"
)
check_servers = ServerStatuses.model_validate(content).root
request_duration = asyncio.get_event_loop().time() - start
context = ContextModel(
zabbix_available=True,
zabbix_url=settings.ZABBIX_URL,
tv_mode=tv_mode,
hostgroups=await get_hostgroups(zabbix_client),
check_servers=check_servers,
alerts=problems,
total_alerts=len(problems),
notes=await NoteManager().display_notes(team),
request=request,
teams=settings.TEAMS,
accepted_latency=request_duration < settings.ZABBIX_API_ACCEPTED_LATENCY,
config={
"ZABBIX_API_TIMEOUT": settings.ZABBIX_API_TIMEOUT,
"ZABBIX_API_LIMIT": settings.ZABBIX_API_LIMIT,
"MIN_SEVERITY": settings.SEVERITY,
"ZABBIX_API_ACCEPTED_LATENCY": settings.ZABBIX_API_ACCEPTED_LATENCY,
}
)
return templates.TemplateResponse("index.html", context.dict())
except ZabbixApiNotResponding:
context = ContextModel(
zabbix_available=False,
zabbix_url=settings.ZABBIX_URL,
tv_mode=tv_mode,
notes=await NoteManager().display_notes(team),
request=request,
teams=settings.TEAMS,
accepted_latency=True, # Already showing the API is down
config={
"ZABBIX_API_TIMEOUT": settings.ZABBIX_API_TIMEOUT,
"ZABBIX_API_LIMIT": settings.ZABBIX_API_LIMIT,
"MIN_SEVERITY": settings.SEVERITY,
"ZABBIX_API_ACCEPTED_LATENCY": settings.ZABBIX_API_ACCEPTED_LATENCY,
}
)
return templates.TemplateResponse("index.html", context.dict())
@app.get("/tv")
async def display_alerts_tv_mode(
request: Request,
):
return await display_alerts(
request,
team=None, # or a default team if applicable
tv_mode=True,
)
@app.get("/tv/{team}")
async def display_alerts_without_team(
request: Request,
team: str,
):
return await display_alerts(
request,
team=team,
tv_mode=True,
)
@app.get("/{team}")
async def display_alerts_without_team(
request: Request,
team: str,
):
return await display_alerts(
request,
team=team,
tv_mode=False,
)
@app.get("/")
async def display_alerts_with_team(
request: Request,
):
return await display_alerts(
request,
team=None,
tv_mode=False,
)

29
routes/notes.py Normal file
View File

@ -0,0 +1,29 @@
from typing import Optional
from fastapi import Form
from fastapi.responses import RedirectResponse
from schemas.notes import Note, NoteManager
from super_server import app
@app.post("/post")
async def post_note(
name: str = Form(...),
msg: str = Form(...),
url: Optional[str] = Form(None),
lvl: str = Form(...),
team: str = Form(...),
save: Optional[str] = Form(None),
):
note = Note(name=name, msg=msg, url=url, lvl=lvl, team=team, save=save)
await NoteManager().add_note(note)
return RedirectResponse(url="/", status_code=303)
@app.post("/del")
async def del_note(
note_id: Optional[str] = Form(None), url: Optional[str] = Form(None)
):
await NoteManager().delete_note(note_id)
return RedirectResponse(url="/", status_code=303)