mirror of
https://forgejo.altau.su/lego/lego-monitoring.git
synced 2026-03-10 04:41:10 +00:00
alerting framework
This commit is contained in:
parent
0184a47345
commit
d3c8b000b0
6 changed files with 145 additions and 1 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
.venv
|
.venv
|
||||||
__pycache__
|
__pycache__
|
||||||
|
alerting/credentials.json
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -1 +1,17 @@
|
||||||
# lego-monitoring
|
# lego-monitoring
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
* `pacman -S libolm`
|
||||||
|
* `pip -r requirements.txt`
|
||||||
|
|
||||||
|
## Configuring
|
||||||
|
|
||||||
|
* Run `alerting/login.py` once to generate credentials file
|
||||||
|
* Invite the bot account to the room (you have to accept the invite manually)
|
||||||
|
* Set room ID in `alerting/common.py`
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
* `prettyprint.py` -- check and print all sensors
|
||||||
|
* TODO -- launch service
|
||||||
|
|
|
||||||
78
alerting/alerts.py
Normal file
78
alerting/alerts.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import json
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum, StrEnum
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import aiofiles
|
||||||
|
import nio
|
||||||
|
|
||||||
|
from alerting.common import CREDS_FILE, ROOM_ID
|
||||||
|
|
||||||
|
|
||||||
|
class AlertType(StrEnum):
|
||||||
|
TEST = "TEST"
|
||||||
|
RAM = "RAM" # TODO
|
||||||
|
CPU = "CPU" # TODO
|
||||||
|
TEMP = "TEMP" # TODO
|
||||||
|
LOGIN = "LOGIN" # TODO
|
||||||
|
SMART = "SMART" # TODO
|
||||||
|
RAID = "RAID" # TODO
|
||||||
|
|
||||||
|
|
||||||
|
class Severity(Enum):
|
||||||
|
INFO = 1
|
||||||
|
WARNING = 2
|
||||||
|
CRITICAL = 3
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Alert:
|
||||||
|
alert_type: AlertType
|
||||||
|
message: str
|
||||||
|
severity: Severity
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
async with aiofiles.open(CREDS_FILE) as f:
|
||||||
|
contents = await f.read()
|
||||||
|
creds = json.loads(contents)
|
||||||
|
client = nio.AsyncClient(creds["homeserver"])
|
||||||
|
client.access_token = creds["access_token"]
|
||||||
|
client.user_id = creds["user_id"]
|
||||||
|
client.device_id = creds["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}"
|
||||||
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
async def send_alert(alert: Alert, client: Optional[nio.AsyncClient] = None) -> None:
|
||||||
|
if client is None:
|
||||||
|
temp_client = True
|
||||||
|
client = await get_client()
|
||||||
|
else:
|
||||||
|
temp_client = False
|
||||||
|
message = format_message(alert)
|
||||||
|
await client.room_send(
|
||||||
|
room_id=ROOM_ID,
|
||||||
|
message_type="m.room.message",
|
||||||
|
content={
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": message,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if temp_client:
|
||||||
|
await client.close()
|
||||||
8
alerting/common.py
Normal file
8
alerting/common.py
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
CREDS_FILE = (Path(os.path.dirname(os.path.realpath(__file__))) / "credentials.json").resolve()
|
||||||
|
HOMESERVER = "https://matrix.altau.su"
|
||||||
|
USER_ID = "@AlertBot:altau.su"
|
||||||
|
DEVICE_NAME = "lego"
|
||||||
|
ROOM_ID = "!aSCaiSJfLHslrJrHiJ:altau.su"
|
||||||
40
alerting/login.py
Executable file
40
alerting/login.py
Executable file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import getpass
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from common import CREDS_FILE, DEVICE_NAME, HOMESERVER, USER_ID
|
||||||
|
from nio import AsyncClient, LoginResponse
|
||||||
|
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
if os.path.exists(CREDS_FILE):
|
||||||
|
print(f"Creds already configured in {CREDS_FILE}")
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
client = AsyncClient(HOMESERVER, USER_ID)
|
||||||
|
password = getpass.getpass()
|
||||||
|
resp = await client.login(password, device_name=DEVICE_NAME)
|
||||||
|
await client.close()
|
||||||
|
if isinstance(resp, LoginResponse):
|
||||||
|
open(CREDS_FILE, "w").close()
|
||||||
|
os.chmod(CREDS_FILE, 0o600)
|
||||||
|
with open(CREDS_FILE, "w") as f:
|
||||||
|
json.dump(
|
||||||
|
{
|
||||||
|
"homeserver": HOMESERVER,
|
||||||
|
"user_id": resp.user_id,
|
||||||
|
"device_id": resp.device_id,
|
||||||
|
"access_token": resp.access_token,
|
||||||
|
},
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
print(f"Logged in as {resp.user_id}. Credentials saved to {CREDS_FILE}")
|
||||||
|
else:
|
||||||
|
raise Exception(f"Failed to log in: {resp}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
colorama==0.4.6
|
colorama==0.4.6
|
||||||
psutil==5.9.8
|
psutil==5.9.8
|
||||||
|
matrix-nio[e2e]==0.24.0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue