55import sys
66import threading
77import time
8+ import requests
89
9- from ipaddress import IPv4Network , IPv6Network
10+ from ipaddress import IPv4Address , IPv6Address , ip_address
1011from functools import lru_cache
1112from typing import Dict , Union , Any , List , Optional
1213from easysnmp import Session
@@ -23,8 +24,11 @@ class ConfigFileNotFoundError(Error):
2324 """File could not be found on disk."""
2425
2526
27+ requests .packages .urllib3 .disable_warnings ()
28+
2629SNMP_TO_INFLUX_CONFIG_OS_ENV = "SNMP_TO_INFLUX_CONFIG_FILE"
2730SNMP_TO_INFLUX_CONFIG_DEFAULT_LOCATION = "./scraper.yaml"
31+ _POLLING_FREQUENCY = datetime .timedelta (seconds = 60 )
2832
2933
3034@dataclasses .dataclass
@@ -38,7 +42,7 @@ class Device:
3842
3943 hostname : str
4044 community : str
41- ip : Union [IPv4Network , IPv6Network ]
45+ ip : Union [IPv4Address , IPv6Address ]
4246 username : str
4347 password : str
4448
@@ -49,7 +53,7 @@ def from_dict(cls, device_cfg: Dict[str, str]) -> "Device":
4953 community = device_cfg ["community" ],
5054 username = device_cfg ["username" ],
5155 password = device_cfg ["password" ],
52- ip = device_cfg ["ip" ],
56+ ip = ip_address ( device_cfg ["ip" ]) ,
5357 )
5458
5559
@@ -179,29 +183,33 @@ def fetch_config_from_disk() -> str:
179183 ) from e
180184
181185
182- def SNMPpollv2 (Device ):
186+ def SNMPpollv2 (device_cfg : Device ) -> bool :
187+ """Polls a device via SNMPv2."""
183188 try :
184- session = Session (hostname = Device .ip , community = Device .community , version = 2 )
185- return pollDevice (session , Device .hostname )
189+ session = Session (
190+ hostname = str (device_cfg .ip ), community = device_cfg .community , version = 2
191+ )
192+ return pollDevice (session , device_cfg .hostname )
186193 except Exception as e :
187- return "ERROR - SNMPv2 error" + str (e )
194+ raise ValueError ( "ERROR - SNMPv2 error" + str (e )) from e
188195
189196
190- def SNMPpollv3 (Device ):
197+ def SNMPpollv3 (device_cfg : Device ) -> bool :
198+ """Polls a device via SNMPv3."""
191199 try :
192200 session = Session (
193- hostname = Device .ip ,
201+ hostname = str ( device_cfg .ip ) ,
194202 version = 3 ,
195203 security_level = "auth_with_privacy" ,
196- security_username = Device .username ,
204+ security_username = device_cfg .username ,
197205 auth_protocol = "SHA" ,
198- auth_password = Device .password ,
206+ auth_password = device_cfg .password ,
199207 privacy_protocol = "AES" ,
200- privacy_password = Device .password ,
208+ privacy_password = device_cfg .password ,
201209 )
202210 return pollDevice (session , hostname )
203211 except Exception as e :
204- return "ERROR - SNMPv3 error" + str (e )
212+ raise ValueError ( "ERROR - SNMPv3 error" + str (e )) from e
205213
206214
207215_ifXEntry = "1.3.6.1.2.1.31.1.1.1"
@@ -223,8 +231,8 @@ def SNMPpollv3(Device):
223231}
224232
225233
226- def pollDevice (session : Session , hostname : str ) -> Dict [ str , str ] :
227- influxdb_cfg = Config . from_dict ( load_config ()). influxdb
234+ def pollDevice (session : Session , hostname : str ) -> bool :
235+
228236 interfaces = dict ()
229237 for interface in session .walk (f"{ _ifXEntry } .{ _ifName } " ):
230238 interfaces [interface .value ] = {
@@ -256,42 +264,49 @@ def pollDevice(session: Session, hostname: str) -> Dict[str, str]:
256264 },
257265 }
258266 ]
267+ return upload_to_influx (dbpayload )
259268
260- client = InfluxDBClient (
261- influxdb_cfg .uri ,
262- 443 ,
263- influxdb_cfg .username ,
264- influxdb_cfg .password ,
265- influxdb_cfg .database ,
266- ssl = True ,
267- )
268- print (dbpayload )
269- try :
270- client .write_points (dbpayload )
271- except Exception as e :
272- print (e )
273269
274- return 0
270+ def upload_to_influx (payload : Any ) -> bool :
271+ """Uploads a payload to influxDB."""
272+ influxdb_cfg = Config .from_dict (load_config ()).influxdb
273+ client = InfluxDBClient (
274+ influxdb_cfg .uri ,
275+ 443 ,
276+ influxdb_cfg .username ,
277+ influxdb_cfg .password ,
278+ influxdb_cfg .database ,
279+ ssl = True ,
280+ )
281+ print (payload )
282+ try :
283+ client .write_points (payload )
284+ return True
285+ except InfluxDBClientError as e :
286+ print (e )
287+ return False
275288
276289
277- def StartPoll (device ):
290+ def StartPoll (device : Config ) -> Dict [str , str ]:
291+ """Polls a device via SNMPv2 or SNMPV3 depending on configuration."""
278292 if device .username :
279293 return SNMPpollv3 (device )
280- elif device .community :
294+ if device .community :
281295 return SNMPpollv2 (device )
282- else :
283- return "Invalid device entity"
296+ raise ValueError (f"Invalid device configuration: { device } " )
284297
285298
286299def main ():
287- """Starts the periodic scraper ."""
300+ """Starts the periodic scraper."""
288301 DeviceList = Config .from_dict (load_config ()).devices
289302
290303 while True :
291- for device in DeviceList .devices :
292- thread = threading .Thread (target = StartPoll , args = (device ,))
293- thread .start ()
294- time .sleep (60 )
304+ polling_threads = [
305+ threading .Thread (target = StartPoll , args = (device ,))
306+ for device in DeviceList .devices
307+ ]
308+ _ = [thread .start () for thread in polling_threads ]
309+ time .sleep (_POLLING_FREQUENCY .total_seconds ())
295310
296311
297312if __name__ == "__main__" :
0 commit comments