153 lines
4.4 KiB
Python
153 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import itertools
|
|
from typing import Any
|
|
|
|
import httpx
|
|
|
|
|
|
class ZabbixApiClient:
|
|
def __init__(
|
|
self,
|
|
api_url: str,
|
|
api_token: str,
|
|
timeout_seconds: float = 10,
|
|
verify_tls: bool = True,
|
|
) -> None:
|
|
self.api_url = api_url
|
|
self.api_token = api_token
|
|
self._id_counter = itertools.count(1)
|
|
self.client = httpx.AsyncClient(
|
|
timeout=timeout_seconds,
|
|
verify=verify_tls,
|
|
headers={
|
|
"Authorization": f"Bearer {self.api_token}",
|
|
"Content-Type": "application/json-rpc",
|
|
},
|
|
)
|
|
|
|
async def close(self) -> None:
|
|
await self.client.aclose()
|
|
|
|
async def _call(self, method: str, params: dict[str, Any]) -> Any:
|
|
payload = {
|
|
"jsonrpc": "2.0",
|
|
"method": method,
|
|
"params": params,
|
|
"id": next(self._id_counter),
|
|
}
|
|
|
|
response = await self.client.post(self.api_url, json=payload)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
if "error" in data:
|
|
error = data["error"]
|
|
raise RuntimeError(
|
|
f"Zabbix API error: method={method} "
|
|
f"code={error.get('code')} message={error.get('message')} "
|
|
f"data={error.get('data')}"
|
|
)
|
|
|
|
return data.get("result")
|
|
|
|
async def get_trigger(self, trigger_id: str) -> dict[str, Any] | None:
|
|
result = await self._call(
|
|
"trigger.get",
|
|
{
|
|
"output": [
|
|
"triggerid",
|
|
"description",
|
|
"comments",
|
|
"opdata",
|
|
"priority",
|
|
"state",
|
|
"status",
|
|
"value",
|
|
],
|
|
"triggerids": [trigger_id],
|
|
"selectHosts": ["hostid", "host", "name"],
|
|
"selectItems": ["itemid", "name", "key_", "lastvalue", "units", "value_type"],
|
|
"selectTags": "extend",
|
|
"limit": 1,
|
|
},
|
|
)
|
|
return result[0] if result else None
|
|
|
|
async def get_item(self, item_id: str) -> dict[str, Any] | None:
|
|
result = await self._call(
|
|
"item.get",
|
|
{
|
|
"output": [
|
|
"itemid",
|
|
"name",
|
|
"key_",
|
|
"lastvalue",
|
|
"units",
|
|
"value_type",
|
|
"status",
|
|
],
|
|
"itemids": [item_id],
|
|
"selectHosts": ["hostid", "host", "name"],
|
|
"selectTags": "extend",
|
|
"limit": 1,
|
|
},
|
|
)
|
|
return result[0] if result else None
|
|
|
|
async def get_event(self, event_id: str) -> dict[str, Any] | None:
|
|
result = await self._call(
|
|
"event.get",
|
|
{
|
|
"output": [
|
|
"eventid",
|
|
"objectid",
|
|
"clock",
|
|
"name",
|
|
"severity",
|
|
"value",
|
|
"acknowledged",
|
|
],
|
|
"eventids": [event_id],
|
|
"selectHosts": ["hostid", "host", "name"],
|
|
"selectTags": "extend",
|
|
"limit": 1,
|
|
},
|
|
)
|
|
return result[0] if result else None
|
|
|
|
async def get_host(self, host_id: str) -> dict[str, Any] | None:
|
|
result = await self._call(
|
|
"host.get",
|
|
{
|
|
"output": ["hostid", "host", "name"],
|
|
"hostids": [host_id],
|
|
"selectTags": "extend",
|
|
"limit": 1,
|
|
},
|
|
)
|
|
return result[0] if result else None
|
|
|
|
async def get_history(
|
|
self,
|
|
item_id: str,
|
|
value_type: int,
|
|
time_from: int,
|
|
time_till: int,
|
|
limit: int = 500,
|
|
) -> list[dict[str, Any]]:
|
|
result = await self._call(
|
|
"history.get",
|
|
{
|
|
"output": ["clock", "value"],
|
|
"history": value_type,
|
|
"itemids": [item_id],
|
|
"time_from": time_from,
|
|
"time_till": time_till,
|
|
"sortfield": "clock",
|
|
"sortorder": "ASC",
|
|
"limit": limit,
|
|
},
|
|
)
|
|
return result or []
|