diff --git a/cont/cisco/lob.py b/cont/cisco/lob.py index 57df8f3..1d83d8b 100644 --- a/cont/cisco/lob.py +++ b/cont/cisco/lob.py @@ -1,61 +1,52 @@ import os, asyncio -from models.ciscoModel import snmpPyCiscoData -from snmp.walker import walk_column_v3 +from models.ciscoModel import C3750XciscoData +from models.snmpTimeOut import SNMPTimeoutError +from snmp.walker import walk_column_v3, walk_lobotomy_column_v3 from typing import Annotated, Final # SNMP from pysnmp.hlapi.v3arch.asyncio import * -# SNMP ENV------------------------------------------- -ROUND_PREC: Final[int] = int(os.getenv("ROUND_PREC", 2)) - -SNMPUSER: Final[str] = os.getenv("SNMPUSER", None) -SNMPPRIVKEY: Final[str] = os.getenv("SNMPPRIVKEY", None) -SNMPAUTHKEY: Final[str] = os.getenv("SNMPAUTHKEY", None) -# Right now I'll only use SHA -# SNMPAUTHPROTO: Final[str] = os.getenv("SNMPAUTHPROTO", "SHA") -# SNMPPRIVPROTO: Final[str] = os.getenv("SNMPPRIVPROTO", "SHA") -SNMPORT: Final[int] = int(os.getenv("SNMPORT", 161)) - - -# Check if SNMP ENV are empty -if not SNMPUSER or not SNMPPRIVKEY or not SNMPAUTHKEY: - raise Exception("No SNMP user or/and PrivAuth passed") - - -# SNMP -USMUSRDATA = UsmUserData( - userName=SNMPUSER, - authKey=SNMPAUTHKEY, - privKey=SNMPPRIVKEY, - authProtocol=usmHMACSHAAuthProtocol, - privProtocol=usmAesCfb128Protocol, - ) - - - # Cisco -async def ciscoPoolRemote(remoteIP: str, queueToInsrt: asyncio.Queue): +async def lobGetRemote( + remoteIP: str, + queueToInsrt: asyncio.Queue, + SNMPUSER: str, + SNMPAUTHKEY: str, + SNMPPRIVKEY: str, + ROUND_PREC: int = 2, + SNMPORT: int = 161 + ): print("starting work on ", remoteIP) + + + # SNMPUSRDATA + USMUSRDATA = UsmUserData( + userName=SNMPUSER, + authKey=SNMPAUTHKEY, + privKey=SNMPPRIVKEY, + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol, + ) + snmpEngine = SnmpEngine() + iterator = get_cmd( snmpEngine, USMUSRDATA, await UdpTransportTarget.create((remoteIP, SNMPORT)), ContextData(), # Get Hostname - ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")), - # + ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")), # 0 ) - - print(iterator) - errorIndication, errorStatus, errorIndex, varBinds = await iterator - + if errorIndication: - print(errorIndication) - + print(f"\n\n{errorIndication}\n\n") + if "No SNMP response received before timeout" in str(errorIndication): + raise SNMPTimeoutError(f"Host {remoteIP} timed out while walking") + raise RuntimeError(errorIndication) elif errorStatus: print( "{} at {}".format( @@ -67,18 +58,56 @@ async def ciscoPoolRemote(remoteIP: str, queueToInsrt: asyncio.Queue): for varBind in varBinds: print(" = ".join([x.prettyPrint() for x in varBind])) + + + + + + try: + # System data + systemData = await walk_lobotomy_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.9.9.13.1.3", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) + + # Uptime in seconds + uptimeSeconds = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.6.3.10.2.1.3", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) + + # Last 5 second CPU usage + last5SecCPUsage = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.9.2.1.56", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) + + # Last minute CPU usage + last1MinCPUsage = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.9.2.1.58", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) + + # Last 5 minutes CPU usage + last5MinCPUsage = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.9.2.1.58", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) + except SNMPTimeoutError as e: + print(f"{e}\nContinuing regardless...") + return 1 + except RuntimeError as e: + print(f"SNMP error on {remoteIP}: {e}") + return 1 + snmpEngine.close_dispatcher() - returObj = snmpPyCiscoData() + returObj = C3750XciscoData( + hostname=varBinds[0][-1], + + systemStatus=systemData[0].split(" ")[2], #[2], + + systemTemp=systemData[1], #[2][-1], + + last5SecUsage=last5SecCPUsage[0], + + last1MinUsage=last1MinCPUsage[0], + + last5MinUsage=last5MinCPUsage[0], + + uptimeS=int(uptimeSeconds[0]) - returObj( - hostname="X" ) returnDict = { "source": "CISCO", + "device": "3750X", "value": returObj, - "type": "snmpPyCiscoData" + "type": "C3750XciscoData" } - # return returnObj - await queueToInsrt.put(returnDict) \ No newline at end of file + await queueToInsrt.put(returnDict) diff --git a/cont/db/Influx.py b/cont/db/Influx.py index d1097be..a369bd1 100644 --- a/cont/db/Influx.py +++ b/cont/db/Influx.py @@ -68,4 +68,100 @@ async def fluxIDRACWriter( return 1 return 0 - # return {"STATUS": "succesfully inserted to InfluxDB"} \ No newline at end of file + # return {"STATUS": "succesfully inserted to InfluxDB"} + + + + + +async def fluxDataWriter( + inpDict: dict + ) -> int: + + """ + Insert temperature data into InfluxDB + :inputQueue: Asyncio Queue that has what is needed to be sent + """ + # inputQueue have multiple such Dicts + # { + # "source": "IDRAC", + # "value": returnObj, + # "type": "snmpPyIDRACData" + # } + + if write_fluxdb_api is None: + return 2 + + match inpDict["source"]: + + case "CISCO": + + match inpDict["device"]: + case "3750X": + # Prep InfluxDB data + inflxdb_3750X_Data_To_Send = ( + influxdb_client.Point(INFXLUXDB_MEASUEREMENT) + .tag("SOURCE", inpDict["source"]) + .tag("DEVICE", inpDict["device"]) + .tag("TYPE", inpDict["type"]) + .tag("HOSTNAME", inpDict["value"].hostname) + .field("systemStatus", inpDict["value"].systemStatus) + .field("systemTemp", inpDict["value"].systemTemp) + .field("last5SecUsage", inpDict["value"].last5SecUsage) + .field("last1MinUsage", inpDict["value"].last1MinUsage) + .field("last5MinUsage", inpDict["value"].last5MinUsage) + .field("uptimeS", inpDict["value"].uptimeS) + ) + + try: + write_fluxdb_api.write(bucket=INFLUXBCKT, org=INFLUXORG, record=inflxdb_3750X_Data_To_Send) + except Exception as e: + print(e) + return 1 + + case "NEXUS": + ... + return 0 + case _: + print(f"{inpDict['device']} is not supported.\nOnly '3750X' and 'Nexus' are.") + return 1 + + case "IDRAC": + # Prep InfluxDB data + inflxdb_IDRAC_Data_To_Send = ( + influxdb_client.Point(INFXLUXDB_MEASUEREMENT) + .tag("SOURCE", inpDict["source"]) + .tag("TYPE", inpDict["type"]) + .tag("HOSTNAME", inpDict["value"].hostname) + .field("PowerDrawPSU1", inpDict["value"].powerDrawPSU1) + .field("PowerDrawPSU2", inpDict["value"].powerDrawPSU2) + .field("TotalBoardPower", inpDict["value"].powerDrawBoard) + .field("VoltagePSU1", inpDict["value"].voltagePSU1) + .field("VoltagePSU2", inpDict["value"].voltagePSU2) + .field("InletTemperature", inpDict["value"].inletTemp) + .field("ExhaustTemperature", inpDict["value"].exhaustTemp) + .field("TemperatureCPU1", inpDict["value"].cpu1Temp) + .field("TemperatureCPU2", inpDict["value"].cpu2Temp) + .field("UptimeInSeconds", inpDict["value"].uptimeS) + .field("UptimeInHours", inpDict["value"].uptimeH) + .field("UptimeInDays", inpDict["value"].uptimeD) + ) + + try: + write_fluxdb_api.write(bucket=INFLUXBCKT, org=INFLUXORG, record=inflxdb_IDRAC_Data_To_Send) + except Exception as e: + print(e) + return 1 + case "FANS": + await eng.execute( + # changeMeLater + t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}] + ) + + case _: + print(f"No such source of data as {inpDict['source']}") + return 1 + + return 0 + + # asyncio.sleep(5) \ No newline at end of file diff --git a/cont/db/MariaDB.py b/cont/db/MariaDB.py index 4c8d33e..c8f0c91 100644 --- a/cont/db/MariaDB.py +++ b/cont/db/MariaDB.py @@ -3,7 +3,8 @@ from sqlalchemy.ext.asyncio import create_async_engine from typing import Annotated, Final from dataclasses import asdict from models.idracModel import snmpPyIDRACData -from models.sqlTable import idracMeasurement +from models.ciscoModel import C3750XciscoData +from models.sqlTable import idracMeasurement, C3750XMeasurement # SQL ENV------------------------------------------- USESQL: Final[int] = int(os.getenv("USESQL", 0)) @@ -27,7 +28,7 @@ else: engine = None -async def sqlIDRACDataWriter( +async def sqlDataWriter( inpDict: dict ) -> int: @@ -44,10 +45,36 @@ async def sqlIDRACDataWriter( match inpDict["source"]: case "CISCO": - await eng.execute( - # changeMeLater - t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}] - ) + + match inpDict["device"]: + case "3750X": + payload = inpDict["value"] # snmpPyIDRACData + row = asdict(payload) + + await eng.execute( + C3750XMeasurement.insert(), + [row] + ) + return 0 + + case "NEXUS": + payload = inpDict["value"] # snmpPyIDRACData + row = asdict(payload) + + await eng.execute( + NexusMeasurement.insert(), + [row] + ) + return 0 + case _: + print(f"{inpDict['device']} is not supported.\nOnly '3750X' and 'Nexus' are.") + return 1 + + + # await eng.execute( + # # changeMeLater + # t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}] + # ) case "IDRAC": payload = inpDict["value"] # snmpPyIDRACData row = asdict(payload) @@ -73,4 +100,4 @@ async def sqlIDRACDataWriter( return 0 - # asyncio.sleep(5) \ No newline at end of file + # asyncio.sleep(5) diff --git a/cont/db/collectiveWriter.py b/cont/db/collectiveWriter.py index 03d5980..151e820 100644 --- a/cont/db/collectiveWriter.py +++ b/cont/db/collectiveWriter.py @@ -1,7 +1,7 @@ import asyncio, os from typing import Annotated, Final -from db.Influx import fluxIDRACWriter -from db.MariaDB import sqlIDRACDataWriter +from db.Influx import fluxDataWriter +from db.MariaDB import sqlDataWriter USEINFLUX: Final[int] = int(os.getenv("USEINFLUX", 1)) USESQL: Final[int] = int(os.getenv("USESQL", 0)) @@ -15,7 +15,7 @@ async def ALLdbIDRACWriter(inputQueue: asyncio.Queue) -> None: try: if USESQL: - sqlResult = await sqlIDRACDataWriter(qu) + sqlResult = await sqlDataWriter(qu) match sqlResult: case 1: print("Wrong source") @@ -26,7 +26,7 @@ async def ALLdbIDRACWriter(inputQueue: asyncio.Queue) -> None: case _: print("Inserted in SQL") if USEINFLUX: - fluxResult = await fluxIDRACWriter(qu) + fluxResult = await fluxDataWriter(qu) match fluxResult: case 1: print("could not insert") diff --git a/cont/mainRE.py b/cont/mainRE.py index 0b2181d..12abe14 100644 --- a/cont/mainRE.py +++ b/cont/mainRE.py @@ -8,39 +8,81 @@ from db.collectiveWriter import ALLdbIDRACWriter # idrac SNMP from idrac import idrac78, idrac9 # Cisco hosts -# from cisco import lob, nyater +from cisco import lob, nyater + +# SNMP ENV------------------------------------------- +ROUND_PREC: Final[int] = int(os.getenv("ROUND_PREC", 2)) + +SNMPUSER: Final[str] = os.getenv("SNMPUSER", None) +SNMPPRIVKEY: Final[str] = os.getenv("SNMPPRIVKEY", None) +SNMPAUTHKEY: Final[str] = os.getenv("SNMPAUTHKEY", None) +# Right now I'll only use SHA +# SNMPAUTHPROTO: Final[str] = os.getenv("SNMPAUTHPROTO", "SHA") +# SNMPPRIVPROTO: Final[str] = os.getenv("SNMPPRIVPROTO", "SHA") +SNMPORT: Final[int] = int(os.getenv("SNMPORT", 161)) + + +# Check if SNMP ENV are empty +if not SNMPUSER or not SNMPPRIVKEY or not SNMPAUTHKEY: + raise Exception("No SNMP user or/and PrivAuth passed") # Program ENV--------------------------------------- try: - IDRAC78_HOST_LIST: Final[list] = os.getenv("IDRAC78_HOST_LIST", None).split(";") - IDRAC9_HOST_LIST: Final[list] = os.getenv("IDRAC9_HOST_LIST", None).split(";") - CISCO_HOST_LIST: Final[list] = os.getenv("CISCO_HOST_LIST", None).split(";") + IDRAC78_HOST_LIST: Final[list] = os.getenv("IDRAC78_HOST_LIST", []).split(";") + IDRAC9_HOST_LIST: Final[list] = os.getenv("IDRAC9_HOST_LIST", []).split(";") except: raise Exception("No IDRAC hosts variable") +try: + CISCO_3750_HOST_LIST: Final[list] = os.getenv("CISCO_3750_HOST_LIST", []).split(";") +except: + print("No 3750-X devices passed.\nContinuing with what is available.\n") + CISCO_3750_HOST_LIST = [] +try: + CISCO_NEXUS_HOST_LIST: Final[list] = os.getenv("CISCO_NEXUS_HOST_LIST", []).split(";") +except: + print("No Nexus devices passed.\nContinuing with what is available.\n") + CISCO_NEXUS_HOST_LIST = [] GET_INTERVAL: Final[int] = int(os.getenv("GET_INTERVAL", 60)) # Flightchecks------------------------------------------- # if HOST_LIST empty, raise Exception No hosts passed -if not IDRAC78_HOST_LIST and not CISCO_HOST_LIST and not IDRAC9_HOST_LIST: - raise Exception("No hosts passed\nExiting...") +# if not IDRAC78_HOST_LIST and not IDRAC9_HOST_LIST: +# raise Exception("No IDRAC hosts passed\nExiting...") # for host in HOST_LIST check if valid IP and create a list with strings -for idrac78Host in IDRAC78_HOST_LIST: + +try: + for idrac78Host in IDRAC78_HOST_LIST: + try: + ip = str(ipaddress.IPv4Address(idrac78Host)) + except ValueError: + raise Exception(f" IP {ip} for IDRAC7/8 devices is invalid.\nExiting...") +except: + IDRAC78_HOST_LIST = [] + + +for cisco3750Host in CISCO_3750_HOST_LIST: try: - ip = str(ipaddress.IPv4Address(idrac78Host)) - except ValueError: - raise Exception(f" IP {ip} for IDRAC7/8 devices is invalid.\nExiting...") -for ciscoHost in CISCO_HOST_LIST: - try: - ip = str(ipaddress.IPv4Address(ciscoHost)) + ip = str(ipaddress.IPv4Address(cisco3750Host)) except ValueError: raise Exception(f" IP {ip} for Cisco devices is invalid.\nExiting...") -for idrac9Host in IDRAC9_HOST_LIST: + + +for ciscoNexusHost in CISCO_NEXUS_HOST_LIST: try: - ip = str(ipaddress.IPv4Address(idrac9Host)) + ip = str(ipaddress.IPv4Address(ciscoNexusHost)) except ValueError: - raise Exception(f" IP {ip} for IDRAC9 devices is invalid.\nExiting...") + raise Exception(f" IP {ip} for Cisco devices is invalid.\nExiting...") + +try: + for idrac9Host in IDRAC9_HOST_LIST: + try: + ip = str(ipaddress.IPv4Address(idrac9Host)) + except ValueError: + raise Exception(f" IP {ip} for IDRAC9 devices is invalid.\nExiting...") +except: + IDRAC9_HOST_LIST = [] # Done under "Program ENV" on line ~18 @@ -49,48 +91,43 @@ for idrac9Host in IDRAC9_HOST_LIST: async def main(): - # Queues for storing states that a database needs to insert - # idracQueue = asyncio.Queue() - # ciscoQueue = asyncio.Queue() - # fanQueue = asyncio.Queue() mainQueue = asyncio.Queue(maxsize=225) asyncio.create_task(ALLdbIDRACWriter(mainQueue)) + print("Starting tasks") + while True: # IDRAC part async with asyncio.TaskGroup() as tg: for Idrac78IP in IDRAC78_HOST_LIST: - tg.create_task(idrac78.idrac7_8PoolRemote_v3(Idrac78IP, mainQueue)) + tg.create_task(idrac78.idrac7_8PoolRemote_v3( + Idrac78IP, mainQueue, + SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY, ROUND_PREC, SNMPORT)) + for Idrac9IP in IDRAC9_HOST_LIST: - tg.create_task(idrac9.idrac9PoolRemote_v3(Idrac9IP, mainQueue)) + tg.create_task(idrac9.idrac9PoolRemote_v3( + Idrac9IP, mainQueue, + SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY, ROUND_PREC, SNMPORT)) # FANS - # tg.create_task(idracPoolRemoteFAN_v3(IdracIP, mainQueue)) + # tg.create_task(idracPoolRemoteFAN_v3(IdracIP, mainQueue)) # CISCO devices - # for CiscoIP in CISCO_HOST_LIST: - # tg.create_task(ciscoPoolRemote(CiscoIP, mainQueue)) + for cisco3750Xdev in CISCO_3750_HOST_LIST: + tg.create_task(lob.lobGetRemote( + cisco3750Xdev, mainQueue, + SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY, ROUND_PREC, SNMPORT)) + + # for ciscoNexusDev in CISCO_NEXUS_HOST_LIST: + # tg.create_task(nyater( + # ciscoNexusDev, mainQueue, + # SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY, ROUND_PREC, SNMPORT)) await asyncio.sleep(GET_INTERVAL) - # yes = asyncio.run(idracPoolRemote_v3("192.168.20.7")) - # fan = asyncio.run(idracPoolRemoteFAN_v3("192.168.20.7")) - - # print("fanThingy") - # # print(fan) - # for thing in fan: - # print(fan[thing]["name"], fan[thing]["rpm"]) - # for thing in fan: - # print(thing) - - # print("for loop") - # print(yes) - - # print("End of code") - if __name__ == "__main__": # qu = asyncio.Queue() # asyncio.run(idracPoolRemote_v3("192.168.20.7", qu)) @@ -100,28 +137,3 @@ if __name__ == "__main__": # loop = asyncio.get_event_loop() # task = loop.create_task(main()) - - - - -# poolRemote(HOST_LIST[0]) -# while True: -# tasks = [poolRemote(ip) for ip in HOST_LIST] -# results = await asyncio.gather(*tasks) - -# print(results) - -# await asyncio.sleep(20) - - -# Create connections for MySQL and InfluxDB - -# functions for inserting data into two DBs - - -# DNS lookup if the user passed a hostname -# if not given a specific IP for DNS server, fallback to 1.1.1.1 - -# maybe a class? -# store last value and check if it wasn't sent already to the database - diff --git a/cont/models/ciscoModel.py b/cont/models/ciscoModel.py index 9eaca25..d3aa6e9 100644 --- a/cont/models/ciscoModel.py +++ b/cont/models/ciscoModel.py @@ -2,6 +2,34 @@ from dataclasses import dataclass from typing import Optional, Annotated, Dict + + +@dataclass +class C3750XciscoData(): + """Dataclass for snmp data""" + hostname: str + systemStatus: str + systemTemp: int + last5SecUsage: int + last1MinUsage: int + last5MinUsage: int + uptimeS: int + # uptimeH: float + + + + def __str__(self): + return ( + f"{self.hostname}\n" + f"System status: {self.systemStatus} \n" + f"System temp: {self.systemTemp} C\n" + f"Last 5 second CPU usage: {self.last5SecUsage} %\n" + f"Last 1 minute CPU usage: {self.last1MinUsage} %\n" + f"Last 5 minutes CPU usage: {self.last5MinUsage} %\n" + f"Uptime: {self.uptimeS} Seconds\n" + ) + + @dataclass class snmpPyCiscoData(): """Dataclass for snmp data""" diff --git a/cont/models/sqlTable.py b/cont/models/sqlTable.py index c468099..b75f65f 100644 --- a/cont/models/sqlTable.py +++ b/cont/models/sqlTable.py @@ -25,4 +25,38 @@ idracMeasurement = Table( Column("uptimeS", BigInteger), Column("uptimeH", Numeric(8, 3)), Column("uptimeD", Numeric(8, 3)), +) + + +C3750XMeasurement = Table( + "C3750XMeasurement", + metadata, + Column("id", Integer, primary_key=True, autoincrement=True), + Column("time_stamp", TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), nullable=False), + Column("hostname", String(64), nullable=False), + + Column("systemStatus", String(64)), + Column("systemTemp", Numeric(7, 2)), + Column("last5SecUsage", Numeric(7, 2)), + Column("last1MinUsage", Numeric(7, 2)), + Column("last5MinUsage", Numeric(7, 2)), + + Column("uptimeS", BigInteger), +) + + +NexusMeasurement = Table( + "NexusMeasurement", + metadata, + Column("id", Integer, primary_key=True, autoincrement=True), + Column("time_stamp", TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), nullable=False), + Column("hostname", String(64), nullable=False), + + Column("systemStatus", String(64)), + Column("systemTemp", Numeric(7, 2)), + Column("last5SecUsage", Numeric(7, 2)), + Column("last1MinUsage", Numeric(7, 2)), + Column("last5MinUsage", Numeric(7, 2)), + + Column("uptimeS", BigInteger), ) \ No newline at end of file diff --git a/cont/snmp/walker.py b/cont/snmp/walker.py index 4237c47..6678bc2 100644 --- a/cont/snmp/walker.py +++ b/cont/snmp/walker.py @@ -20,14 +20,6 @@ if not SNMPUSER or not SNMPPRIVKEY or not SNMPAUTHKEY: raise Exception("No SNMP user or/and PrivAuth passed") -# SNMP -USMUSRDATA = UsmUserData( - userName=SNMPUSER, - authKey=SNMPAUTHKEY, - privKey=SNMPPRIVKEY, - authProtocol=usmHMACSHAAuthProtocol, - privProtocol=usmAesCfb128Protocol, - ) @@ -43,7 +35,23 @@ USMUSRDATA = UsmUserData( # The value is always a string so it needs to be converted to int if needed -async def walk_column_v3(snmpEngine, remoteIP: str, base_oid: str) -> dict: +async def walk_column_v3( + snmpEngine, + remoteIP: str, + base_oid: str, + SNMPUSER: str, + SNMPAUTHKEY: str, + SNMPPRIVKEY: str + ) -> dict: + + # SNMP + USMUSRDATA = UsmUserData( + userName=SNMPUSER, + authKey=SNMPAUTHKEY, + privKey=SNMPPRIVKEY, + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol, + ) rows = {} async for errInd, errStat, errIdx, varBinds in walk_cmd( snmpEngine, @@ -66,4 +74,44 @@ async def walk_column_v3(snmpEngine, remoteIP: str, base_oid: str) -> dict: idx = int(oid.prettyPrint().split(".")[-1]) rows[idx] = val.prettyPrint() - return rows \ No newline at end of file + return rows + + +async def walk_lobotomy_column_v3( + snmpEngine, + remoteIP: str, + base_oid: str, + SNMPUSER: str, + SNMPAUTHKEY: str, + SNMPPRIVKEY: str + ) -> list: + + # SNMP + USMUSRDATA = UsmUserData( + userName=SNMPUSER, + authKey=SNMPAUTHKEY, + privKey=SNMPPRIVKEY, + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol, + ) + elements = [] + async for errInd, errStat, errIdx, varBinds in walk_cmd( + snmpEngine, + USMUSRDATA, + await UdpTransportTarget.create((remoteIP, SNMPORT)), + ContextData(), + ObjectType(ObjectIdentity(base_oid)), + lexicographicMode=False, + ): + if errInd: + print(f"\n\n{errInd}\n\n") + if "No SNMP response received before timeout" in str(errInd): + raise SNMPTimeoutError(f"Host {remoteIP} timed out while walking {base_oid}") + raise RuntimeError(errInd) + if errStat: + raise RuntimeError(errStat.prettyPrint()) + + for oid, val in varBinds: + elements.append(val.prettyPrint()) + + return elements \ No newline at end of file diff --git a/tables.sql b/tables.sql index c03bea6..33136da 100644 --- a/tables.sql +++ b/tables.sql @@ -59,6 +59,24 @@ CREATE TABLE IDRACmeasurement ( INDEX idx_host_time (hostname, time_stamp) ); + + +-- New universal table type +CREATE TABLE C3750XMeasurement ( + id MEDIUMINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + time_stamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + hostname VARCHAR(64) NOT NULL, + systemStatus VARCHAR(64) NOT NULL, + systemTemp DECIMAL(7,2) NOT NULL, + last5SecUsage DECIMAL(7,2) NOT NULL, + last1MinUsage DECIMAL(7,2) NOT NULL, + last5MinUsage DECIMAL(7,2) NOT NULL, + uptimeS BIGINT, + + INDEX idx_time (time_stamp), + INDEX idx_host_time (hostname, time_stamp) +); + CREATE TABLE fansHOSTNAMEHERE ( id MEDIUMINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,