forked from zabbix/community-templates
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request zabbix#148 from blind-oracle/add_template_nut
Add template_nut (network ups tools)
- Loading branch information
Showing
8 changed files
with
1,107 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# zabbix-nut | ||
|
||
Zabbix template & script to monitor UPS exposed through NUT (https://networkupstools.org). | ||
|
||
Currently only basic parameters are gathered (which are available on my UPS). Feel free to do PR to add other stuff, preferably in form of low-level discovery so that if it's not available - items are not created. | ||
|
||
Single Python script that emits all information needed for discovery & data gathering in a single JSON. | ||
All items are defined as `Dependent` and extract relevant data using JSONPath queries. | ||
|
||
<details> | ||
<summary>Click to expand JSON example</summary> | ||
|
||
```json | ||
{ | ||
"vars": { | ||
"ups": { | ||
"battery.charge": 100, | ||
"battery.voltage": 27.7, | ||
"battery.voltage.high": 27.7, | ||
"battery.voltage.low": 21, | ||
"battery.voltage.nominal": 24.0, | ||
"device.mfr": "", | ||
"device.model": "1500VA", | ||
"device.type": "ups", | ||
"driver.name": "blazer_usb", | ||
"driver.parameter.pollinterval": 2, | ||
"driver.parameter.port": "auto", | ||
"driver.parameter.synchronous": "no", | ||
"driver.version": "2.7.4", | ||
"driver.version.internal": 0.12, | ||
"input.current.nominal": 6.0, | ||
"input.frequency": 50.0, | ||
"input.frequency.nominal": 50, | ||
"input.voltage": 221.7, | ||
"input.voltage.fault": 0.5, | ||
"input.voltage.nominal": 230, | ||
"output.voltage": 223.0, | ||
"ups.beeper.status": "enabled", | ||
"ups.delay.shutdown": 30, | ||
"ups.delay.start": 180, | ||
"ups.firmware": "", | ||
"ups.load": 26, | ||
"ups.mfr": "", | ||
"ups.model": "1500VA", | ||
"ups.productid": 5161, | ||
"ups.status": "OL", | ||
"ups.type": "offline / line interactive", | ||
"ups.vendorid": 665 | ||
} | ||
}, | ||
"list": [ | ||
{ | ||
"name": "ups" | ||
} | ||
] | ||
} | ||
``` | ||
</details> | ||
|
||
## Features | ||
|
||
- Low level discovery of UPS | ||
- Items: | ||
- Voltage & Frequency | ||
- Battery voltage & charge | ||
- UPS Status | ||
- Triggers: | ||
- Voltage out of bounds | ||
- UPS status is not healthy | ||
- UPS is calibrating/in bypass/charging | ||
- Optional authentication (fill `{$NUT_USERNAME}` and `{$NUT_PASSWORD}` macros to enable) | ||
- Zabbix agent passive checks. Can be converted to active if needed. | ||
- Macros to customize triggers | ||
|
||
## Requirements | ||
|
||
- Tested on Zabbix 5.2, but should work on 4.2+ | ||
- Python3 | ||
|
||
## Installation | ||
|
||
- Place `nut.conf` in `/etc/zabbix/zabbix_agentd.d` | ||
- Place `nut.py` in `/etc/zabbix/scripts` | ||
You can put it into any other place, but then you'll have to adjust `nut.conf` | ||
- Restart `zabbix-agentd` | ||
- Import `template_nut.xml` | ||
- You're good to go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
UserParameter=nut[*],/etc/zabbix/scripts/nut.py $1 $2 $3 $4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import sys | ||
import socket | ||
import json | ||
|
||
|
||
username, password = "", "" | ||
|
||
argc = len(sys.argv) | ||
|
||
if argc in (3, 5): | ||
host, port = sys.argv[1], int(sys.argv[2]) | ||
if argc == 5: | ||
username, password = sys.argv[3], sys.argv[4] | ||
else: | ||
print(f"Usage: {sys.argv[0]} <host> <port> [<user> <pass>]") | ||
sys.exit(1) | ||
|
||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
sock.connect((host, port)) | ||
sock.settimeout(5) | ||
|
||
|
||
def conv(s): | ||
try: | ||
s = int(s) | ||
except BaseException: | ||
try: | ||
s = float(s) | ||
except BaseException: | ||
return s | ||
|
||
return s | ||
|
||
|
||
def read_reply(cmd): | ||
sock.sendall(str.encode(cmd + "\n")) | ||
r = [] | ||
|
||
while True: | ||
s = sock.recv(8192).decode('ascii') | ||
|
||
for l in s.split("\n"): | ||
if l == "" or l.startswith("BEGIN"): | ||
continue | ||
elif l.startswith("END"): | ||
return r | ||
|
||
r.append(l) | ||
|
||
|
||
def send_cmd(cmd, expect): | ||
sock.sendall(str.encode(cmd)) | ||
r = sock.recv(1024).decode('ascii') | ||
if r != expect: | ||
raise Exception(f"{r} != {expect}\n") | ||
|
||
|
||
def list_ups(): | ||
ups = [] | ||
for l in read_reply("LIST UPS"): | ||
t = l.split(" ", 2) | ||
ups.append(t[1]) | ||
return ups | ||
|
||
|
||
def read_vars(ups): | ||
vars = {} | ||
for l in read_reply(f"LIST VAR {ups}"): | ||
t = l.split(" ", 3) | ||
vars[t[2]] = conv(t[3][1:len(t[3]) - 1]) | ||
return vars | ||
|
||
|
||
if username != "": | ||
send_cmd(f"USERNAME {username}\n", "OK\n") | ||
send_cmd(f"PASSWORD {password}\n", "OK\n") | ||
|
||
r = {'vars': {}} | ||
ups_list = list_ups() | ||
r['list'] = [{'name': x} for x in ups_list] | ||
|
||
for u in ups_list: | ||
r['vars'][u] = read_vars(u) | ||
|
||
sock.sendall(b'LOGOUT\n') | ||
sock.close() | ||
|
||
json.dump(r, sys.stdout, indent=1) |
Oops, something went wrong.