====== Zabbix ====== ===== task ===== * dashboard con conteggi aggregati (e altri grafici interessanti) * trigger di allarme: * luce accesa da troppo tempo * export dati csv con API * gestire utente non privilegiato su zabbix * VPN robusta che riparte quando il cloud non è raggiungibile * gestire il mancato boot della componente zabbix di hass * /etc/openvpn/iotaiuto.conf ? * come far ripartire la connessione zabbix all'interno di hass ? * esphome: * costruire in power meter con allarme su alexa * costruire un citofono con ESP32 CAM ===== API ===== #!/bin/sh # 1. set connection details url=http://monitor.iotaiuto.it/api_jsonrpc.php user=xxx password=xxx # 2. get authorization token auth=$(curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"user.login\", \"params\": { \"user\": \"$user\", \"password\": \"$password\" }, \"id\": 1, \"auth\": null } " $url | \ jq -r '.result' ) # 3. show triggers in problem state curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"trigger.get\", \"params\": { \"output\": \"extend\", \"selectHosts\": \"extend\", \"filter\": { \"value\": 1 }, \"sortfield\": \"priority\", \"sortorder\": \"DESC\" }, \"auth\": \"$auth\", \"id\": 1 } " $url | \ jq -r '.result' # 4. logout user curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"user.logout\", \"params\": [], \"id\": 1, \"auth\": \"$auth\" } " $url ~  Scaricati  → # 1. set connection details url=http://127.0.0.1/api_jsonrpc.php user=api password=zabbix # 2. get authorization token auth=$(curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"user.login\", \"params\": { \"user\": \"$user\", \"password\": \"$password\" }, \"id\": 1, # 1. set connection details url=http://127.0.0.1/api_jsonrpc.php user=api \ password=zabbix ) # 2. get authorization token auth=$(curl -s -X POST \oblem state -H 'Content-Type: application/json-rpc' \ -d " \ 'Content-Type: application/json-rpc' \ { -d " \ \"jsonrpc\": \"2.0\", \"method\": \"user.login\", \"params\": {: \"trigger.get\", \"user\": \"$user\", \"password\": \"$password\"", }, \"selectHosts\": \"extend\", \"id\": 1,ilter\": { \"auth\": nullalue\": 1 } }, " $url | \sortfield\": \"priority\", jq -r '.result'rder\": \"DESC\" ) }, \"auth\": \"$auth\", # 3. show triggers in problem state curl -s -X POST \ " $u-H 'Content-Type: application/json-rpc' \ -d " \'.result' { \"jsonrpc\": \"2.0\", \"method\": \"trigger.get\", \"params\": {ype: application/json-rpc' \ \"output\": \"extend\", \"selectHosts\": \"extend\", \"filter\": {0\", \"value\": 1ogout\", },ms\": [], \"sortfield\": \"priority\", \"sortorder\": \"DESC\" }, \"auth\": \"$auth\", \"id\": 1 } " $url | \ jq -r '.result' # 4. logout user curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"user.logout\", \"params\": [], \"id\": 1, \"auth\": \"$auth\" } " $url #!/bin/bash # 1. set connection details url=http://monitor.iotaiuto.it/api_jsonrpc.php user=username password=passwd # 2. get authorization token auth=$(curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"user.login\", \"params\": { \"user\": \"$user\", \"password\": \"$password\" }, \"id\": 1, \"auth\": null } " $url | \ jq -r '.result' ) # 3. show triggers in problem state curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"trigger.get\", \"params\": { \"output\": \"extend\", \"selectHosts\": \"extend\", \"filter\": { \"value\": 1 }, \"sortfield\": \"priority\", \"sortorder\": \"DESC\" }, \"auth\": \"$auth\", \"id\": 1 } " $url | \ jq -r '.result' > ../flussi/dati.json jq -r 'del(.[].hosts) | (map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv' ../flussi/dati.json > ../flussi/dati_trigger.csv jq -r '(map(.hosts[] + {"triggerid": .triggerid} | keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv' ../flussi/dati.json > ../flussi/dati_host.csv rm ../flussi/dati.json cat ../flussi/dati_trigger.csv & ../flussi/dati_host.csv # 4. logout user curl -s -X POST \ -H 'Content-Type: application/json-rpc' \ -d " \ { \"jsonrpc\": \"2.0\", \"method\": \"user.logout\", \"params\": [], \"id\": 1, \"auth\": \"$auth\" } " $url ===== Patch infinite componente zabbix ===== class ZabbixThread(threading.Thread): """A threaded event handler class.""" # Rename to TRIES and set to 0 MAX_TRIES = 3 def __init__(self, hass, zabbix_sender, event_to_metrics): """Initialize the listener.""" threading.Thread.__init__(self, name="Zabbix") self.queue = queue.Queue() self.zabbix_sender = zabbix_sender self.event_to_metrics = event_to_metrics self.write_errors = 0 self.shutdown = False self.float_keys = set() self.string_keys = set() def setup(self, hass): """Set up the thread and start it.""" hass.bus.listen(EVENT_STATE_CHANGED, self._event_listener) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self._shutdown) self.start() _LOGGER.debug("Started publishing state changes to Zabbix") def _shutdown(self, event): """Shut down the thread.""" self.queue.put(None) self.join() @callback def _event_listener(self, event): """Listen for new messages on the bus and queue them for Zabbix.""" item = (time.monotonic(), event) self.queue.put(item) def get_metrics(self): """Return a batch of events formatted for writing.""" # Replace MAX_TRIES to TRIES queue_seconds = QUEUE_BACKLOG_SECONDS + self.MAX_TRIES * RETRY_DELAY count = 0 metrics = [] dropped = 0 with suppress(queue.Empty): while len(metrics) < BATCH_BUFFER_SIZE and not self.shutdown: timeout = None if count == 0 else BATCH_TIMEOUT item = self.queue.get(timeout=timeout) count += 1 if item is None: self.shutdown = True else: timestamp, event = item age = time.monotonic() - timestamp if age < queue_seconds: event_metrics = self.event_to_metrics( event, self.float_keys, self.string_keys ) if event_metrics: metrics += event_metrics else: dropped += 1 if dropped: _LOGGER.warning("Catching up, dropped %d old events", dropped) return count, metrics def write_to_zabbix(self, metrics): """Write preprocessed events to zabbix, with retry.""" # while True: for retry in range(self.MAX_TRIES + 1): try: self.zabbix_sender.send(metrics) if self.write_errors: _LOGGER.error("Resumed, lost %d events", self.write_errors) self.write_errors = 0 _LOGGER.debug("Wrote %d metrics", len(metrics)) # Put [self.TRIES = 0] break except OSError as err: # [time.sleep(RETRY_DELAY)] out of [if retry < self.MAX_TRIES:] if retry < self.MAX_TRIES: # Put [self.TRIES += 1] time.sleep(RETRY_DELAY) else: if not self.write_errors: _LOGGER.error("Write error: %s", err) self.write_errors += len(metrics)