1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
# wget https://static.tp-link.com/upload/software/2022/202209/20220915/privateMibs(20220831).zip
# cp -v *.mib /home/eden/.snmp/mibs
# sudo apt install snmp
# sudo apt-get install snmp-mibs-downloader
import subprocess
from dataclasses import dataclass
import dotenv
import os
import pandas
import configparser
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
DIVIDE_BY_10_ENDPOINTS = ["tpPoePower", "tpPoeVoltage"]
@dataclass
class SNMPReading:
endpoint: str
port: int
reading: float
@classmethod
def from_string(cls, str_):
s = str_.split()
if len(s) != 4:
raise Exception("Couldn't parse")
endpoint_and_port, _, type_, reading = s
endpoint, port = endpoint_and_port.split(".")
if reading.isdigit():
reading = int(reading)
if endpoint in DIVIDE_BY_10_ENDPOINTS:
reading = reading / 10
return cls(endpoint, int(port), reading)
def get_alternate_name(port, host):
port_names = configparser.ConfigParser()
port_names.read(os.path.join(os.path.dirname(__file__), "omada-switches.conf"))
port_names = {int(k): v for k, v in port_names[host].items()}
try:
return port_names[port]
except KeyError:
return port
def snmp_walk(host):
proc = subprocess.Popen(
["snmpwalk", "-Os", "-c", "tplink", "-v", "2c", "-m", "TPLINK-POWER-OVER-ETHERNET-MIB", host, "tplinkPowerOverEthernetMIB"],
stdout = subprocess.PIPE
)
out = []
while True:
line = proc.stdout.readline()
if not line:
break
try:
out.append(SNMPReading.from_string(line.rstrip().decode()))
except Exception:
pass
return out
def readings_to_points(readings, switch_host):
points = []
df = pandas.DataFrame(readings)
df["port_name"] = df["port"].apply(get_alternate_name, args = (switch_host, ))
for p, group_df in df.groupby(["port", "port_name"]):
port, port_name = p
fields = dict(zip(group_df['endpoint'], group_df['reading']))
points.append({
"measurement": "switch_status",
"tags": {"port": port, "port_name": port_name, "switch_host": switch_host, "type": "Omada"},
"fields": fields
})
return points
def get_points():
if not os.path.exists(os.path.join(os.path.dirname(__file__), "omada-switches.conf")):
raise FileNotFoundError("Couldn't find config file")
switches = configparser.ConfigParser()
switches.read(os.path.join(os.path.dirname(__file__), "omada-switches.conf"))
points = []
for switch_host in switches.sections():
points += readings_to_points(snmp_walk(switch_host), switch_host)
return points
if __name__ == "__main__":
import mikrotik
points = get_points()
print(points)
mikrotik.append(points)
|