11.03
This commit is contained in:
parent
db52020fa3
commit
fc1e34e727
|
@ -4,6 +4,7 @@ CFG__LOG__LEVEL_TO_FILE=30
|
||||||
CFG__ZABBIX__URL=https://example.com
|
CFG__ZABBIX__URL=https://example.com
|
||||||
CFG__ZABBIX__TOKEN=string
|
CFG__ZABBIX__TOKEN=string
|
||||||
CFG__ZABBIX__MIN_SEVERITY=0
|
CFG__ZABBIX__MIN_SEVERITY=0
|
||||||
|
CFG__ZABBIX__UPD_INTERVAL=60
|
||||||
|
|
||||||
CFG__TGBOT__TOKEN=string
|
CFG__TGBOT__TOKEN=string
|
||||||
CFG__TGBOT__CHAT_ID=00000000
|
CFG__TGBOT__CHAT_ID=00000000
|
||||||
|
|
|
@ -34,10 +34,13 @@ class TelegramBotConfig(BaseModel):
|
||||||
chat_id: int
|
chat_id: int
|
||||||
tread_id: int
|
tread_id: int
|
||||||
|
|
||||||
|
|
||||||
class ZabbixConfig(BaseModel):
|
class ZabbixConfig(BaseModel):
|
||||||
url: str
|
url: str
|
||||||
token: str
|
token: str
|
||||||
min_severity: int
|
min_severity: int
|
||||||
|
upd_interval: int
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
model_config = SettingsConfigDict(
|
model_config = SettingsConfigDict(
|
||||||
|
@ -55,7 +58,6 @@ class Settings(BaseSettings):
|
||||||
zabbix: ZabbixConfig
|
zabbix: ZabbixConfig
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
conf = Settings()
|
conf = Settings()
|
||||||
|
|
||||||
|
|
||||||
|
|
19
main.py
19
main.py
|
@ -1,11 +1,22 @@
|
||||||
import logging as log
|
import logging as log
|
||||||
|
from zabbix import get_active_problems
|
||||||
from config import conf
|
from config import conf
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
def main():
|
|
||||||
print("Hello from zbx-tg-bot!")
|
def main_loop():
|
||||||
|
active_alerts = get_active_problems()
|
||||||
|
for i in active_alerts:
|
||||||
|
print(i)
|
||||||
|
print(len(active_alerts))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
log.info("Starting app")
|
log.info("Starting app")
|
||||||
main()
|
try:
|
||||||
log.info("App stopped")
|
while True:
|
||||||
|
main_loop()
|
||||||
|
sleep(conf.zabbix.upd_interval)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
log.info("Manual app stopped")
|
||||||
|
log.info("App stopped")
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
from .crud import (
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
ping,
|
||||||
|
pop_value,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"get_value",
|
||||||
|
"set_value",
|
||||||
|
"ping",
|
||||||
|
"pop_value",
|
||||||
|
]
|
|
@ -0,0 +1,33 @@
|
||||||
|
import logging as log
|
||||||
|
from .r_helper import RedisManager
|
||||||
|
|
||||||
|
|
||||||
|
async def ping():
|
||||||
|
async with RedisManager() as redis_connect:
|
||||||
|
if redis_connect:
|
||||||
|
result = await redis_connect.client.ping()
|
||||||
|
log.info("Ping - %s", result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
async def set_value(key, value):
|
||||||
|
async with RedisManager() as redis_connect:
|
||||||
|
if redis_connect:
|
||||||
|
await redis_connect.client.set(key, value)
|
||||||
|
log.info("Set %s = %s", key, value)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_value(key):
|
||||||
|
async with RedisManager() as redis_connect:
|
||||||
|
if redis_connect:
|
||||||
|
value = await redis_connect.client.get(key)
|
||||||
|
log.info("Get %s = %s", key, value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
async def pop_value(key):
|
||||||
|
async with RedisManager() as redis_connect:
|
||||||
|
if redis_connect:
|
||||||
|
value = await redis_connect.client.getdel(key)
|
||||||
|
log.info("Get and delete %s = %s", key, value)
|
||||||
|
return value
|
|
@ -0,0 +1,30 @@
|
||||||
|
from redis.asyncio import Redis
|
||||||
|
from redis import ConnectionError
|
||||||
|
from config import conf
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
|
||||||
|
class RedisManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.client = None
|
||||||
|
self.connect_params = {
|
||||||
|
"host": conf.redis.host,
|
||||||
|
"port": conf.redis.port,
|
||||||
|
}
|
||||||
|
if conf.redis.pwd:
|
||||||
|
self.connect_params["password"] = conf.redis.pwd
|
||||||
|
|
||||||
|
async def __aenter__(self):
|
||||||
|
self.client = Redis(**self.connect_params)
|
||||||
|
try:
|
||||||
|
await self.client.ping()
|
||||||
|
log.info("connected to Redis")
|
||||||
|
return self
|
||||||
|
except ConnectionError:
|
||||||
|
log.warning("failed to connect to Redis")
|
||||||
|
self.client = None
|
||||||
|
|
||||||
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
if self.client:
|
||||||
|
await self.client.close()
|
||||||
|
log.info("closed connection to Redis")
|
|
@ -0,0 +1,52 @@
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
from config import conf
|
||||||
|
|
||||||
|
|
||||||
|
async def send_message(
|
||||||
|
message: str,
|
||||||
|
|
||||||
|
) -> dict | None:
|
||||||
|
url = f"https://api.telegram.org/bot{conf.tgbot.token}/sendMessage"
|
||||||
|
params = {
|
||||||
|
"chat_id": conf.tgbot.chat_id,
|
||||||
|
"message_thread_id": conf.tgbot.tread_id,
|
||||||
|
"text": message,
|
||||||
|
}
|
||||||
|
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.post(
|
||||||
|
url,
|
||||||
|
json=params,
|
||||||
|
) as response:
|
||||||
|
log.info(f"Response status: {response.status}")
|
||||||
|
resp = await response.json()
|
||||||
|
if response.status == 200:
|
||||||
|
log.info(f"Message with ID: {resp['result']['message_id']} send")
|
||||||
|
return {
|
||||||
|
"status": response.status,
|
||||||
|
"msg_id": resp["result"]["message_id"],
|
||||||
|
}
|
||||||
|
log.warning(f"Message not send. Response status: {response.status}")
|
||||||
|
|
||||||
|
|
||||||
|
async def del_message(
|
||||||
|
message_id: int,
|
||||||
|
) -> dict | None:
|
||||||
|
url = f"https://api.telegram.org/bot{conf.tgbot.token}/deleteMessage"
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.post(
|
||||||
|
url,
|
||||||
|
json={
|
||||||
|
"chat_id": conf.tgbot.chat_id,
|
||||||
|
"message_id": message_id,
|
||||||
|
},
|
||||||
|
) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
log.info(f"Message ID {message_id} deleted")
|
||||||
|
return {
|
||||||
|
"status": response.status,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
log.warning(f"Response status: {response.status}")
|
|
@ -0,0 +1,6 @@
|
||||||
|
from .zabbix_api import get_active_problems
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"get_active_problems",
|
||||||
|
]
|
|
@ -0,0 +1,39 @@
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
from zabbix_utils import ZabbixAPI
|
||||||
|
|
||||||
|
from config import conf
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_problems():
|
||||||
|
api = ZabbixAPI(url=conf.zabbix.url, token=conf.zabbix.token)
|
||||||
|
try:
|
||||||
|
problems = api.problem.get(
|
||||||
|
output=[
|
||||||
|
"eventid",
|
||||||
|
"suppressed",
|
||||||
|
"severity",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
event_ids = []
|
||||||
|
for problem in problems:
|
||||||
|
if (
|
||||||
|
problem["suppressed"] == "0"
|
||||||
|
and int(problem["severity"]) >= conf.zabbix.min_severity
|
||||||
|
):
|
||||||
|
event_ids.append(problem["eventid"])
|
||||||
|
|
||||||
|
events = api.event.get(
|
||||||
|
selectHosts=["host"],
|
||||||
|
eventids=event_ids,
|
||||||
|
output=[
|
||||||
|
"eventid",
|
||||||
|
"name",
|
||||||
|
"severity",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
for event in events:
|
||||||
|
event["host"] = event.pop("hosts", None)[0]["host"]
|
||||||
|
return events
|
||||||
|
except:
|
||||||
|
log.warning("Get event from zabbix error")
|
Loading…
Reference in New Issue