move existing stuff to archive dir (for now)

This commit is contained in:
Alex Tau 2025-04-27 20:39:07 +03:00
parent ae1204449c
commit 4fc491f61a
32 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,73 @@
from dataclasses import dataclass
from typing import Optional
import nio
from alerting.enum import AlertType, Severity
from misc import cvars
from misc.config import get_config
@dataclass
class Alert:
alert_type: AlertType
message: str
severity: Severity
html_message: Optional[str] = None
async def get_client() -> nio.AsyncClient:
"""
Returns a Matrix client.
It is better to call get_client once and use it for multiple send_alert calls
"""
matrix_cfg = cvars.config.get().matrix
client = nio.AsyncClient(matrix_cfg.homeserver)
client.access_token = matrix_cfg.access_token
client.user_id = matrix_cfg.user_id
client.device_id = matrix_cfg.device_id
return client
def format_message(alert: Alert) -> str:
match alert.severity:
case Severity.INFO:
severity_emoji = ""
case Severity.WARNING:
severity_emoji = "⚠️"
case Severity.CRITICAL:
severity_emoji = "🆘"
message = f"{severity_emoji} {alert.alert_type} Alert\n{alert.message}"
if alert.html_message:
html_message = f"{severity_emoji} {alert.alert_type} Alert<br>{alert.html_message}"
return message, html_message
else:
return message, None
async def send_alert(alert: Alert) -> None:
try:
client = cvars.matrix_client.get()
except LookupError: # being called standalone
cvars.config.set(get_config())
temp_client = True
client = await get_client()
cvars.matrix_client.set(client)
else:
temp_client = False
room_id = cvars.config.get().matrix.room_id
message, html_message = format_message(alert)
content = {
"msgtype": "m.text",
"body": message,
}
if html_message:
content["format"] = "org.matrix.custom.html"
content["formatted_body"] = html_message
await client.room_send(
room_id=room_id,
message_type="m.room.message",
content=content,
)
if temp_client:
await client.close()

View file

@ -0,0 +1,53 @@
import asyncio
import json
import logging
import os
import signal
import tempfile
from dataclasses import asdict
from alerting.alerts import Alert, send_alert
from misc.common import TMP_DIR
handler_lock = asyncio.Lock()
async def handler():
"""
Is executed when SIGUSR1 is received.
Checks for new alerts, sends them in 10 seconds
"""
alert_counts: list[list] = []
async with handler_lock:
await asyncio.sleep(10)
alert_files = [f for f in os.listdir(str(TMP_DIR)) if f.startswith("alert-")]
for fname in alert_files:
fpath = str(TMP_DIR / fname)
with open(fpath) as f:
alert = Alert(**json.load(f))
for pair in alert_counts:
if alert == pair[0]:
pair[1] += 1
break
else:
alert_counts.append([alert, 1])
os.unlink(fpath)
for pair in alert_counts:
if pair[1] > 1:
pair[0].message += f" ({pair[1]} times)"
pair[0].html_message += f" ({pair[1]} times)"
logging.info(f"Sending delayed alert of type {pair[0].alert_type}")
await send_alert(pair[0])
def send_alert_delayed(alert: Alert) -> None:
"""
Put alert into a temporary file to be sent later.
Intended as an IPC mechanism
"""
alert_json = json.dumps(asdict(alert))
with tempfile.NamedTemporaryFile(prefix="alert-", dir=str(TMP_DIR), delete=False) as af:
af.write(alert_json.encode())
with open(str(TMP_DIR / "pid")) as pf:
pid = int(pf.read().strip())
os.kill(pid, signal.SIGUSR1)

View file

@ -0,0 +1,22 @@
from enum import StrEnum
class AlertType(StrEnum):
TEST = "TEST"
ERROR = "ERROR"
RAM = "RAM"
CPU = "CPU"
TEMP = "TEMP"
VULN = "VULN"
LOGIN = "LOGIN"
SMART = "SMART" # TODO
RAID = "RAID"
DISKS = "DISKS"
UPS = "UPS"
UPDATE = "UPDATE"
class Severity(StrEnum):
INFO = "INFO"
WARNING = "WARNING"
CRITICAL = "CRITICAL"

46
archive-arch/alerting/login.py Executable file
View file

@ -0,0 +1,46 @@
#!/usr/bin/env python3
import getpass
import json
import os
from nio import AsyncClient, LoginResponse
from misc.common import CONFIG_FILE
async def main() -> None:
try:
with open(CONFIG_FILE) as f:
cfg = json.load(f)
if "matrix" in cfg:
print(f"Creds already configured in {CONFIG_FILE}")
raise SystemExit
cfg["matrix"] = {}
except (FileNotFoundError, json.JSONDecodeError):
open(CONFIG_FILE, "w").close()
os.chmod(CONFIG_FILE, 0o600)
cfg = {"matrix": {}}
homeserver = input("Homeserver: ")
user_id = input("User ID: ")
device_name = input("Device name: ")
room_id = input("Room ID: ")
password = getpass.getpass()
client = AsyncClient(homeserver, user_id)
resp = await client.login(password, device_name=device_name)
await client.close()
if isinstance(resp, LoginResponse):
cfg["matrix"]["homeserver"] = homeserver
cfg["matrix"]["user_id"] = resp.user_id
cfg["matrix"]["device_id"] = resp.device_id
cfg["matrix"]["access_token"] = resp.access_token
cfg["matrix"]["room_id"] = room_id
with open(CONFIG_FILE, "w") as f:
json.dump(cfg, f, indent=2)
print(f"Logged in as {resp.user_id}. Credentials saved to {CONFIG_FILE}")
else:
raise Exception(f"Failed to log in: {resp}")