add dataclass RedfishResource, update discover_redfish_resources, process_power_supply
This commit is contained in:
@@ -19,6 +19,22 @@ from prometheus_client import (
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RedfishResource:
|
||||
"""Container for Redfish resource URLs."""
|
||||
chassis: str | None = None
|
||||
systems: str | None = None
|
||||
power: str | None = None
|
||||
session_service: str | None = None
|
||||
|
||||
@dataclass
|
||||
class PowerMetrics:
|
||||
"""Container for power metrics."""
|
||||
voltage: float | None = None
|
||||
watts: float | None = None
|
||||
amps: float | None = None
|
||||
serial: str | None = None
|
||||
|
||||
@dataclass
|
||||
class RedfishSession:
|
||||
"""Container for Redfish session data."""
|
||||
@@ -132,8 +148,8 @@ async def login_hpe(session, host: HostConfig) -> bool:
|
||||
try:
|
||||
async with session.post(login_url, json=payload, ssl=False, timeout=10) as login_resp:
|
||||
if login_resp.status == 201:
|
||||
host.session_token = login_resp.headers.get("X-Auth-Token")
|
||||
host.session_logout = login_resp.headers.get("Location")
|
||||
host.session.token = login_resp.headers.get("X-Auth-Token")
|
||||
host.session.logout_url = login_resp.headers.get("Location")
|
||||
|
||||
if not host.session.token or not host.session.logout_url:
|
||||
raise RuntimeError("Invalid login response")
|
||||
@@ -228,23 +244,25 @@ async def fetch_with_retry(session, host: HostConfig, url: str) -> dict | None:
|
||||
return None
|
||||
|
||||
|
||||
async def discover_redfish_resources(session, host: HostConfig) -> dict:
|
||||
async def discover_redfish_resources(session, host: HostConfig) -> RedfishResource | None:
|
||||
"""Discover available Redfish resources and return relevant URLs"""
|
||||
root_url = f"https://{host.fqdn}/redfish/v1/"
|
||||
data = await fetch_with_retry(session, host, root_url)
|
||||
if not data:
|
||||
return {}
|
||||
|
||||
# Extrahiere Links aus der Root-Antwort
|
||||
links = {
|
||||
"Chassis": data.get("Chassis", {}).get("@odata.id"),
|
||||
"Systems": data.get("Systems", {}).get("@odata.id"),
|
||||
"SessionService": data.get("SessionService", {}).get("@odata.id"),
|
||||
}
|
||||
if not links["Chassis"]:
|
||||
# Create RedfishRessource object
|
||||
resources = RedfishResource(
|
||||
chassis=data.get("Chassis", {}).get("@odata.id"),
|
||||
systems=data.get("Systems", {}).get("@odata.id"),
|
||||
session_service=data.get("SessionService", {}).get("@odata.id"),
|
||||
)
|
||||
|
||||
if not resources.chassis:
|
||||
logging.error("No valid Chassis URL found for host %s", host.fqdn)
|
||||
return {}
|
||||
return links
|
||||
return None
|
||||
|
||||
return resources
|
||||
|
||||
|
||||
def get_power_resource_info(
|
||||
@@ -313,54 +331,46 @@ def process_power_supplies(
|
||||
|
||||
async def process_power_supply(
|
||||
session, host: HostConfig, psu_data: dict, power_resource_type: str
|
||||
):
|
||||
) -> PowerMetrics | None:
|
||||
"""Extract metrics from PowerSupply"""
|
||||
serial = psu_data.get("SerialNumber")
|
||||
metrics = PowerMetrics(serial=serial)
|
||||
|
||||
if power_resource_type == "PowerSubsystem":
|
||||
# Newer Redfish API: Metrics are an own "Metrics" ressource
|
||||
# New Redfish API: Metrics are an own "Metrics" ressource
|
||||
metrics_url = psu_data.get("Metrics", {}).get("@odata.id")
|
||||
if not metrics_url:
|
||||
logging.warning("No Metrics found for PowerSupply %s", psu_data.get("Id"))
|
||||
return
|
||||
return None
|
||||
|
||||
metrics_url = f"https://{host.fqdn}{metrics_url}"
|
||||
metrics_data = await fetch_with_retry(session, host, metrics_url)
|
||||
if not metrics_data:
|
||||
return
|
||||
return None
|
||||
|
||||
# Get metrics from Metrics ressource
|
||||
line_input_v = metrics_data.get("InputVoltage", {}).get("Reading")
|
||||
watts_input = metrics_data.get("InputPowerWatts", {}).get("Reading")
|
||||
amps_input = metrics_data.get("InputCurrentAmps", {}).get("Reading")
|
||||
metrics.voltage = metrics_data.get("InputVoltage", {}).get("Reading")
|
||||
metrics.watts = metrics_data.get("InputPowerWatts", {}).get("Reading")
|
||||
metrics.amps = metrics_data.get("InputCurrentAmps", {}).get("Reading")
|
||||
|
||||
elif power_resource_type == "Power":
|
||||
# Older Redfish API: Metrics are direct in PowerSupply as an array
|
||||
line_input_v = psu_data.get("LineInputVoltage")
|
||||
watts_input = psu_data.get("PowerInputWatts")
|
||||
if watts_input is None:
|
||||
watts_input = psu_data.get("LastPowerOutputWatts")
|
||||
amps_input = psu_data.get("InputCurrentAmps")
|
||||
if amps_input is None:
|
||||
if line_input_v and watts_input:
|
||||
amps_input = round(watts_input / line_input_v, 2)
|
||||
metrics.voltage = psu_data.get("LineInputVoltage")
|
||||
metrics.watts = psu_data.get("PowerInputWatts")
|
||||
if metrics.watts is None:
|
||||
metrics.watts = psu_data.get("LastPowerOutputWatts")
|
||||
metrics.amps = psu_data.get("InputCurrentAmps")
|
||||
if metrics.amps is None and metrics.voltage and metrics.watts:
|
||||
metrics.amps = round(metrics.watts / metrics.voltage, 2)
|
||||
|
||||
else:
|
||||
logging.error(
|
||||
"Unknown power resource type for PowerSupply %s", psu_data.get("Id")
|
||||
)
|
||||
return
|
||||
|
||||
if amps_input is None and line_input_v and watts_input:
|
||||
amps_input = round(watts_input / line_input_v, 2)
|
||||
return None
|
||||
|
||||
# Update Prometheus metrics
|
||||
if line_input_v is not None:
|
||||
VOLTAGE_GAUGE.labels(host=host.fqdn, psu_serial=serial).set(line_input_v)
|
||||
if watts_input is not None:
|
||||
WATTS_GAUGE.labels(host=host.fqdn, psu_serial=serial).set(watts_input)
|
||||
if amps_input is not None:
|
||||
AMPS_GAUGE.labels(host=host.fqdn, psu_serial=serial).set(amps_input)
|
||||
return metrics
|
||||
|
||||
|
||||
def normalize_url(url: str) -> str:
|
||||
|
||||
Reference in New Issue
Block a user