import os, asyncio from models.idracModel import snmpPyIDRACData from models.snmpTimeOut import SNMPTimeoutError from snmp.walker import walk_column_v3 from typing import Annotated, Final # SNMP from pysnmp.hlapi.v3arch.asyncio import * # IDRAC get data for snmpPyIDRACData class async def idrac9PoolRemote_v3( remoteIP: str, queueToInsrt: asyncio.Queue, SNMPUSER: str, SNMPAUTHKEY: str, SNMPPRIVKEY: str, ROUND_PREC: int = 2, SNMPORT: int = 161 ): print("starting work on ", remoteIP) # SNMP 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(), # Hostname (sysName.0) ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")), #0 # Uptime in seconds ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.2.5.0")), #1 ) errorIndication, errorStatus, errorIndex, mainVarBinds = await iterator if errorIndication: if errorIndication == "No SNMP response received before timeout": print(f"Host {remoteIP} timed out.\nContinuing...") snmpEngine.close_dispatcher() return 1 print(errorIndication) elif errorStatus: print( "{} at {}".format( errorStatus.prettyPrint(), errorIndex and mainVarBinds[int(errorIndex) - 1][0] or "?", ) ) else: for oid, val in mainVarBinds: print(f"{oid.prettyPrint()} = {val.prettyPrint()}") try: # Get PSU1 current, [PSU2 current], total board power draw in watts currentsCurrentResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.600.30.1.6", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) # PSU1 OID name, [PSU2 OID name], system board power draw currentsNamesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.600.30.1.8", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) # CPU1 OID name .1, [CPU2 OID name], Inlet temp OID name, [Exhaust temp OID name] sensorNamesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.700.20.1.8", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) # CPU1 temp, [CPU2 temp], Inlet temp, [Exhaust temp] sensorValuesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.700.20.1.6", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY) # .1.3.6.1.4.1.674.10892.5.4.600.20.1.6.1 voltResult = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.600.20.1.6.1", 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() hasExhaust = any("exhaust" in str(thing).lower() for thing in sensorNamesResults.values()) hasCPU2 = any("cpu2" in str(thing).lower() for thing in sensorNamesResults.values()) hasPSU2 = any("ps2" in str(thing).lower() for thing in currentsNamesResults.values()) # Exhaust CPU1 and CPU2 temp exhaustTemp = None inletTemp = None cpu2Temp = None if len(currentsCurrentResults) == 1 and int(mainVarBinds[1][-1]) == 0: exhaustTemp = int(sensorValuesResults[2]) / 10 inletTemp = int(sensorValuesResults[1]) / 10 cpu1Temp = None elif hasExhaust and hasCPU2: exhaustTemp = int(sensorValuesResults[4]) / 10 inletTemp = int(sensorValuesResults[3]) / 10 cpu2Temp = int(sensorValuesResults[2]) / 10 elif hasExhaust and not hasCPU2: exhaustTemp = int(sensorValuesResults[3]) / 10 inletTemp = int(sensorValuesResults[2]) / 10 elif hasCPU2 and not hasExhaust: inletTemp = int(sensorValuesResults[3]) / 10 cpu2Temp = int(sensorValuesResults[2]) / 10 else: inletTemp = int(sensorValuesResults[2]) / 10 if len(currentsCurrentResults) == 1 and int(mainVarBinds[1][-1]) == 0: returnObj = snmpPyIDRACData( hostname=mainVarBinds[0][-1], # Hostname powerDrawPSU1=None, powerDrawPSU2=None, # PSU1 and PSU2 power draw in Watts # board power draw powerDrawBoard=None, voltagePSU1=None, voltagePSU2=None, # PSU1 and PSU2 voltages inletTemp=inletTemp, exhaustTemp=exhaustTemp, # Inlet and Exhaust temp cpu1Temp=None, cpu2Temp=None, # CPU1 and CPU2 temp uptimeS=int(mainVarBinds[1][-1]), # seconds uptimeH=round(((int(mainVarBinds[1][-1]) / 60) / 60), ROUND_PREC), # seconds->minutes->hours uptimeD=round((((int(mainVarBinds[1][-1]) / 60) / 60) / 24), ROUND_PREC) # seconds->minutes->hours->days ) returnDict = { "source": "IDRAC", "value": returnObj, "type": "snmpPyIDRACData" } # return returnObj await queueToInsrt.put(returnDict) return 1 voltList = [] for thing in voltResult: voltList.append(voltResult[thing]) # PSU2 values and board power psu2PowerDraw = None psu2Amperage = None psu2Voltage = None psu1PowerDraw = None psu1Amperage = None psu1Voltage = None if hasPSU2: psu2PowerDraw = round((int(currentsCurrentResults[2]) / 10) * (int(voltList[1]) / 1000), ROUND_PREC) psu2Amperage = int(currentsCurrentResults[2]) / 10 psu2Voltage = round((int(voltList[1]) / 1000), ROUND_PREC) boardPowerDraw = int(currentsCurrentResults[3]) else: boardPowerDraw = int(currentsCurrentResults[2]) returnObj = snmpPyIDRACData( hostname=mainVarBinds[0][-1], # Hostname powerDrawPSU1=round((int(currentsCurrentResults[1]) / 10) * (int(voltList[0]) / 1000), ROUND_PREC), powerDrawPSU2=psu2PowerDraw, # PSU1 and PSU2 power draw in Watts # board power draw powerDrawBoard=boardPowerDraw, voltagePSU1=round((int(voltList[0]) / 1000), ROUND_PREC), voltagePSU2=psu2Voltage, # PSU1 and PSU2 voltages inletTemp=inletTemp, exhaustTemp=exhaustTemp, # Inlet and Exhaust temp cpu1Temp=int(sensorValuesResults[1]) / 10, cpu2Temp=cpu2Temp, # CPU1 and CPU2 temp uptimeS=int(mainVarBinds[1][-1]), # seconds uptimeH=round(((int(mainVarBinds[1][-1]) / 60) / 60), ROUND_PREC), # seconds->minutes->hours uptimeD=round((((int(mainVarBinds[1][-1]) / 60) / 60) / 24), ROUND_PREC) # seconds->minutes->hours->days ) returnDict = { "source": "IDRAC", "value": returnObj, "type": "snmpPyIDRACData" } # return returnObj await queueToInsrt.put(returnDict)