Skip to content

Commit be18a83

Browse files
kossusukkalaf
andauthored
Add support for I2PD application monitoring (#586)
* SNMP extend agent for application I2Pd * Better error reporting to LibreNMS. Minor tweaks * Update i2pd-stats.py * Fixed code layout as Super-Linter suggested --------- Co-authored-by: Neil Lathwood <[email protected]>
1 parent ec78820 commit be18a83

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

snmp/i2pd-stats.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env python3
2+
3+
# i2pd-stats.py
4+
# SNMP Extend-agent for exporting I2Pd statistics to LibreNMS
5+
#
6+
# Inspired from i2pdctl:
7+
# https://github.com/PurpleI2P/i2pd-tools
8+
#
9+
# Run script and it will print JSON-blob into stdout
10+
# Set I2P Control socket params below!
11+
#
12+
# Installation:
13+
# 1. copy this file to /etc/snmp/i2pd-stats.py
14+
# 2. chmod +x /etc/snmp/i2pd-stats.py
15+
# 3. edit /etc/snmp/snmpd.conf and add following line:
16+
# extend i2pd /etc/snmp/i2pd-stats.py
17+
# 4. systemctl restart snmpd.service
18+
#
19+
# author: Kossusukka <[email protected]>
20+
21+
import json
22+
import os
23+
import ssl
24+
import urllib.error
25+
import urllib.parse
26+
import urllib.request
27+
28+
######### CONFIGURATION ##############
29+
I2PC_URL = "https://127.0.0.1:7650/"
30+
I2PC_PASS = "itoopie"
31+
##### END OF CONFIGURATION ###########
32+
33+
34+
# Do not change! Must match LibreNMS version
35+
JSONVER = "1"
36+
37+
38+
class I2PControl(object):
39+
"""Talk to I2PControl API"""
40+
41+
def __init__(self, url, password):
42+
self.url = url
43+
self.password = password
44+
self._token = None
45+
46+
@property
47+
def token(self):
48+
"""Cached authentication token"""
49+
if not self._token:
50+
try:
51+
self._token = self.do_post(
52+
self.url,
53+
json.dumps(
54+
{
55+
"id": 1,
56+
"method": "Authenticate",
57+
"params": {"API": 1, "Password": self.password},
58+
"jsonrpc": "2.0",
59+
}
60+
),
61+
)["result"]["Token"]
62+
except KeyError:
63+
post_error("1", "Invalid I2PControl password or token!")
64+
exit(1)
65+
return self._token
66+
67+
def do_post(self, url, data):
68+
"""HTTP(S) handler"""
69+
req = urllib.request.Request(url, data=data.encode())
70+
try:
71+
with urllib.request.urlopen(
72+
req, context=ssl._create_unverified_context(), timeout=5
73+
) as f:
74+
resp = f.read().decode("utf-8")
75+
except urllib.error.URLError:
76+
post_error("2", "Unable to connect I2PControl socket!")
77+
exit(1)
78+
except TimeoutError:
79+
post_error("3", "Connection timed out to I2PControl socket!")
80+
exit(1)
81+
return json.loads(resp)
82+
83+
def request(self, method, params):
84+
"""Execute authenticated request"""
85+
params["Token"] = self.token
86+
return self.do_post(
87+
self.url,
88+
json.dumps({"id": 1, "method": method, "params": params, "jsonrpc": "2.0"}),
89+
)
90+
91+
92+
def post_error(code: str, message: str):
93+
"""Post error code+message as JSON for LibreNMS"""
94+
resp_err = {"data": "", "version": JSONVER, "error": code, "errorString": message}
95+
96+
print(json.dumps(resp_err))
97+
98+
99+
def main():
100+
# Craft JSON request for I2PC
101+
JSON_REQUEST = json.loads(
102+
'{ "i2p.router.uptime": "", "i2p.router.net.status": "", "i2p.router.net.bw.inbound.1s": "", "i2p.router.net.bw.inbound.15s": "", "i2p.router.net.bw.outbound.1s": "", "i2p.router.net.bw.outbound.15s": "", "i2p.router.net.tunnels.participating": "", "i2p.router.net.tunnels.successrate": "", "i2p.router.netdb.knownpeers": "", "i2p.router.netdb.activepeers": "", "i2p.router.net.total.received.bytes": "", "i2p.router.net.total.sent.bytes": "" }'
103+
)
104+
105+
ctl = I2PControl(I2PC_URL, I2PC_PASS)
106+
107+
resp = ctl.request("RouterInfo", JSON_REQUEST)["result"]
108+
resp_full = {"data": resp, "version": JSONVER, "error": "0", "errorString": ""}
109+
110+
print(json.dumps(resp_full))
111+
112+
113+
if __name__ == "__main__":
114+
main()

0 commit comments

Comments
 (0)