Moved the project to asyncio
This commit is contained in:
@@ -11,29 +11,31 @@ from dataclasses import dataclass
|
|||||||
AlchemyBase = declarative_base()
|
AlchemyBase = declarative_base()
|
||||||
|
|
||||||
# DATABASE "CLASSESS"--------------------------------------------
|
# DATABASE "CLASSESS"--------------------------------------------
|
||||||
def sensorsqldata(table_name: Annotated[str, "Name of the table"]):
|
# class idracSQLTable(AlchemyBase):
|
||||||
|
# def __init__(self, inputData: snmpPyIDRACData):
|
||||||
|
# __table_args__ = {'extend_existing': True}
|
||||||
|
|
||||||
class SensorSQLDataClass(AlchemyBase):
|
# __tablename__ = table_name
|
||||||
__table_args__ = {'extend_existing': True}
|
|
||||||
|
|
||||||
__tablename__ = table_name
|
# id = Column(MEDIUMINT(unsigned=True), primary_key=True, autoincrement=True)
|
||||||
|
# time_stamp = Column(
|
||||||
|
# TIMESTAMP,
|
||||||
|
# server_default=text("CURRENT_TIMESTAMP"),
|
||||||
|
# server_onupdate=text("CURRENT_TIMESTAMP"),
|
||||||
|
# nullable=False,
|
||||||
|
# )
|
||||||
|
|
||||||
id = Column(MEDIUMINT(unsigned=True), primary_key=True, autoincrement=True)
|
# inputData.hostname = Column(TEXT)
|
||||||
time_stamp = Column(
|
# inputData.powerDrawPSU1 = Column(Float)
|
||||||
TIMESTAMP,
|
# inputData.powerDrawPSU2 = Column(Float, nullable=True)
|
||||||
server_default=text("CURRENT_TIMESTAMP"),
|
# inputData.voltagePSU1 = Column(Float)
|
||||||
server_onupdate=text("CURRENT_TIMESTAMP"),
|
# inputData.voltagePSU2 = Column(Float, nullable=True)
|
||||||
nullable=False,
|
# inputData.inletTemp = Column(Float)
|
||||||
)
|
# inputData.exhaustTemp = Column(Float)
|
||||||
TEMP = Column(TINYINT)
|
# inputData.cpu1Temp = Column(Float)
|
||||||
TEMP = Column(TEXT)
|
# inputData.cpu2Temp = Column(Float, nullable=True)
|
||||||
TEMP = Column(Float)
|
# inputData.uptimeH = Column(Float)
|
||||||
TEMP = Column(Float)
|
# inputData.uptimeD = Column(Float, nullable=True)
|
||||||
TEMP = Column(Float, nullable=True)
|
|
||||||
TEMP = Column(Float, nullable=True)
|
|
||||||
TEMP = Column(Float, nullable=True)
|
|
||||||
|
|
||||||
return SensorSQLDataClass
|
|
||||||
|
|
||||||
|
|
||||||
# Custom--------------------------------------------
|
# Custom--------------------------------------------
|
||||||
@@ -115,5 +117,37 @@ class snmpPyIDRACData():
|
|||||||
)
|
)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class idracFanStatus:
|
class snmpPyCiscoData():
|
||||||
fans: Dict[str, int] # name/index -> rpm
|
"""Dataclass for snmp data"""
|
||||||
|
hostname: str
|
||||||
|
powerDrawPSU1: int
|
||||||
|
voltagePSU1: int
|
||||||
|
inletTemp: float
|
||||||
|
exhaustTemp: float
|
||||||
|
cpu1Temp: float
|
||||||
|
uptimeH: float
|
||||||
|
|
||||||
|
# optional fields
|
||||||
|
uptimeD: float | None = None
|
||||||
|
cpu2Temp: float | None = None
|
||||||
|
powerDrawPSU2: int | None = None
|
||||||
|
voltagePSU2: int | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"{self.hostname}\n"
|
||||||
|
f"PSU1 {self.powerDrawPSU1} Watts\n"
|
||||||
|
f"PSU2 {self.powerDrawPSU2} Watts\n"
|
||||||
|
f"PSU1 {self.voltagePSU1} Volts\n"
|
||||||
|
f"PSU2 {self.voltagePSU2} Volts\n"
|
||||||
|
f"Inlet {self.inletTemp} C\n"
|
||||||
|
f"Exhaust {self.exhaustTemp} C\n"
|
||||||
|
f"CPU1 {self.cpu1Temp} C\n"
|
||||||
|
f"CPU2 {self.cpu2Temp} C\n"
|
||||||
|
f"Uptime {self.uptimeH} Hours\n"
|
||||||
|
f"Uptime {self.uptimeD} Days"
|
||||||
|
)
|
||||||
|
# @dataclass
|
||||||
|
# class idracFanStatus:
|
||||||
|
# fans: Dict[str, int] | None = Dict[None, None] # name/index -> rpm
|
||||||
381
cont/funct.py
381
cont/funct.py
@@ -1,17 +1,21 @@
|
|||||||
import influxdb_client, sqlalchemy, random, os
|
import influxdb_client, sqlalchemy, random, os, asyncio
|
||||||
# from sqlmodel import Field, Session, SQLModel, create_engine, select
|
# from sqlmodel import Field, Session, SQLModel, create_engine, select
|
||||||
from sqlalchemy import create_engine, exc # , Column, Integer, String, Numeric
|
# from sqlalchemy import create_engine, exc # , Column, Integer, String, Numeric
|
||||||
# from sqlalchemy.ext.declarative import declarative_base
|
# from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import sessionmaker
|
# from sqlalchemy.orm import sessionmaker
|
||||||
|
from sqlalchemy.ext.asyncio import create_async_engine
|
||||||
|
|
||||||
from classes import *
|
from classes import *
|
||||||
from typing import Annotated, Final
|
from typing import Annotated, Final
|
||||||
|
|
||||||
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
||||||
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS, WriteOptions
|
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS, WriteOptions
|
||||||
# import pymysql
|
|
||||||
|
# SNMP
|
||||||
|
from pysnmp.hlapi.v3arch.asyncio import *
|
||||||
|
|
||||||
# FluxQL ENV----------------------------------------
|
# FluxQL ENV----------------------------------------
|
||||||
USEINFLUX: Final[bool] = os.getenv("USEINFLUX", True)
|
USEINFLUX: Final[int] = int(os.getenv("USEINFLUX", 1))
|
||||||
if USEINFLUX:
|
if USEINFLUX:
|
||||||
INFLXDBTOKEN: Final[str] = os.getenv("INFLXDBTOKEN", "123" )
|
INFLXDBTOKEN: Final[str] = os.getenv("INFLXDBTOKEN", "123" )
|
||||||
INFLUXBCKT: Final[str] = os.getenv("INFLUXBCKT", "SNMPyth")
|
INFLUXBCKT: Final[str] = os.getenv("INFLUXBCKT", "SNMPyth")
|
||||||
@@ -20,90 +24,126 @@ if USEINFLUX:
|
|||||||
INFXLUXDB_MEASUEREMENT: Final[str] = os.getenv("INFXLUXDB_MEASUEREMENT", "SNMPyth-containrr")
|
INFXLUXDB_MEASUEREMENT: Final[str] = os.getenv("INFXLUXDB_MEASUEREMENT", "SNMPyth-containrr")
|
||||||
INFLX_SEPARATE_POINTS: Final[float] = float(os.getenv("INFLX_SEPARATE_POINTS", 0.1))
|
INFLX_SEPARATE_POINTS: Final[float] = float(os.getenv("INFLX_SEPARATE_POINTS", 0.1))
|
||||||
# SQL ENV-------------------------------------------
|
# SQL ENV-------------------------------------------
|
||||||
USESQL: Final[bool] = os.getenv("USESQL", False)
|
USESQL: Final[int] = int(os.getenv("USESQL", 0))
|
||||||
if USESQL:
|
if USESQL:
|
||||||
DBENGINE: Final[str] = os.getenv("DBENGINE", "mysql+pymysql")
|
DBENGINE: Final[str] = os.getenv("DBENGINE", "mysql+asyncmy")
|
||||||
DBADDR: Final[str] = os.getenv("DBADDR", "127.0.0.1")
|
DBADDR: Final[str] = os.getenv("DBADDR", "127.0.0.1")
|
||||||
DBUSR: Final[str] = os.getenv("DBUSR", "root")
|
DBUSR: Final[str] = os.getenv("DBUSR", "root")
|
||||||
DBPWD: Final[str] = os.getenv("DBPWD", "6767")
|
DBPWD: Final[str] = os.getenv("DBPWD", "6767")
|
||||||
DBNAME: Final[str] = os.getenv("DBNAME", "TEMP_SENSR")
|
DBNAME: Final[str] = os.getenv("DBNAME", "TEMP_SENSR")
|
||||||
|
# SNMP ENV-------------------------------------------
|
||||||
|
ROUND_PREC: Final[int] = int(os.getenv("ROUND_PREC", 6))
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
# Flightchecks-------------------------------------------
|
# Flightchecks-------------------------------------------
|
||||||
# Check if some neccesary ENVs are passed
|
# Check if some neccesary ENVs are passed
|
||||||
if not USEINFLUX and not USESQL:
|
if not USEINFLUX and not USESQL:
|
||||||
raise Exception("No database selected to store the data")
|
raise Exception("No database selected to store the data")
|
||||||
|
# Check if SNMP ENV are empty
|
||||||
|
if not SNMPUSER or not SNMPPRIVKEY or not SNMPAUTHKEY:
|
||||||
|
raise Exception("No SNMP user or/and PrivAuth passed")
|
||||||
|
|
||||||
|
|
||||||
# DBprepare-------------------------------------------
|
# Prepare-------------------------------------------
|
||||||
# INFLUX
|
# INFLUX
|
||||||
if USEINFLUX:
|
if USEINFLUX:
|
||||||
fluxdb_client = influxdb_client.InfluxDBClient(url=INFLXDBURL, token=INFLXDBTOKEN, org=INFLUXORG)
|
fluxdb_client = influxdb_client.InfluxDBClient(url=INFLXDBURL, token=INFLXDBTOKEN, org=INFLUXORG)
|
||||||
write_fluxdb_api = fluxdb_client.write_api(write_options=SYNCHRONOUS)
|
write_fluxdb_api = fluxdb_client.write_api(write_options=ASYNCHRONOUS)
|
||||||
query_fluxdb_api = fluxdb_client.query_api()
|
query_fluxdb_api = fluxdb_client.query_api()
|
||||||
|
else:
|
||||||
|
fluxdb_client = write_fluxdb_api = query_fluxdb_api = None
|
||||||
# SQL
|
# SQL
|
||||||
if USESQL:
|
if USESQL:
|
||||||
engine = create_engine(
|
engine = create_async_engine(
|
||||||
f"{DBENGINE}://{DBUSR}:{DBPWD}@{DBADDR}/{DBNAME}",
|
f"{DBENGINE}://{DBUSR}:{DBPWD}@{DBADDR}/{DBNAME}",
|
||||||
pool_pre_ping=True, # Check connection liveness before using and if needed, recconect
|
# pool_pre_ping=True, # Check connection liveness before using and if needed, recconect
|
||||||
pool_recycle=3600 # recycle connections older than N (3600 in this case) seconds
|
# pool_recycle=3600, # recycle connections older than N (3600 in this case) seconds
|
||||||
|
echo=True,
|
||||||
)
|
)
|
||||||
Session = sessionmaker(bind=engine)
|
else:
|
||||||
|
engine = None
|
||||||
|
|
||||||
|
# SNMP
|
||||||
|
USMUSRDATA = UsmUserData(
|
||||||
|
userName=SNMPUSER,
|
||||||
|
authKey=SNMPAUTHKEY,
|
||||||
|
privKey=SNMPPRIVKEY,
|
||||||
|
authProtocol=usmHMACSHAAuthProtocol,
|
||||||
|
privProtocol=usmAesCfb128Protocol,
|
||||||
|
)
|
||||||
|
|
||||||
def tempsnsrIntoSQLDB(
|
# DB functions-------------------------------------------
|
||||||
tableInp: Annotated[int, "Name of the table"],
|
|
||||||
insertData: Annotated[str, "Data to insert"]
|
async def sqlDataWriter(
|
||||||
|
inpDict: dict
|
||||||
) -> int:
|
) -> int:
|
||||||
f"""
|
|
||||||
Insert {DBNAME} data into MariaDB
|
|
||||||
:tableInp: Name of the table
|
|
||||||
:return: 0 if succesfull, 1 if rolled back on error, 2 if SQL is not enabled 3 if no such table
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not USESQL:
|
# inputQueue have multiple such Dicts
|
||||||
return 2
|
# {
|
||||||
|
# "source": "IDRAC",
|
||||||
# Check if table exists
|
# "value": returnObj,
|
||||||
if not sqlalchemy.inspect(engine).has_table(tableInp):
|
# "type": "snmpPyIDRACData"
|
||||||
|
# }
|
||||||
|
if engine is None:
|
||||||
return 3
|
return 3
|
||||||
|
|
||||||
with Session() as session:
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
async with engine.begin() as eng:
|
||||||
|
match inpDict["source"]:
|
||||||
|
|
||||||
sqlData = sensorsqldata(tableInp)
|
case "CISCO":
|
||||||
# print("2")
|
await eng.execute(
|
||||||
|
# changeMeLater
|
||||||
|
t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}]
|
||||||
|
)
|
||||||
|
case "IDRAC":
|
||||||
|
await eng.execute(
|
||||||
|
# changeMeLater
|
||||||
|
t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}]
|
||||||
|
)
|
||||||
|
case "FANS":
|
||||||
|
await eng.execute(
|
||||||
|
# changeMeLater
|
||||||
|
t1.insert(), [{"name": "some name 1"}, {"name": "some name 2"}]
|
||||||
|
)
|
||||||
|
|
||||||
if inpayload:
|
case _:
|
||||||
# print("3")
|
print(f"No such source of data as {inpDict['source']}")
|
||||||
session.add(sqlData(
|
|
||||||
data = insertData,
|
|
||||||
))
|
|
||||||
# print("4")
|
|
||||||
|
|
||||||
session.commit() #Attempt to commit all the records
|
|
||||||
# print("good")
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error {e} when sending to mariadb")
|
|
||||||
session.rollback() #Rollback the changes on error
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return 2
|
||||||
|
|
||||||
def tempsnsrIntoFluxQLDB(
|
return 0
|
||||||
inIdracPayload: Annotated[snmpPyIDRACData, "Payload"] | None = None,
|
|
||||||
inCiscoPayload: Annotated[int, "yes"] | None = None
|
# asyncio.sleep(5)
|
||||||
|
|
||||||
|
|
||||||
|
async def fluxWriter(
|
||||||
|
inpDict: dict
|
||||||
) -> int:
|
) -> int:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Insert temperature data into InfluxDB
|
Insert temperature data into InfluxDB
|
||||||
:inpayload: Payload
|
:inputQueue: Asyncio Queue that has what is needed to be sent
|
||||||
:return: 0 if succesfull, 1 if general error, 2 if Influx is not enabled
|
|
||||||
"""
|
"""
|
||||||
if not USEINFLUX:
|
# inputQueue have multiple such Dicts
|
||||||
|
# {
|
||||||
|
# "source": "IDRAC",
|
||||||
|
# "value": returnObj,
|
||||||
|
# "type": "snmpPyIDRACData"
|
||||||
|
# }
|
||||||
|
|
||||||
|
if write_fluxdb_api is None:
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
# Prep InfluxDB data
|
# Prep InfluxDB data
|
||||||
inflxdb_Data_To_Send = (
|
inflxdb_Data_To_Send = (
|
||||||
influxdb_client.Point(f"{INFXLUXDB_MEASUEREMENT}")
|
influxdb_client.Point(f"{INFXLUXDB_MEASUEREMENT}")
|
||||||
@@ -117,13 +157,234 @@ def tempsnsrIntoFluxQLDB(
|
|||||||
.field("TEMP", inpayload.alttd)
|
.field("TEMP", inpayload.alttd)
|
||||||
)
|
)
|
||||||
|
|
||||||
# print(write_fluxdb_api.write(bucket=INFLUXBCKT, org=INFLUXORG, record=inflxdb_Data_To_Send))
|
try:
|
||||||
# if write_fluxdb_api.write(bucket=INFLUXBCKT, org=INFLUXORG, record=inflxdb_Data_To_Send) == None:
|
write_fluxdb_api.write(bucket=INFLUXBCKT, org=INFLUXORG, record=inflxdb_Data_To_Send)
|
||||||
|
except Exception as e:
|
||||||
if write_fluxdb_api.write(bucket=INFLUXBCKT, org=INFLUXORG, record=inflxdb_Data_To_Send):
|
print(e)
|
||||||
# return {"STATUS": "succesfully inserted to InfluxDB"}
|
|
||||||
print("0")
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
print("1")
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
# return {"STATUS": "succesfully inserted to InfluxDB"}
|
||||||
|
|
||||||
|
|
||||||
|
async def ALLdbWriter(inputQueue: asyncio.Queue) -> None:
|
||||||
|
while True:
|
||||||
|
|
||||||
|
qu = await inputQueue.get()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if USESQL:
|
||||||
|
sqlResult = await sqlDataWriter(qu)
|
||||||
|
match sqlResult:
|
||||||
|
case 1:
|
||||||
|
print("Wrong source")
|
||||||
|
case 2:
|
||||||
|
print("Error inserting to database")
|
||||||
|
case 3:
|
||||||
|
print("No engine defined")
|
||||||
|
case _:
|
||||||
|
print("nice")
|
||||||
|
if USEINFLUX:
|
||||||
|
fluxResult = await fluxWriter(qu)
|
||||||
|
match fluxResult:
|
||||||
|
case 1:
|
||||||
|
print("could not insert")
|
||||||
|
case 2:
|
||||||
|
print("Error with initializing Inxlux variables")
|
||||||
|
case _:
|
||||||
|
print("nice")
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
finally:
|
||||||
|
inputQueue.task_done()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# SNMP functions-------------------------------------------
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
# def wattageCalc(amperageInp: float, voltageInp: float) -> float:
|
||||||
|
# return amperageInp * voltageInp
|
||||||
|
|
||||||
|
# Cisco
|
||||||
|
async def ciscoPoolRemote(remoteIP: str, queueToInsrt: asyncio.Queue):
|
||||||
|
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")),
|
||||||
|
#
|
||||||
|
)
|
||||||
|
|
||||||
|
print(iterator)
|
||||||
|
|
||||||
|
errorIndication, errorStatus, errorIndex, varBinds = await iterator
|
||||||
|
|
||||||
|
if errorIndication:
|
||||||
|
print(errorIndication)
|
||||||
|
|
||||||
|
elif errorStatus:
|
||||||
|
print(
|
||||||
|
"{} at {}".format(
|
||||||
|
errorStatus.prettyPrint(),
|
||||||
|
errorIndex and varBinds[int(errorIndex) - 1][0] or "?",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for varBind in varBinds:
|
||||||
|
print(" = ".join([x.prettyPrint() for x in varBind]))
|
||||||
|
|
||||||
|
snmpEngine.close_dispatcher()
|
||||||
|
|
||||||
|
returObj = snmpPyCiscoData()
|
||||||
|
|
||||||
|
returObj(
|
||||||
|
hostname="X"
|
||||||
|
)
|
||||||
|
|
||||||
|
returnDict = {
|
||||||
|
"source": "CISCO",
|
||||||
|
"value": returObj,
|
||||||
|
"type": "snmpPyCiscoData"
|
||||||
|
}
|
||||||
|
# return returnObj
|
||||||
|
queueToInsrt.put(returnDict)
|
||||||
|
|
||||||
|
# IDRAC get data for snmpPyIDRACData class
|
||||||
|
async def idracPoolRemote_v3(remoteIP: str, queueToInsrt: asyncio.Queue):
|
||||||
|
snmpEngine = SnmpEngine()
|
||||||
|
|
||||||
|
iterator = get_cmd(
|
||||||
|
snmpEngine,
|
||||||
|
# SNMPv1 = mpModel=0 (SNMPv2c would be mpModel=1)
|
||||||
|
# CommunityData("public", mpModel=0),
|
||||||
|
USMUSRDATA,
|
||||||
|
await UdpTransportTarget.create((remoteIP, SNMPORT)),
|
||||||
|
ContextData(),
|
||||||
|
# Hostname (sysName.0)
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")), #0
|
||||||
|
|
||||||
|
# PSU1 powerDraw and PSU2 powerDraw (Amps)
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.30.1.6.1.1")), #1
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.30.1.6.1.2")), #2
|
||||||
|
# (Volts)
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.20.1.6.1.31")), #3
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.20.1.6.1.32")), #4
|
||||||
|
|
||||||
|
# Get Inlet, Exhaust, CPU1, CPU2
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.1")), #5
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.2")), #6
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.3")), #7
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.4")), #8
|
||||||
|
|
||||||
|
# Uptime in seconds
|
||||||
|
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.2.5.0")), #9
|
||||||
|
)
|
||||||
|
|
||||||
|
errorIndication, errorStatus, errorIndex, varBinds = await iterator
|
||||||
|
|
||||||
|
if errorIndication:
|
||||||
|
print(errorIndication)
|
||||||
|
elif errorStatus:
|
||||||
|
print(
|
||||||
|
"{} at {}".format(
|
||||||
|
errorStatus.prettyPrint(),
|
||||||
|
errorIndex and varBinds[int(errorIndex) - 1][0] or "?",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for oid, val in varBinds:
|
||||||
|
print(f"{oid.prettyPrint()} = {val.prettyPrint()}")
|
||||||
|
|
||||||
|
# for element in varBinds:
|
||||||
|
# print(element)
|
||||||
|
|
||||||
|
snmpEngine.close_dispatcher()
|
||||||
|
# print(varBinds[1][-1])
|
||||||
|
# print(type(varBinds[1][-1]))
|
||||||
|
returnObj = snmpPyIDRACData(
|
||||||
|
hostname=varBinds[0][-1],
|
||||||
|
# Hostname
|
||||||
|
|
||||||
|
powerDrawPSU1=round((int(varBinds[1][-1]) / 10) * (int(varBinds[3][-1]) / 1000), ROUND_PREC),
|
||||||
|
powerDrawPSU2=round((int(varBinds[2][-1]) / 10) * (int(varBinds[4][-1]) / 1000), ROUND_PREC),
|
||||||
|
# PSU1 and PSU2 power draw in Watts
|
||||||
|
|
||||||
|
voltagePSU1=round((int(varBinds[3][-1]) / 1000), ROUND_PREC),
|
||||||
|
voltagePSU2=round((int(varBinds[4][-1]) / 1000), ROUND_PREC),
|
||||||
|
# PSU1 and PSU2 voltages
|
||||||
|
|
||||||
|
inletTemp=int(varBinds[5][-1] / 10),
|
||||||
|
exhaustTemp=int(varBinds[6][-1] / 10),
|
||||||
|
# Inlet and Exhaust temp
|
||||||
|
|
||||||
|
cpu1Temp=int(varBinds[7][-1] / 10),
|
||||||
|
cpu2Temp=int(varBinds[8][-1] / 10),
|
||||||
|
# CPU1 and CPU2 temp
|
||||||
|
|
||||||
|
uptimeH=round(((int(varBinds[9][-1]) / 60) / 60), ROUND_PREC),
|
||||||
|
# seconds->minutes->hours
|
||||||
|
uptimeD=round((((int(varBinds[9][-1]) / 60) / 60) / 24), ROUND_PREC)
|
||||||
|
# seconds->minutes->hours->days
|
||||||
|
)
|
||||||
|
|
||||||
|
returnDict = {
|
||||||
|
"source": "IDRAC",
|
||||||
|
"value": returnObj,
|
||||||
|
"type": "snmpPyIDRACData"
|
||||||
|
}
|
||||||
|
# return returnObj
|
||||||
|
queueToInsrt.put(returnDict)
|
||||||
|
|
||||||
|
|
||||||
|
# IDRAC get FAN data
|
||||||
|
async def walk_column_v3(snmpEngine, remoteIP: str, base_oid: str) -> dict:
|
||||||
|
rows = {}
|
||||||
|
async for errInd, errStat, errIdx, varBinds in walk_cmd(
|
||||||
|
snmpEngine,
|
||||||
|
# CommunityData("public", mpModel=0),
|
||||||
|
USMUSRDATA,
|
||||||
|
await UdpTransportTarget.create((remoteIP, SNMPORT)),
|
||||||
|
ContextData(),
|
||||||
|
ObjectType(ObjectIdentity(base_oid)),
|
||||||
|
lexicographicMode=False,
|
||||||
|
):
|
||||||
|
if errInd:
|
||||||
|
raise RuntimeError(errInd)
|
||||||
|
if errStat:
|
||||||
|
raise RuntimeError(errStat.prettyPrint())
|
||||||
|
|
||||||
|
for oid, val in varBinds:
|
||||||
|
# index is typically the last sub-identifier
|
||||||
|
idx = int(oid.prettyPrint().split(".")[-1])
|
||||||
|
rows[idx] = val.prettyPrint()
|
||||||
|
|
||||||
|
return rows
|
||||||
|
|
||||||
|
async def idracPoolRemoteFAN_v3(remoteIP: str, queueToInsrt: asyncio.Queue) -> dict:
|
||||||
|
snmpEngine = SnmpEngine()
|
||||||
|
|
||||||
|
rpm_oid = "1.3.6.1.4.1.674.10892.5.4.700.12.1.6"
|
||||||
|
name_oid = "1.3.6.1.4.1.674.10892.5.4.700.12.1.19"
|
||||||
|
|
||||||
|
rpms, names = await asyncio.gather(
|
||||||
|
walk_column_v3(snmpEngine, remoteIP, rpm_oid),
|
||||||
|
walk_column_v3(snmpEngine, remoteIP, name_oid),
|
||||||
|
)
|
||||||
|
|
||||||
|
snmpEngine.close_dispatcher()
|
||||||
|
|
||||||
|
# merge by index
|
||||||
|
out = {}
|
||||||
|
for idx, rpm in rpms.items():
|
||||||
|
out[idx] = {"rpm": rpm, "name": names.get(idx).split(".")[2]}
|
||||||
|
|
||||||
|
returnDict = {
|
||||||
|
"source": "FANS",
|
||||||
|
"value": out,
|
||||||
|
"type": "Dict"
|
||||||
|
}
|
||||||
|
|||||||
215
cont/main.py
215
cont/main.py
@@ -9,28 +9,15 @@ from funct import *
|
|||||||
from classes import *
|
from classes import *
|
||||||
|
|
||||||
# Program ENV---------------------------------------
|
# Program ENV---------------------------------------
|
||||||
ROUND_PREC: Final[int] = os.getenv("ROUND_PREC", 6)
|
|
||||||
IDRAC_HOST_LIST: Final[list] = os.getenv("IDRAC_HOST_LIST").split(";")
|
IDRAC_HOST_LIST: Final[list] = os.getenv("IDRAC_HOST_LIST").split(";")
|
||||||
CISCO_HOST_LIST: Final[list] = os.getenv("CISCO_HOST_LIST").split(";")
|
CISCO_HOST_LIST: Final[list] = os.getenv("CISCO_HOST_LIST").split(";")
|
||||||
|
|
||||||
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] = os.getenv("SNMPORT", 161)
|
|
||||||
|
|
||||||
# Flightchecks-------------------------------------------
|
# Flightchecks-------------------------------------------
|
||||||
# Check if SNMP ENV are empty
|
|
||||||
if not SNMPUSER or not SNMPPRIVKEY or not SNMPAUTHKEY:
|
|
||||||
raise Exception("No SNMP user or/and PrivAuth passed")
|
|
||||||
|
|
||||||
# if HOST_LIST empty, raise Exception No hosts passed
|
# if HOST_LIST empty, raise Exception No hosts passed
|
||||||
if not IDRAC_HOST_LIST and not CISCO_HOST_LIST:
|
if not IDRAC_HOST_LIST and not CISCO_HOST_LIST:
|
||||||
raise Exception("No hosts passed\nExiting...")
|
raise Exception("No 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 idracHost in IDRAC_HOST_LIST:
|
for idracHost in IDRAC_HOST_LIST:
|
||||||
try:
|
try:
|
||||||
@@ -48,185 +35,53 @@ for ciscoHost in CISCO_HOST_LIST:
|
|||||||
|
|
||||||
# Code-------------------------------------------
|
# Code-------------------------------------------
|
||||||
|
|
||||||
# Helper functions
|
async def main():
|
||||||
def wattageCalc(amperageInp: float, voltageInp: float) -> float:
|
|
||||||
return amperageInp * voltageInp
|
# Queues for storing states that a database needs to insert
|
||||||
|
# idracQueue = asyncio.Queue()
|
||||||
|
# ciscoQueue = asyncio.Queue()
|
||||||
|
# fanQueue = asyncio.Queue()
|
||||||
|
mainQueue(maxsize=225)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
tasks = []
|
||||||
|
# IDRAC part
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
for IdracIP in IDRAC_HOST_LIST:
|
||||||
|
tasks.append(tg.create_task(idracPoolRemote_v3(IdracIP, mainQueue)))
|
||||||
|
# tasks.append(tg.create_task(idracPoolRemoteFAN_v3(IdracIP, mainQueue)))
|
||||||
|
|
||||||
|
|
||||||
async def ciscoPoolRemote(remoteIP: str):
|
# for CiscoIP in CISCO_HOST_LIST:
|
||||||
snmpEngine = SnmpEngine()
|
# tasks.append(tg.create_task(ciscoPoolRemote(CiscoIP, mainQueue)))
|
||||||
|
|
||||||
iterator = get_cmd(
|
sleep(20)
|
||||||
snmpEngine,
|
|
||||||
UsmUserData(
|
|
||||||
userName=SNMPUSER,
|
|
||||||
authKey=SNMPPRIVKEY,
|
|
||||||
privKey=SNMPAUTHKEY,
|
|
||||||
authProtocol=usmHMACSHAAuthProtocol,
|
|
||||||
privProtocol=usmHMACSHAAuthProtocol,
|
|
||||||
),
|
|
||||||
await UdpTransportTarget.create((remoteIP, SNMPORT)),
|
|
||||||
ContextData(),
|
|
||||||
# Get Hostname
|
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")),
|
|
||||||
#
|
|
||||||
)
|
|
||||||
|
|
||||||
print(iterator)
|
|
||||||
|
|
||||||
errorIndication, errorStatus, errorIndex, varBinds = await iterator
|
|
||||||
|
|
||||||
if errorIndication:
|
|
||||||
print(errorIndication)
|
|
||||||
|
|
||||||
elif errorStatus:
|
|
||||||
print(
|
|
||||||
"{} at {}".format(
|
|
||||||
errorStatus.prettyPrint(),
|
|
||||||
errorIndex and varBinds[int(errorIndex) - 1][0] or "?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
for varBind in varBinds:
|
|
||||||
print(" = ".join([x.prettyPrint() for x in varBind]))
|
|
||||||
|
|
||||||
snmpEngine.close_dispatcher()
|
|
||||||
|
|
||||||
async def idracPoolRemote(remoteIP: str):
|
|
||||||
snmpEngine = SnmpEngine()
|
|
||||||
|
|
||||||
iterator = get_cmd(
|
|
||||||
snmpEngine,
|
|
||||||
UsmUserData(
|
|
||||||
userName=SNMPUSER,
|
|
||||||
authKey=SNMPPRIVKEY,
|
|
||||||
privKey=SNMPAUTHKEY,
|
|
||||||
authProtocol=usmHMACSHAAuthProtocol,
|
|
||||||
privProtocol=usmHMACSHAAuthProtocol,
|
|
||||||
),
|
|
||||||
await UdpTransportTarget.create((remoteIP, SNMPORT)),
|
|
||||||
ContextData(),
|
|
||||||
# Get Hostname
|
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")),
|
|
||||||
#
|
|
||||||
)
|
|
||||||
|
|
||||||
print(iterator)
|
|
||||||
|
|
||||||
errorIndication, errorStatus, errorIndex, varBinds = await iterator
|
|
||||||
|
|
||||||
if errorIndication:
|
|
||||||
print(errorIndication)
|
|
||||||
|
|
||||||
elif errorStatus:
|
|
||||||
print(
|
|
||||||
"{} at {}".format(
|
|
||||||
errorStatus.prettyPrint(),
|
|
||||||
errorIndex and varBinds[int(errorIndex) - 1][0] or "?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
for varBind in varBinds:
|
|
||||||
print(" = ".join([x.prettyPrint() for x in varBind]))
|
|
||||||
|
|
||||||
snmpEngine.close_dispatcher()
|
|
||||||
|
|
||||||
|
|
||||||
async def idracPoolRemote_v1(remoteIP: str):
|
|
||||||
snmpEngine = SnmpEngine()
|
|
||||||
|
|
||||||
iterator = get_cmd(
|
# yes = asyncio.run(idracPoolRemote_v3("192.168.20.7"))
|
||||||
snmpEngine,
|
# fan = asyncio.run(idracPoolRemoteFAN_v3("192.168.20.7"))
|
||||||
# SNMPv1 = mpModel=0 (SNMPv2c would be mpModel=1)
|
|
||||||
CommunityData("public", mpModel=0),
|
|
||||||
await UdpTransportTarget.create((remoteIP, SNMPORT)),
|
|
||||||
ContextData(),
|
|
||||||
# Hostname (sysName.0)
|
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.2.1.1.5.0")), #0
|
|
||||||
|
|
||||||
# PSU1 powerDraw and PSU2 powerDraw (Amps)
|
# print("fanThingy")
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.30.1.6.1.1")), #1
|
# # print(fan)
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.30.1.6.1.2")), #2
|
# for thing in fan:
|
||||||
# (Volts)
|
# print(fan[thing]["name"], fan[thing]["rpm"])
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.20.1.6.1.31")), #3
|
# for thing in fan:
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.600.20.1.6.1.32")), #4
|
# print(thing)
|
||||||
|
|
||||||
# Get Inlet, Exhaust, CPU1, CPU2
|
# print("for loop")
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.1")), #5
|
# print(yes)
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.2")), #6
|
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.3")), #7
|
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.4.700.20.1.6.1.4")), #8
|
|
||||||
|
|
||||||
# Uptime in seconds
|
# print("End of code")
|
||||||
ObjectType(ObjectIdentity(".1.3.6.1.4.1.674.10892.5.2.5.0")), #9
|
|
||||||
)
|
|
||||||
|
|
||||||
errorIndication, errorStatus, errorIndex, varBinds = await iterator
|
if __name__ == "__main__":
|
||||||
|
|
||||||
if errorIndication:
|
|
||||||
print(errorIndication)
|
|
||||||
elif errorStatus:
|
|
||||||
print(
|
|
||||||
"{} at {}".format(
|
|
||||||
errorStatus.prettyPrint(),
|
|
||||||
errorIndex and varBinds[int(errorIndex) - 1][0] or "?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
for oid, val in varBinds:
|
|
||||||
print(f"{oid.prettyPrint()} = {val.prettyPrint()}")
|
|
||||||
|
|
||||||
# for element in varBinds:
|
|
||||||
# print(element)
|
|
||||||
|
|
||||||
snmpEngine.close_dispatcher()
|
|
||||||
# print(varBinds[1][-1])
|
|
||||||
# print(type(varBinds[1][-1]))
|
|
||||||
returnObj = snmpPyIDRACData(
|
|
||||||
hostname=varBinds[0][-1],
|
|
||||||
# Hostname
|
|
||||||
|
|
||||||
powerDrawPSU1=round((int(varBinds[1][-1]) / 10) * (int(varBinds[3][-1]) / 1000), ROUND_PREC),
|
|
||||||
powerDrawPSU2=round((int(varBinds[2][-1]) / 10) * (int(varBinds[4][-1]) / 1000), ROUND_PREC),
|
|
||||||
# PSU1 and PSU2 power draw in Watts
|
|
||||||
|
|
||||||
voltagePSU1=round((int(varBinds[3][-1]) / 1000), ROUND_PREC),
|
|
||||||
voltagePSU2=round((int(varBinds[4][-1]) / 1000), ROUND_PREC),
|
|
||||||
# PSU1 and PSU2 voltages
|
|
||||||
|
|
||||||
inletTemp=int(varBinds[5][-1] / 10),
|
|
||||||
exhaustTemp=int(varBinds[6][-1] / 10),
|
|
||||||
# Inlet and Exhaust temp
|
|
||||||
|
|
||||||
cpu1Temp=int(varBinds[7][-1] / 10),
|
|
||||||
cpu2Temp=int(varBinds[8][-1] / 10),
|
|
||||||
# CPU1 and CPU2 temp
|
|
||||||
|
|
||||||
uptimeH=round(((int(varBinds[9][-1]) / 60) / 60), ROUND_PREC),
|
|
||||||
# seconds->minutes->hours
|
|
||||||
uptimeD=round((((int(varBinds[9][-1]) / 60) / 60) / 24), ROUND_PREC)
|
|
||||||
# seconds->minutes->hours->days
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
return returnObj
|
loop = asyncio.get_event_loop()
|
||||||
|
task = loop.create_task(main())
|
||||||
|
|
||||||
|
|
||||||
yes = asyncio.run(idracPoolRemote_v1("192.168.20.7"))
|
|
||||||
|
|
||||||
print("for loop")
|
|
||||||
print(yes)
|
|
||||||
|
|
||||||
x = idracFanStatus(6)
|
|
||||||
# print(yes.hostname)
|
|
||||||
# print(yes.powerDrawPSU1)
|
|
||||||
# print(yes.powerDrawPSU2)
|
|
||||||
# print(yes.voltagePSU1)
|
|
||||||
# print(yes.voltagePSU2)
|
|
||||||
# print(yes.inletTemp)
|
|
||||||
# print(yes.exhaustTemp)
|
|
||||||
# print(yes.uptimeH)
|
|
||||||
# print(yes.uptimeD)
|
|
||||||
|
|
||||||
|
|
||||||
# poolRemote(HOST_LIST[0])
|
# poolRemote(HOST_LIST[0])
|
||||||
@@ -239,12 +94,6 @@ x = idracFanStatus(6)
|
|||||||
# await asyncio.sleep(20)
|
# await asyncio.sleep(20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Create connections for MySQL and InfluxDB
|
# Create connections for MySQL and InfluxDB
|
||||||
|
|
||||||
# functions for inserting data into two DBs
|
# functions for inserting data into two DBs
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
# mysql-connector-python==9.2.0
|
# mysql-connector-python==9.2.0
|
||||||
PyMySQL==1.1.1
|
PyMySQL==1.1.1
|
||||||
sqlmodel==0.0.24
|
sqlmodel==0.0.24
|
||||||
|
sqlalchemy[asyncio]
|
||||||
pydantic==2.10.6
|
pydantic==2.10.6
|
||||||
pydantic_core==2.27.2
|
pydantic_core==2.27.2
|
||||||
annotated-types==0.7.0
|
annotated-types==0.7.0
|
||||||
typing==3.7.4.3
|
typing==3.7.4.3
|
||||||
pysnmp==7.1.22
|
pysnmp==7.1.22
|
||||||
|
cryptography==46.0.5
|
||||||
# requests==2.32.3
|
# requests==2.32.3
|
||||||
influxdb-client==1.49.0
|
influxdb-client==1.49.0
|
||||||
# influxdb3-python==0.18.0
|
# influxdb3-python==0.18.0
|
||||||
0
cont/sqlFunct.py
Normal file
0
cont/sqlFunct.py
Normal file
Reference in New Issue
Block a user