]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
node-proxy: update the JSON data structure
authorGuillaume Abrioux <gabrioux@ibm.com>
Thu, 12 Oct 2023 13:29:19 +0000 (13:29 +0000)
committerGuillaume Abrioux <gabrioux@ibm.com>
Thu, 25 Jan 2024 15:09:40 +0000 (15:09 +0000)
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 <gabrioux@ibm.com>
(cherry picked from commit 65d3f781f92505eb708716eb281c670a71ed503c)

src/cephadm/cephadm.py
src/cephadm/cephadmlib/node_proxy/baseredfishsystem.py
src/cephadm/cephadmlib/node_proxy/basesystem.py
src/cephadm/cephadmlib/node_proxy/main.py
src/cephadm/cephadmlib/node_proxy/redfishdellsystem.py
src/cephadm/cephadmlib/node_proxy/reporter.py
src/pybind/mgr/cephadm/agent.py
src/pybind/mgr/cephadm/inventory.py

index bfa5819788c2c0c4477b12ed3eca656e605da143..cd7973bd76a08e7fe88a1ae7c3e9339d64775d68 100755 (executable)
@@ -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,
         }
index 850a86e933d607b8a92afa1d4c5e68cd00ebf057..b41983000cf1dd84c0e433c508ee066707e882c6 100644 (file)
@@ -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
 
index d3571e921f92284763395c7f0cebb4a09fcf9170..d853e967cd34a29f28769fc73074bf79f0a9f09d 100644 (file)
@@ -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()
 
index 25a42e19f2f36e2a8c517dc2ebde4e8d156f9dde..a906a3098c16f1669d11c36af3d94eb6342916b3 100644 (file)
@@ -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.")
index a79a3fcf52be1c9fcfae3464d0690d387124ac39..7d4d6f1a4a0101fb74d174bad591bde82c0f9fcb 100644 (file)
@@ -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']
 
index 79de9509ac86f70f4593863e61e7b7126363506c..5089dd13197981ec2b17f9b71ee2b341a366cf8f 100644 (file)
@@ -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}")
index adcff4e67c337395885f6b985c4b502a909f1342..fab4f2ca8a0c22fb07e2c6de6520f33d967b6d5c 100644 (file)
@@ -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
index c19099af6014fd4ebae1c1541c50c845ec7a9ce4..1be1ef6eeb553687bc610c678bbc45cd8fb8833e 100644 (file)
@@ -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}')