Files
SNMP-Influx-collector/cont/idrac/idrac9.py
2026-03-17 19:09:11 +01:00

219 lines
7.2 KiB
Python

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)