]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
node-proxy: handle nested Redfish paths for components
authorGuillaume Abrioux <gabrioux@ibm.com>
Tue, 3 Feb 2026 12:22:03 +0000 (13:22 +0100)
committerGuillaume Abrioux <gabrioux@ibm.com>
Thu, 5 Feb 2026 09:09:20 +0000 (10:09 +0100)
Add a _resolve_path() helper to support components whose data
lives under nested Redfish paths when assembling component data.

For instance, power is exposed at 'PowerSubsystem/PowerSupplies'

Fixes: https://tracker.ceph.com/issues/74749
Signed-off-by: Guillaume Abrioux <gabrioux@ibm.com>
src/ceph-node-proxy/ceph_node_proxy/atollon.py
src/ceph-node-proxy/ceph_node_proxy/baseredfishsystem.py
src/ceph-node-proxy/ceph_node_proxy/redfish.py

index 5d71b7730425849e726de5115f172a7ef54794ea..5b083420b45d5911724f49f6fae171c207c4e103 100644 (file)
@@ -1,12 +1,9 @@
 from ceph_node_proxy.baseredfishsystem import BaseRedfishSystem
 from ceph_node_proxy.util import get_logger
-from typing import Any, Dict
+from typing import Any
 
 
 class AtollonSystem(BaseRedfishSystem):
     def __init__(self, **kw: Any) -> None:
         super().__init__(**kw)
         self.log = get_logger(__name__)
-
-    def get_component_spec_overrides(self) -> Dict[str, Dict[str, Any]]:
-        return {'power': {'path': 'PowerSubsystem'}}
index 98b88d8416e944d5ef6200c1986630516e857e26..50f5b01c9d5811f908311cc1331d8711d0b95860 100644 (file)
@@ -29,7 +29,8 @@ class BaseRedfishSystem(BaseSystem):
         'network': ComponentUpdateSpec('systems', 'EthernetInterfaces', NETWORK_FIELDS, None),
         'processors': ComponentUpdateSpec('systems', 'Processors', PROCESSORS_FIELDS, None),
         'memory': ComponentUpdateSpec('systems', 'Memory', MEMORY_FIELDS, None),
-        'power': ComponentUpdateSpec('chassis', 'Power', POWER_FIELDS, 'PowerSupplies'),
+        # Power supplies: Chassis/.../PowerSubsystem/PowerSupplies (not like other components: like Systems/.../Memory)
+        'power': ComponentUpdateSpec('chassis', 'PowerSubsystem/PowerSupplies', POWER_FIELDS, None),
         'fans': ComponentUpdateSpec('chassis', 'Thermal', FANS_FIELDS, 'Fans'),
         'firmwares': ComponentUpdateSpec('update_service', 'FirmwareInventory', FIRMWARES_FIELDS, None),
     }
index c9ef874f31fb293d6dec20f5eb211041696ccdc7..70a99f380d19f929cb9654b5fd05c2003b4a2bb8 100644 (file)
@@ -245,6 +245,15 @@ def build_data(
     return normalize_dict(result)
 
 
+def _resolve_path(endpoint: Endpoint, path: str) -> Endpoint:
+    """Resolve an endpoint by traversing path segments (example: 'PowerSubsystem/PowerSupplies')."""
+    parts = [p for p in path.split('/') if p]
+    current = endpoint
+    for part in parts:
+        current = current[part]
+    return current
+
+
 def update_component(
     endpoints: EndpointMgr,
     collection: str,
@@ -255,21 +264,25 @@ def update_component(
     log: Any,
     attribute: Optional[str] = None,
 ) -> None:
-    """Update _sys[component] from Redfish endpoints using the given spec."""
+    """Update _sys[component] from Redfish endpoints using the given spec.
+    path can be a single segment ('Memory') or multiple ('PowerSubsystem/PowerSupplies').
+    """
     members: List[str] = endpoints[collection].get_members_names()
     result: Dict[str, Any] = {}
     if not members:
-        data = endpoints[collection][path].get_members_data()
+        ep = _resolve_path(endpoints[collection], path)
+        data = ep.get_members_data()
         result = build_data(data=data, fields=fields, log=log, attribute=attribute)
     else:
         for member in members:
             try:
+                ep = _resolve_path(endpoints[collection][member], path)
                 if attribute is None:
-                    data = endpoints[collection][member][path].get_members_data()
+                    data = ep.get_members_data()
                 else:
-                    data = endpoints[collection][member][path].data
+                    data = ep.data
+                result[member] = build_data(data=data, fields=fields, log=log, attribute=attribute)
             except HTTPError as e:
                 log.error(f'Error while updating {component}: {e}')
                 continue
-            result[member] = build_data(data=data, fields=fields, log=log, attribute=attribute)
     _sys[component] = result