From 3e942c9b1abb25b41be92c5679f209e4bc55d87f Mon Sep 17 00:00:00 2001 From: Guillaume Abrioux Date: Thu, 12 Oct 2023 13:29:19 +0000 Subject: [PATCH] node-proxy: update the JSON data structure Change the data structure from: ``` { "storage": "ok", "processors": "ok", "network": "ok", "memory": "ok", "power": "ok", "fans": "ok" } ``` to: ``` { "host": "node1", "sn": "xxxx", "status": { "storage": { } } } ``` In order to provide a unique key (sn) which is more reliable at the top level of the dict. Signed-off-by: Guillaume Abrioux (cherry picked from commit 65d3f781f92505eb708716eb281c670a71ed503c) --- src/cephadm/cephadm.py | 13 +++++--- .../node_proxy/baseredfishsystem.py | 16 +++++---- .../cephadmlib/node_proxy/basesystem.py | 7 ++++ src/cephadm/cephadmlib/node_proxy/main.py | 4 +-- .../node_proxy/redfishdellsystem.py | 3 ++ src/cephadm/cephadmlib/node_proxy/reporter.py | 8 +++-- src/pybind/mgr/cephadm/agent.py | 33 +++++++++---------- src/pybind/mgr/cephadm/inventory.py | 8 ++--- 8 files changed, 54 insertions(+), 38 deletions(-) diff --git a/src/cephadm/cephadm.py b/src/cephadm/cephadm.py index bfa5819788c2c..cd7973bd76a08 100755 --- a/src/cephadm/cephadm.py +++ b/src/cephadm/cephadm.py @@ -4916,10 +4916,13 @@ WantedBy=ceph-{fsid}.target return response_str def init_node_proxy(self, ssl_ctx: Any) -> None: - node_proxy_data = json.dumps({'keyring': self.keyring, - 'host': self.host}) - node_proxy_data = node_proxy_data.encode('ascii') - result = self.query_endpoint(data=node_proxy_data, + node_proxy_meta = { + 'cephx': { + 'name': self.host, + 'secret': self.keyring + } + } + result = self.query_endpoint(data=json.dumps(node_proxy_meta).encode('ascii'), endpoint='/node-proxy/idrac', ssl_ctx=ssl_ctx) result_json = json.loads(result) @@ -4927,7 +4930,7 @@ WantedBy=ceph-{fsid}.target 'host': result_json['result']['addr'], 'username': result_json['result']['username'], 'password': result_json['result']['password'], - 'data': node_proxy_data, + 'cephx': node_proxy_meta['cephx'], 'mgr_target_ip': self.target_ip, 'mgr_target_port': self.target_port, } diff --git a/src/cephadm/cephadmlib/node_proxy/baseredfishsystem.py b/src/cephadm/cephadmlib/node_proxy/baseredfishsystem.py index 850a86e933d60..b41983000cf1d 100644 --- a/src/cephadm/cephadmlib/node_proxy/baseredfishsystem.py +++ b/src/cephadm/cephadmlib/node_proxy/baseredfishsystem.py @@ -108,12 +108,16 @@ class BaseRedfishSystem(BaseSystem): def get_system(self) -> Dict[str, Dict[str, Dict]]: result = { - 'storage': self.get_storage(), - 'processors': self.get_processors(), - 'network': self.get_network(), - 'memory': self.get_memory(), - 'power': self.get_power(), - 'fans': self.get_fans() + 'host': self.get_host(), + 'sn': self.get_sn(), + 'status': { + 'storage': self.get_storage(), + 'processors': self.get_processors(), + 'network': self.get_network(), + 'memory': self.get_memory(), + 'power': self.get_power(), + 'fans': self.get_fans() + } } return result diff --git a/src/cephadm/cephadmlib/node_proxy/basesystem.py b/src/cephadm/cephadmlib/node_proxy/basesystem.py index d3571e921f922..d853e967cd34a 100644 --- a/src/cephadm/cephadmlib/node_proxy/basesystem.py +++ b/src/cephadm/cephadmlib/node_proxy/basesystem.py @@ -1,3 +1,4 @@ +import socket from .util import Config from typing import Dict, Any from .baseclient import BaseClient @@ -33,6 +34,12 @@ class BaseSystem: def get_storage(self) -> Dict[str, Dict[str, Dict]]: raise NotImplementedError() + def get_sn(self) -> str: + raise NotImplementedError() + + def get_host(self) -> str: + return socket.gethostname() + def start_update_loop(self) -> None: raise NotImplementedError() diff --git a/src/cephadm/cephadmlib/node_proxy/main.py b/src/cephadm/cephadmlib/node_proxy/main.py index 25a42e19f2f36..a906a3098c16f 100644 --- a/src/cephadm/cephadmlib/node_proxy/main.py +++ b/src/cephadm/cephadmlib/node_proxy/main.py @@ -216,8 +216,6 @@ class NodeProxy(Thread): log = Logger(__name__, level=config.__dict__['logging']['level']) - self.data = json.loads(self.__dict__['data']) - # create the redfish system and the obsever log.logger.info(f"Server initialization...") try: @@ -232,7 +230,7 @@ class NodeProxy(Thread): try: reporter_agent = Reporter(self.system, - self.data, + self.__dict__['cephx'], f"https://{self.__dict__['mgr_target_ip']}:{self.__dict__['mgr_target_port']}/node-proxy/data") except RuntimeError: log.logger.error("Can't initialize the reporter.") diff --git a/src/cephadm/cephadmlib/node_proxy/redfishdellsystem.py b/src/cephadm/cephadmlib/node_proxy/redfishdellsystem.py index a79a3fcf52be1..7d4d6f1a4a010 100644 --- a/src/cephadm/cephadmlib/node_proxy/redfishdellsystem.py +++ b/src/cephadm/cephadmlib/node_proxy/redfishdellsystem.py @@ -24,6 +24,9 @@ class RedfishDellSystem(BaseRedfishSystem): return normalize_dict(result) + def get_sn(self) -> str: + return self._system['SKU'] + def get_status(self) -> Dict[str, Dict[str, Dict]]: return self._system['status'] diff --git a/src/cephadm/cephadmlib/node_proxy/reporter.py b/src/cephadm/cephadmlib/node_proxy/reporter.py index 79de9509ac86f..5089dd1319798 100644 --- a/src/cephadm/cephadmlib/node_proxy/reporter.py +++ b/src/cephadm/cephadmlib/node_proxy/reporter.py @@ -6,11 +6,11 @@ from typing import Dict, Any class Reporter: - def __init__(self, system: Any, data: Dict[str, Any], observer_url: str) -> None: + def __init__(self, system: Any, cephx: Dict[str, Any], observer_url: str) -> None: self.system = system self.observer_url = observer_url self.finish = False - self.data = data + self.cephx = cephx self.log = Logger(__name__) self.log.logger.info(f'Observer url set to {self.observer_url}') @@ -36,7 +36,9 @@ class Reporter: self.log.logger.info('data ready to be sent to the mgr.') if not self.system.get_system() == self.system.previous_data: self.log.logger.info('data has changed since last iteration.') - self.data['data'] = self.system.get_system() + self.data = {} + self.data['cephx'] = self.cephx + self.data['patch'] = self.system.get_system() try: # TODO: add a timeout parameter to the reporter in the config file self.log.logger.info(f"sending data to {self.observer_url}") diff --git a/src/pybind/mgr/cephadm/agent.py b/src/pybind/mgr/cephadm/agent.py index adcff4e67c337..fab4f2ca8a0c2 100644 --- a/src/pybind/mgr/cephadm/agent.py +++ b/src/pybind/mgr/cephadm/agent.py @@ -116,7 +116,7 @@ class NodeProxy: if self.validate_node_proxy_data(data): idrac_details = self.mgr.get_store('node_proxy/idrac') idrac_details_json = json.loads(idrac_details) - results['result'] = idrac_details_json[data["host"]] + results['result'] = idrac_details_json[data["cephx"]["name"]] else: results['result'] = self.validate_msg @@ -125,18 +125,18 @@ class NodeProxy: def validate_node_proxy_data(self, data: Dict[str, Any]) -> bool: self.validate_msg = 'valid node-proxy data received.' cherrypy.response.status = 200 - if 'host' not in data: + if 'cephx' not in data: cherrypy.response.status = 400 self.validate_msg = 'The field \'host\' must be provided.' - elif 'keyring' not in data: + elif 'secret' not in data['cephx']: cherrypy.response.status = 400 self.validate_msg = 'The agent keyring must be provided.' - elif not self.mgr.agent_cache.agent_keys.get(data['host']): + elif not self.mgr.agent_cache.agent_keys.get(data['cephx']['name']): cherrypy.response.status = 400 - self.validate_msg = f'Make sure the agent is running on {data["host"]}' - elif data['keyring'] != self.mgr.agent_cache.agent_keys[data['host']]: + self.validate_msg = f'Make sure the agent is running on {data["cephx"]["name"]}' + elif data['cephx']['secret'] != self.mgr.agent_cache.agent_keys[data['cephx']['name']]: cherrypy.response.status = 403 - self.validate_msg = f'Got wrong keyring from agent on host {data["host"]}.' + self.validate_msg = f'Got wrong keyring from agent on host {data["cephx"]["name"]}.' return cherrypy.response.status == 200 @@ -145,7 +145,7 @@ class NodeProxy: data: Dict[str, Any]) -> List[Dict[str, str]]: nok_members: List[Dict[str, str]] = [] - for member in data[component].keys(): + for member in data.keys(): # Force a fake error for testing purpose if component == 'storage': _status = 'critical' @@ -154,9 +154,9 @@ class NodeProxy: _status = 'critical' state = "[Fake error] power supply unplugged." else: - _status = data[component][member]['status']['health'].lower() + _status = data[member]['status']['health'].lower() if _status.lower() != 'ok': - # state = data[component][member]['status']['state'] + # state = data[member]['status']['state'] _member = dict( member=member, status=_status, @@ -176,10 +176,9 @@ class NodeProxy: 'fans': 'HARDWARE_FANS' } - for component in data['data'].keys(): + for component in data['patch']['status'].keys(): self.mgr.remove_health_warning(mapping[component]) - nok_members = self.get_nok_members(component, - data['data']) + nok_members = self.get_nok_members(component, data['patch']['status'][component]) if nok_members: count = len(nok_members) @@ -199,8 +198,8 @@ class NodeProxy: data: Dict[str, Any] = cherrypy.request.json if self.validate_node_proxy_data(data): - host = data['host'] - self.mgr.node_proxy.save(host, data['data']) + host = data['cephx']['name'] + self.mgr.node_proxy.save(host, data['patch']) self.raise_alert(data) results["result"] = self.validate_msg @@ -238,9 +237,9 @@ class NodeProxy: except AttributeError: try: result = self.common(**kw) - except RuntimeError: + except RuntimeError as e: cherrypy.response.status = 404 - result = {} + result = {"error": f"{e}"} return {"error": "Not a valid endpoint."} finally: return result diff --git a/src/pybind/mgr/cephadm/inventory.py b/src/pybind/mgr/cephadm/inventory.py index c19099af6014f..1be1ef6eeb553 100644 --- a/src/pybind/mgr/cephadm/inventory.py +++ b/src/pybind/mgr/cephadm/inventory.py @@ -1439,7 +1439,7 @@ class NodeProxyCache: def fullreport(self, **kw: Any) -> Dict[str, Any]: hostname = kw.get('hostname') if hostname not in self.data.keys(): - return self.data + return [self.data[h] for h in self.data.keys()] else: return self.data[hostname] @@ -1456,8 +1456,8 @@ class NodeProxyCache: for host, data in results.items(): _result[host] = {} - for component, details in data.items(): - res = any([member['status']['health'].lower() != 'ok' for member in data[component].values()]) + for component, details in data['status'].items(): + res = any([member['status']['health'].lower() != 'ok' for member in data['status'][component].values()]) _result[host][component] = mapper[res] if hostname and hostname in results.keys(): @@ -1472,7 +1472,7 @@ class NodeProxyCache: for host, data in self.data.items(): try: - _result[host] = data[cmd] + _result[host] = data['status'][cmd] except KeyError: raise RuntimeError(f'Invalid node-proxy category {cmd}') -- 2.39.5