fast_ilo_exporter/scrape.py

173 lines
5.6 KiB
Python

from snmp import snmp_walk, SnmpConfiguration, SnmpEngine, CommunityData, UdpTransportTarget, ContextData
from https import get_json_response, HttpsConfiguration
from targets.fan import FAN_ENDPOINT
from targets.temp import TEMP_ENDPOINT
import traceback
def detect_things(c: SnmpConfiguration, base_oid: str) -> list[int]:
""" Scans for things and returns a list of their ids. """
things = []
for _, index in snmp_walk(c, base_oid):
assert isinstance(index, int)
assert index not in things
things.append(index)
return things
# because of the way drive indexing works, this is the simplest way I can think to do it without over-complicating
# everything else
def detect_complex(c: SnmpConfiguration, base_oid: str) -> list[tuple[int]]:
""" Scans for things and returns a list of their oid indexes. """
drives = []
for oid, _ in snmp_walk(c, base_oid):
index = oid[len(base_oid) + 1:]
index = (*[int(i) for i in index.split('.')],)
assert index not in drives
drives.append(index)
return drives
# since there's only two that get fetched via https, these are just kinda hacked together
def get_fan_speeds(c: HttpsConfiguration) -> dict[int, tuple[int | float, str]]: # {id: (speed, unit)}
speed_map = {}
response = get_json_response(c, FAN_ENDPOINT)
try:
fans = response['fans']
for fan in fans:
# try to derive fan id
label = fan.get('label')
if not isinstance(label, str):
continue
fan_id = str(label[4:]) # label seems to follow a format of "Fan X"
if not fan_id.isnumeric():
continue
fan_id = int(fan_id)
# get speed
speed = fan.get('speed')
if not (isinstance(speed, int) or isinstance(speed, float)):
speed = -1
# get units
unit = fan.get('speed_unit')
if not isinstance(unit, str):
unit = 'unknown'
speed_map[fan_id] = (speed, unit)
except (KeyError, TypeError) as e:
print('unexpected response from ILO')
traceback.print_exception(e)
print('response:', response)
return speed_map
def get_temp_sensor_info(c: HttpsConfiguration) -> dict[int, dict[str, str | int | float]]:
# {id: {name: value}}
labels = {}
response = get_json_response(c, TEMP_ENDPOINT)
try:
sensors = response['temperature']
for sensor in sensors:
sensor_labels = {}
# try to derive sensor id
label = sensor.get('label')
if not isinstance(label, str):
continue
sensor_id = str(label[:2]) # label seems to follow a format of "XX-Some Sensor"
if not sensor_id.isnumeric():
continue
sensor_id = int(sensor_id)
for key in ['label', 'xposition', 'yposition']:
value = sensor.get(key)
if value is not None:
sensor_labels[key] = str(value)
for key in ['caution', 'critical']:
value = sensor.get(key)
if isinstance(value, int) or isinstance(value, float):
sensor_labels[key] = value
labels[sensor_id] = sensor_labels
except (KeyError, TypeError) as e:
print('unexpected response from ILO')
traceback.print_exception(e)
print('response:', response)
return labels
if __name__ == '__main__':
from targets.fan import FAN_VALUES, FAN_INDEX
from targets.temp import TEMP_VALUES, TEMP_INDEX
from targets.cpu import CPU_VALUES, CPU_INDEX
from targets.memory import MEMORY_VALUES, MEMORY_INDEX
from targets.drive import DRIVE_INDEX
from targets.logical_drive import LOGICAL_DRIVES_INDEX
config = SnmpConfiguration(
SnmpEngine(),
CommunityData('public'),
UdpTransportTarget(('192.168.100.88', 161)),
ContextData(),
)
print('scanning hardware...')
fans = detect_things(config, FAN_INDEX)
temp_sensors = detect_things(config, TEMP_INDEX)
cpus = detect_things(config, CPU_INDEX)
logical_drives = detect_things(config, LOGICAL_DRIVES_INDEX)
drives = detect_complex(config, DRIVE_INDEX)
memory_slots = detect_things(config, MEMORY_INDEX)
print('\'puter has', len(fans), 'fans')
print('\'puter has', len(temp_sensors), 'temp sensors')
print('\'puter has', len(cpus), 'processors')
print('\'puter has', len(logical_drives), 'logical drives')
print('\'puter has', len(drives), 'physical drives')
print('\'puter has', len(memory_slots), 'memory slots')
for ilo_enum in FAN_VALUES:
states = ilo_enum.get_values(config, fans)
for fan in fans:
print('fan', fan, ilo_enum.name, 'is', states[fan])
print()
for value in TEMP_VALUES:
states = value.get_values(config, temp_sensors)
for sensor in temp_sensors:
print('temperature', sensor, value.name, 'is', states[sensor])
print()
for value in CPU_VALUES:
states = value.get_values(config, cpus)
for cpu in cpus:
print('cpu', cpu, value.name, 'is', states[cpu])
print()
for value in MEMORY_VALUES:
states = value.get_values(config, memory_slots)
for slot in memory_slots:
print('memory slot', slot, value.name, 'is', states[slot])
print()
print('asdf')
conf = HttpsConfiguration(
'192.168.100.88',
'some username',
'some password',
'./ilo.pem',
5
)
print(get_fan_speeds(conf))
print(get_temp_sensor_info(conf))