Compare commits

...

2 Commits

Author SHA1 Message Date
e66998b826 Got 3750-X monitoring working 2026-03-17 19:38:27 +01:00
c474f9c9c2 Added error handling for idrac 2026-03-17 19:09:11 +01:00
11 changed files with 473 additions and 204 deletions

View File

@@ -1,61 +1,52 @@
import os, asyncio import os, asyncio
from models.ciscoModel import snmpPyCiscoData from models.ciscoModel import C3750XciscoData
from snmp.walker import walk_column_v3 from models.snmpTimeOut import SNMPTimeoutError
from snmp.walker import walk_column_v3, walk_lobotomy_column_v3
from typing import Annotated, Final from typing import Annotated, Final
# SNMP # SNMP
from pysnmp.hlapi.v3arch.asyncio import * 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 # 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) print("starting work on ", remoteIP)
# SNMPUSRDATA
USMUSRDATA = UsmUserData(
userName=SNMPUSER,
authKey=SNMPAUTHKEY,
privKey=SNMPPRIVKEY,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol,
)
snmpEngine = SnmpEngine() snmpEngine = SnmpEngine()
iterator = get_cmd( iterator = get_cmd(
snmpEngine, snmpEngine,
USMUSRDATA, USMUSRDATA,
await UdpTransportTarget.create((remoteIP, SNMPORT)), await UdpTransportTarget.create((remoteIP, SNMPORT)),
ContextData(), ContextData(),
# Get Hostname # 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 errorIndication, errorStatus, errorIndex, varBinds = await iterator
if errorIndication: 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: elif errorStatus:
print( print(
"{} at {}".format( "{} at {}".format(
@@ -67,18 +58,56 @@ async def ciscoPoolRemote(remoteIP: str, queueToInsrt: asyncio.Queue):
for varBind in varBinds: for varBind in varBinds:
print(" = ".join([x.prettyPrint() for x in varBind])) 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() 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 = { returnDict = {
"source": "CISCO", "source": "CISCO",
"device": "3750X",
"value": returObj, "value": returObj,
"type": "snmpPyCiscoData" "type": "C3750XciscoData"
} }
# return returnObj await queueToInsrt.put(returnDict)
await queueToInsrt.put(returnDict)

View File

@@ -68,4 +68,100 @@ async def fluxIDRACWriter(
return 1 return 1
return 0 return 0
# return {"STATUS": "succesfully inserted to InfluxDB"} # 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)

View File

@@ -3,7 +3,8 @@ from sqlalchemy.ext.asyncio import create_async_engine
from typing import Annotated, Final from typing import Annotated, Final
from dataclasses import asdict from dataclasses import asdict
from models.idracModel import snmpPyIDRACData from models.idracModel import snmpPyIDRACData
from models.sqlTable import idracMeasurement from models.ciscoModel import C3750XciscoData
from models.sqlTable import idracMeasurement, C3750XMeasurement
# SQL ENV------------------------------------------- # SQL ENV-------------------------------------------
USESQL: Final[int] = int(os.getenv("USESQL", 0)) USESQL: Final[int] = int(os.getenv("USESQL", 0))
@@ -27,7 +28,7 @@ else:
engine = None engine = None
async def sqlIDRACDataWriter( async def sqlDataWriter(
inpDict: dict inpDict: dict
) -> int: ) -> int:
@@ -44,10 +45,36 @@ async def sqlIDRACDataWriter(
match inpDict["source"]: match inpDict["source"]:
case "CISCO": case "CISCO":
await eng.execute(
# changeMeLater match inpDict["device"]:
t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}] 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": case "IDRAC":
payload = inpDict["value"] # snmpPyIDRACData payload = inpDict["value"] # snmpPyIDRACData
row = asdict(payload) row = asdict(payload)
@@ -73,4 +100,4 @@ async def sqlIDRACDataWriter(
return 0 return 0
# asyncio.sleep(5) # asyncio.sleep(5)

View File

@@ -1,7 +1,7 @@
import asyncio, os import asyncio, os
from typing import Annotated, Final from typing import Annotated, Final
from db.Influx import fluxIDRACWriter from db.Influx import fluxDataWriter
from db.MariaDB import sqlIDRACDataWriter from db.MariaDB import sqlDataWriter
USEINFLUX: Final[int] = int(os.getenv("USEINFLUX", 1)) USEINFLUX: Final[int] = int(os.getenv("USEINFLUX", 1))
USESQL: Final[int] = int(os.getenv("USESQL", 0)) USESQL: Final[int] = int(os.getenv("USESQL", 0))
@@ -15,7 +15,7 @@ async def ALLdbIDRACWriter(inputQueue: asyncio.Queue) -> None:
try: try:
if USESQL: if USESQL:
sqlResult = await sqlIDRACDataWriter(qu) sqlResult = await sqlDataWriter(qu)
match sqlResult: match sqlResult:
case 1: case 1:
print("Wrong source") print("Wrong source")
@@ -26,7 +26,7 @@ async def ALLdbIDRACWriter(inputQueue: asyncio.Queue) -> None:
case _: case _:
print("Inserted in SQL") print("Inserted in SQL")
if USEINFLUX: if USEINFLUX:
fluxResult = await fluxIDRACWriter(qu) fluxResult = await fluxDataWriter(qu)
match fluxResult: match fluxResult:
case 1: case 1:
print("could not insert") print("could not insert")

View File

@@ -6,39 +6,25 @@ from typing import Annotated, Final
# SNMP # SNMP
from pysnmp.hlapi.v3arch.asyncio import * 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,
)
# IDRAC78 get data for snmpPyIDRACData class # IDRAC78 get data for snmpPyIDRACData class
async def idrac7_8PoolRemote_v3(remoteIP: str, queueToInsrt: asyncio.Queue): async def idrac7_8PoolRemote_v3(
remoteIP: str,
queueToInsrt: asyncio.Queue,
SNMPUSER: str,
SNMPAUTHKEY: str,
SNMPPRIVKEY: str,
ROUND_PREC: int = 2,
SNMPORT: int = 161
):
print("starting work on ", remoteIP) print("starting work on ", remoteIP)
# SNMPUSRDATA
USMUSRDATA = UsmUserData(
userName=SNMPUSER,
authKey=SNMPAUTHKEY,
privKey=SNMPPRIVKEY,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol,
)
snmpEngine = SnmpEngine() snmpEngine = SnmpEngine()
# try CPU2 as CPU1 is always there # try CPU2 as CPU1 is always there
@@ -59,6 +45,10 @@ async def idrac7_8PoolRemote_v3(remoteIP: str, queueToInsrt: asyncio.Queue):
errorIndication, errorStatus, errorIndex, mainVarBinds = await mainIterator errorIndication, errorStatus, errorIndex, mainVarBinds = await mainIterator
if errorIndication: if errorIndication:
if errorIndication == "No SNMP response received before timeout":
print(f"Host {remoteIP} timed out.\nContinuing...")
snmpEngine.close_dispatcher()
return 1
print(errorIndication) print(errorIndication)
elif errorStatus: elif errorStatus:
print( print(
@@ -73,17 +63,17 @@ async def idrac7_8PoolRemote_v3(remoteIP: str, queueToInsrt: asyncio.Queue):
try: try:
# Get PSU1 current, [PSU2 current], total board power draw in watts # 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") 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 # 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") currentsNamesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.600.30.1.8", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY)
# Inlet OID name .1, [Exhaust OID name], CPU1 temp OID name, [CPU2 tempOID name] # Inlet OID name .1, [Exhaust OID name], CPU1 temp OID name, [CPU2 tempOID name]
sensorNamesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.700.20.1.8") sensorNamesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.700.20.1.8", SNMPUSER, SNMPAUTHKEY, SNMPPRIVKEY)
# Inlet temp, [Exhaust temp], CPU1 temp, [CPU2 temp] # Inlet temp, [Exhaust temp], CPU1 temp, [CPU2 temp]
sensorValuesResults = await walk_column_v3(snmpEngine, remoteIP, ".1.3.6.1.4.1.674.10892.5.4.700.20.1.6") 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 # .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") 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)
hasExhaust = any("exhaust" in str(thing).lower() for thing in sensorNamesResults.values()) hasExhaust = any("exhaust" in str(thing).lower() for thing in sensorNamesResults.values())
hasCPU2 = any("cpu2" in str(thing).lower() for thing in sensorNamesResults.values()) hasCPU2 = any("cpu2" in str(thing).lower() for thing in sensorNamesResults.values())

View File

@@ -10,40 +10,27 @@ from typing import Annotated, Final
# SNMP # SNMP
from pysnmp.hlapi.v3arch.asyncio import * 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,
)
# IDRAC get data for snmpPyIDRACData class # IDRAC get data for snmpPyIDRACData class
async def idrac9PoolRemote_v3(remoteIP: str, queueToInsrt: asyncio.Queue): 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) print("starting work on ", remoteIP)
# SNMP
USMUSRDATA = UsmUserData(
userName=SNMPUSER,
authKey=SNMPAUTHKEY,
privKey=SNMPPRIVKEY,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol,
)
snmpEngine = SnmpEngine() snmpEngine = SnmpEngine()
iterator = get_cmd( iterator = get_cmd(
@@ -80,17 +67,17 @@ async def idrac9PoolRemote_v3(remoteIP: str, queueToInsrt: asyncio.Queue):
try: try:
# Get PSU1 current, [PSU2 current], total board power draw in watts # 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") 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 # 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") 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] # 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") 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] # 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") 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 # .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") 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: except SNMPTimeoutError as e:
print(f"{e}\nContinuing regardless...") print(f"{e}\nContinuing regardless...")
return 1 return 1

View File

@@ -8,39 +8,81 @@ from db.collectiveWriter import ALLdbIDRACWriter
# idrac SNMP # idrac SNMP
from idrac import idrac78, idrac9 from idrac import idrac78, idrac9
# Cisco hosts # 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--------------------------------------- # Program ENV---------------------------------------
try: try:
IDRAC78_HOST_LIST: Final[list] = os.getenv("IDRAC78_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", None).split(";") IDRAC9_HOST_LIST: Final[list] = os.getenv("IDRAC9_HOST_LIST", []).split(";")
CISCO_HOST_LIST: Final[list] = os.getenv("CISCO_HOST_LIST", None).split(";")
except: except:
raise Exception("No IDRAC hosts variable") 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)) GET_INTERVAL: Final[int] = int(os.getenv("GET_INTERVAL", 60))
# Flightchecks------------------------------------------- # Flightchecks-------------------------------------------
# if HOST_LIST empty, raise Exception No hosts passed # if HOST_LIST empty, raise Exception No hosts passed
if not IDRAC78_HOST_LIST and not CISCO_HOST_LIST and not IDRAC9_HOST_LIST: # if not IDRAC78_HOST_LIST and not IDRAC9_HOST_LIST:
raise Exception("No hosts passed\nExiting...") # raise Exception("No IDRAC hosts passed\nExiting...")
# for host in HOST_LIST check if valid IP and create a list with strings # 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: try:
ip = str(ipaddress.IPv4Address(idrac78Host)) ip = str(ipaddress.IPv4Address(cisco3750Host))
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))
except ValueError: except ValueError:
raise Exception(f" IP {ip} for Cisco devices is invalid.\nExiting...") 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: try:
ip = str(ipaddress.IPv4Address(idrac9Host)) ip = str(ipaddress.IPv4Address(ciscoNexusHost))
except ValueError: 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 # Done under "Program ENV" on line ~18
@@ -49,48 +91,43 @@ for idrac9Host in IDRAC9_HOST_LIST:
async def main(): 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) mainQueue = asyncio.Queue(maxsize=225)
asyncio.create_task(ALLdbIDRACWriter(mainQueue)) asyncio.create_task(ALLdbIDRACWriter(mainQueue))
print("Starting tasks")
while True: while True:
# IDRAC part # IDRAC part
async with asyncio.TaskGroup() as tg: async with asyncio.TaskGroup() as tg:
for Idrac78IP in IDRAC78_HOST_LIST: 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: 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 # FANS
# tg.create_task(idracPoolRemoteFAN_v3(IdracIP, mainQueue)) # tg.create_task(idracPoolRemoteFAN_v3(IdracIP, mainQueue))
# CISCO devices # CISCO devices
# for CiscoIP in CISCO_HOST_LIST: for cisco3750Xdev in CISCO_3750_HOST_LIST:
# tg.create_task(ciscoPoolRemote(CiscoIP, mainQueue)) 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) 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__": if __name__ == "__main__":
# qu = asyncio.Queue() # qu = asyncio.Queue()
# asyncio.run(idracPoolRemote_v3("192.168.20.7", qu)) # asyncio.run(idracPoolRemote_v3("192.168.20.7", qu))
@@ -100,28 +137,3 @@ if __name__ == "__main__":
# loop = asyncio.get_event_loop() # loop = asyncio.get_event_loop()
# task = loop.create_task(main()) # 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

View File

@@ -2,6 +2,34 @@ from dataclasses import dataclass
from typing import Optional, Annotated, Dict 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 @dataclass
class snmpPyCiscoData(): class snmpPyCiscoData():
"""Dataclass for snmp data""" """Dataclass for snmp data"""

View File

@@ -25,4 +25,38 @@ idracMeasurement = Table(
Column("uptimeS", BigInteger), Column("uptimeS", BigInteger),
Column("uptimeH", Numeric(8, 3)), Column("uptimeH", Numeric(8, 3)),
Column("uptimeD", 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),
) )

View File

@@ -20,14 +20,6 @@ if not SNMPUSER or not SNMPPRIVKEY or not SNMPAUTHKEY:
raise Exception("No SNMP user or/and PrivAuth passed") 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 # 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 = {} rows = {}
async for errInd, errStat, errIdx, varBinds in walk_cmd( async for errInd, errStat, errIdx, varBinds in walk_cmd(
snmpEngine, snmpEngine,
@@ -66,4 +74,44 @@ async def walk_column_v3(snmpEngine, remoteIP: str, base_oid: str) -> dict:
idx = int(oid.prettyPrint().split(".")[-1]) idx = int(oid.prettyPrint().split(".")[-1])
rows[idx] = val.prettyPrint() rows[idx] = val.prettyPrint()
return rows 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

View File

@@ -59,6 +59,24 @@ CREATE TABLE IDRACmeasurement (
INDEX idx_host_time (hostname, time_stamp) 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 ( CREATE TABLE fansHOSTNAMEHERE (
id MEDIUMINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, id MEDIUMINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,