]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/cephadm: validate hostname in NodeProxyCache
authorGuillaume Abrioux <gabrioux@ibm.com>
Mon, 16 Feb 2026 13:24:36 +0000 (14:24 +0100)
committerGuillaume Abrioux <gabrioux@ibm.com>
Wed, 18 Feb 2026 12:26:01 +0000 (13:26 +0100)
This adds a _resolve_hosts() method to resolve hostname from kwargs
and raise OrchestratorError when the host has no node-proxy data.

Fixes: https://tracker.ceph.com/issues/74749
Signed-off-by: Guillaume Abrioux <gabrioux@ibm.com>
src/pybind/mgr/cephadm/agent.py
src/pybind/mgr/cephadm/inventory.py

index 6f52ad47514b89a0169faa01cc28a706272a4131..e6aafce4c78d66f3b3e6a803bd5255a197f5f960 100644 (file)
@@ -13,7 +13,7 @@ import ssl
 import threading
 import time
 
-from orchestrator import DaemonDescriptionStatus
+from orchestrator import DaemonDescriptionStatus, OrchestratorError
 from orchestrator._interface import daemon_type_to_service
 from ceph.utils import datetime_now, http_req
 from ceph.deployment.inventory import Devices
@@ -418,7 +418,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.fullreport(**kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -442,7 +442,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.criticals(**kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -466,7 +466,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.summary(**kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -491,7 +491,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.common('memory', **kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -516,7 +516,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.common('network', **kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -541,7 +541,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.common('processors', **kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -566,7 +566,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.common('storage', **kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -591,7 +591,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.common('power', **kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -616,7 +616,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.common('fans', **kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
@@ -640,7 +640,7 @@ class NodeProxyEndpoint:
         """
         try:
             results = self.mgr.node_proxy_cache.firmwares(**kw)
-        except KeyError:
+        except (KeyError, OrchestratorError):
             raise cherrypy.HTTPError(404, f"{kw.get('hostname')} not found.")
         return results
 
index 37e346845c3d68eec9f439a9eeb8f69c9dfe08c4..aed6ba03efadb406ce9fc42a08864007bed7a1d2 100644 (file)
@@ -1669,6 +1669,16 @@ class NodeProxyCache:
     def _is_unknown_status(self, statuses: ValuesView) -> bool:
         return self._has_health_value(statuses, 'unknown') and not self._is_error_status(statuses)
 
+    def _resolve_hosts(self, **kw: Any) -> List[str]:
+        hostname = kw.get('hostname')
+        if hostname is None:
+            return list(self.data.keys())
+        if hostname not in self.data:
+            raise OrchestratorError(
+                f"Host '{hostname}' has no node-proxy data (unknown host or node-proxy not running)."
+            )
+        return [hostname]
+
     def fullreport(self, **kw: Any) -> Dict[str, Any]:
         """
         Retrieves the full report for the specified hostname.
@@ -1683,8 +1693,7 @@ class NodeProxyCache:
         :return: The full report data for the specified hostname(s).
         :rtype: dict
         """
-        hostname = kw.get('hostname')
-        hosts = [hostname] if hostname else self.data.keys()
+        hosts = self._resolve_hosts(**kw)
         return {host: self.data[host] for host in hosts}
 
     def summary(self, **kw: Any) -> Dict[str, Any]:
@@ -1703,9 +1712,7 @@ class NodeProxyCache:
                 host or all hosts and their components.
         :rtype: Dict[str, Dict[str, str]]
         """
-        hostname = kw.get('hostname')
-        hosts = [hostname] if hostname else self.data.keys()
-
+        hosts = self._resolve_hosts(**kw)
         _result: Dict[str, Any] = {}
 
         for host in hosts:
@@ -1751,9 +1758,8 @@ class NodeProxyCache:
         :return: Endpoint information for the specified host(s).
         :rtype: Union[Dict[str, Any], Any]
         """
-        hostname = kw.get('hostname')
+        hosts = self._resolve_hosts(**kw)
         _result = {}
-        hosts = [hostname] if hostname else self.data.keys()
 
         for host in hosts:
             try:
@@ -1776,12 +1782,14 @@ class NodeProxyCache:
         :return: A dictionary containing firmware information for each host.
         :rtype: Dict[str, Any]
         """
-        hostname = kw.get('hostname')
-        hosts = [hostname] if hostname else self.data.keys()
-
+        hosts = self._resolve_hosts(**kw)
         return {host: self.data[host]['firmwares'] for host in hosts}
 
     def get_critical_from_host(self, hostname: str) -> Dict[str, Any]:
+        if hostname not in self.data:
+            raise OrchestratorError(
+                f"Host '{hostname}' has no node-proxy data (unknown host or node-proxy not running)."
+            )
         results: Dict[str, Any] = {}
 
         for component, component_data in self.data[hostname]['status'].items():
@@ -1812,10 +1820,9 @@ class NodeProxyCache:
         :return: A dictionary containing critical information for each host.
         :rtype: List[Dict[str, Any]]
         """
-        hostname = kw.get('hostname')
+        hosts = self._resolve_hosts(**kw)
         results: Dict[str, Any] = {}
 
-        hosts = [hostname] if hostname else self.data.keys()
         for host in hosts:
             results[host] = self.get_critical_from_host(host)
         return results