Skip to content

Commit

Permalink
Switch to official Zabbix Python API
Browse files Browse the repository at this point in the history
The Zabbix project released an official Python API library called
"zabbix_utils" which can replace the current library that this component
is using.

This just does a conversion to the existing synchronous API. The new
Python library also supports an asynchronous API which could be used to
further migrate this plugin.
  • Loading branch information
kruton committed Nov 27, 2024
1 parent dc62ef8 commit b2dbac8
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 19 deletions.
28 changes: 15 additions & 13 deletions homeassistant/components/zabbix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
from urllib.error import HTTPError
from urllib.parse import urljoin

from pyzabbix import ZabbixAPI, ZabbixAPIException, ZabbixMetric, ZabbixSender
import voluptuous as vol
from zabbix_utils import ItemValue, Sender, ZabbixAPI
from zabbix_utils.exceptions import APIRequestError

Check warning on line 16 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L15-L16

Added lines #L15 - L16 were not covered by tests

from homeassistant.const import (
CONF_HOST,
Expand All @@ -39,9 +40,11 @@
_LOGGER = logging.getLogger(__name__)

CONF_PUBLISH_STATES_HOST = "publish_states_host"
CONF_SENDER_PORT = "sender_port"

Check warning on line 43 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L43

Added line #L43 was not covered by tests

DEFAULT_SSL = False
DEFAULT_PATH = "zabbix"
DEFAULT_SENDER_PORT = 10051

Check warning on line 47 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L47

Added line #L47 was not covered by tests

TIMEOUT = 5
RETRY_DELAY = 20
Expand All @@ -60,6 +63,7 @@
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string,
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
vol.Optional(CONF_SENDER_PORT, default=DEFAULT_SENDER_PORT): cv.port,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PUBLISH_STATES_HOST): cv.string,
}
Expand All @@ -86,7 +90,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
try:
zapi = ZabbixAPI(url=url, user=username, password=password)
_LOGGER.debug("Connected to Zabbix API Version %s", zapi.api_version())
except ZabbixAPIException as login_exception:
except APIRequestError as login_exception:

Check warning on line 93 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L93

Added line #L93 was not covered by tests
_LOGGER.error("Unable to login to the Zabbix API: %s", login_exception)
return False
except HTTPError as http_error:
Expand All @@ -104,7 +108,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:

def event_to_metrics(
event: Event, float_keys: set[str], string_keys: set[str]
) -> list[ZabbixMetric] | None:
) -> list[ItemValue] | None:
"""Add an event to the outgoing Zabbix list."""
state = event.data.get("new_state")
if state is None or state.state in (STATE_UNKNOWN, "", STATE_UNAVAILABLE):
Expand Down Expand Up @@ -145,14 +149,14 @@ def event_to_metrics(
float_keys.update(floats)
if len(float_keys) != float_keys_count:
floats_discovery = [{"{#KEY}": float_key} for float_key in float_keys]
metric = ZabbixMetric(
metric = ItemValue(

Check warning on line 152 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L152

Added line #L152 was not covered by tests
publish_states_host,
"homeassistant.floats_discovery",
json.dumps(floats_discovery),
)
metrics.append(metric)
for key, value in floats.items():
metric = ZabbixMetric(
metric = ItemValue(

Check warning on line 159 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L159

Added line #L159 was not covered by tests
publish_states_host, f"homeassistant.float[{key}]", value
)
metrics.append(metric)
Expand All @@ -161,7 +165,7 @@ def event_to_metrics(
return metrics

if publish_states_host:
zabbix_sender = ZabbixSender(zabbix_server=conf[CONF_HOST])
zabbix_sender = Sender(server=conf[CONF_HOST], port=conf[CONF_SENDER_PORT])

Check warning on line 168 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L168

Added line #L168 was not covered by tests
instance = ZabbixThread(zabbix_sender, event_to_metrics)
instance.setup(hass)

Expand All @@ -175,10 +179,8 @@ class ZabbixThread(threading.Thread):

def __init__(
self,
zabbix_sender: ZabbixSender,
event_to_metrics: Callable[
[Event, set[str], set[str]], list[ZabbixMetric] | None
],
zabbix_sender: Sender,
event_to_metrics: Callable[[Event, set[str], set[str]], list[ItemValue] | None],
) -> None:
"""Initialize the listener."""
threading.Thread.__init__(self, name="Zabbix")
Expand Down Expand Up @@ -208,12 +210,12 @@ def _event_listener(self, event: Event[EventStateChangedData]) -> None:
item = (time.monotonic(), event)
self.queue.put(item)

def get_metrics(self) -> tuple[int, list[ZabbixMetric]]:
def get_metrics(self) -> tuple[int, list[ItemValue]]:

Check warning on line 213 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L213

Added line #L213 was not covered by tests
"""Return a batch of events formatted for writing."""
queue_seconds = QUEUE_BACKLOG_SECONDS + self.MAX_TRIES * RETRY_DELAY

count = 0
metrics: list[ZabbixMetric] = []
metrics: list[ItemValue] = []

Check warning on line 218 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L218

Added line #L218 was not covered by tests

dropped = 0

Expand Down Expand Up @@ -243,7 +245,7 @@ def get_metrics(self) -> tuple[int, list[ZabbixMetric]]:

return count, metrics

def write_to_zabbix(self, metrics: list[ZabbixMetric]) -> None:
def write_to_zabbix(self, metrics: list[ItemValue]) -> None:

Check warning on line 248 in homeassistant/components/zabbix/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/__init__.py#L248

Added line #L248 was not covered by tests
"""Write preprocessed events to zabbix, with retry."""

for retry in range(self.MAX_TRIES + 1):
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/zabbix/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"codeowners": [],
"documentation": "https://www.home-assistant.io/integrations/zabbix",
"iot_class": "local_polling",
"loggers": ["pyzabbix"],
"loggers": ["zabbix_utils"],
"quality_scale": "legacy",
"requirements": ["py-zabbix==1.1.7"]
"requirements": ["zabbix-utils==2.0.1"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/zabbix/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import logging
from typing import Any

from pyzabbix import ZabbixAPI
import voluptuous as vol
from zabbix_utils import ZabbixAPI

Check warning on line 10 in homeassistant/components/zabbix/sensor.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/zabbix/sensor.py#L10

Added line #L10 was not covered by tests

from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
Expand Down
6 changes: 3 additions & 3 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1710,9 +1710,6 @@ py-sucks==0.9.10
# homeassistant.components.synology_dsm
py-synologydsm-api==2.5.3

# homeassistant.components.zabbix
py-zabbix==1.1.7

# homeassistant.components.atome
pyAtome==0.1.1

Expand Down Expand Up @@ -3068,6 +3065,9 @@ youtubeaio==1.1.5
# homeassistant.components.media_extractor
yt-dlp[default]==2024.11.04

# homeassistant.components.zabbix
zabbix-utils==2.0.1

# homeassistant.components.zamg
zamg==0.3.6

Expand Down

0 comments on commit b2dbac8

Please sign in to comment.