summaryrefslogtreecommitdiffstats
path: root/src/pybind
diff options
context:
space:
mode:
authorGuillaume Abrioux <gabrioux@ibm.com>2024-04-09 17:07:45 +0200
committerGuillaume Abrioux <gabrioux@redhat.com>2024-05-06 09:06:49 +0200
commitce360a4a5f67329b95a4b75bc7b5e59dc7633637 (patch)
treee79f3b2becc20f61ba6e88010287e40cf0106b90 /src/pybind
parentnode-proxy: do not fail when empty data is received (diff)
downloadceph-ce360a4a5f67329b95a4b75bc7b5e59dc7633637.tar.xz
ceph-ce360a4a5f67329b95a4b75bc7b5e59dc7633637.zip
node-proxy: make the daemon discover endpoints
Add logic in order to explore the API. This will allow node-proxy to be compatible with more hardware. Fixes: https://tracker.ceph.com/issues/65394 Signed-off-by: Guillaume Abrioux <gabrioux@ibm.com>
Diffstat (limited to 'src/pybind')
-rw-r--r--src/pybind/mgr/cephadm/agent.py26
-rw-r--r--src/pybind/mgr/cephadm/inventory.py61
-rw-r--r--src/pybind/mgr/cephadm/tests/node_proxy_data.py4
-rw-r--r--src/pybind/mgr/cephadm/tests/test_node_proxy.py6
-rw-r--r--src/pybind/mgr/orchestrator/module.py61
5 files changed, 89 insertions, 69 deletions
diff --git a/src/pybind/mgr/cephadm/agent.py b/src/pybind/mgr/cephadm/agent.py
index 12c03901de8..e38122ddc4b 100644
--- a/src/pybind/mgr/cephadm/agent.py
+++ b/src/pybind/mgr/cephadm/agent.py
@@ -192,16 +192,18 @@ class NodeProxyEndpoint:
"""
nok_members: List[Dict[str, str]] = []
- for member in data.keys():
- _status = data[member]['status']['health'].lower()
- if _status.lower() != 'ok':
- state = data[member]['status']['state']
- _member = dict(
- member=member,
- status=_status,
- state=state
- )
- nok_members.append(_member)
+ for sys_id in data.keys():
+ for member in data[sys_id].keys():
+ _status = data[sys_id][member]['status']['health'].lower()
+ if _status.lower() != 'ok':
+ state = data[sys_id][member]['status']['state']
+ _member = dict(
+ sys_id=sys_id,
+ member=member,
+ status=_status,
+ state=state
+ )
+ nok_members.append(_member)
return nok_members
@@ -229,7 +231,7 @@ class NodeProxyEndpoint:
"""
for component in data['patch']['status'].keys():
- alert_name = f"HARDWARE_{component.upper()}"
+ alert_name = f'HARDWARE_{component.upper()}'
self.mgr.remove_health_warning(alert_name)
nok_members = self.get_nok_members(data['patch']['status'][component])
@@ -239,7 +241,7 @@ class NodeProxyEndpoint:
alert_name,
summary=f'{count} {component} member{"s" if count > 1 else ""} {"are" if count > 1 else "is"} not ok',
count=count,
- detail=[f"{member['member']} is {member['status']}: {member['state']}" for member in nok_members],
+ detail=[f"[{member['sys_id']}]: {member['member']} is {member['status']}: {member['state']}" for member in nok_members],
)
@cherrypy.expose
diff --git a/src/pybind/mgr/cephadm/inventory.py b/src/pybind/mgr/cephadm/inventory.py
index cbaff8a5b00..5ecb142cb6a 100644
--- a/src/pybind/mgr/cephadm/inventory.py
+++ b/src/pybind/mgr/cephadm/inventory.py
@@ -1410,7 +1410,7 @@ class HostCache():
class NodeProxyCache:
- def __init__(self, mgr: "CephadmOrchestrator") -> None:
+ def __init__(self, mgr: 'CephadmOrchestrator') -> None:
self.mgr = mgr
self.data: Dict[str, Any] = {}
self.oob: Dict[str, Any] = {}
@@ -1428,7 +1428,7 @@ class NodeProxyCache:
if host not in self.mgr.inventory.keys():
# remove entry for host that no longer exists
- self.mgr.set_store(f"{NODE_PROXY_CACHE_PREFIX}/data/{host}", None)
+ self.mgr.set_store(f'{NODE_PROXY_CACHE_PREFIX}/data/{host}', None)
try:
self.oob.pop(host)
self.data.pop(host)
@@ -1442,15 +1442,15 @@ class NodeProxyCache:
def save(self,
host: str = '',
data: Dict[str, Any] = {}) -> None:
- self.mgr.set_store(f"{NODE_PROXY_CACHE_PREFIX}/data/{host}", json.dumps(data))
+ self.mgr.set_store(f'{NODE_PROXY_CACHE_PREFIX}/data/{host}', json.dumps(data))
def update_oob(self, host: str, host_oob_info: Dict[str, str]) -> None:
self.oob[host] = host_oob_info
- self.mgr.set_store(f"{NODE_PROXY_CACHE_PREFIX}/oob", json.dumps(self.oob))
+ self.mgr.set_store(f'{NODE_PROXY_CACHE_PREFIX}/oob', json.dumps(self.oob))
def update_keyring(self, host: str, key: str) -> None:
self.keyrings[host] = key
- self.mgr.set_store(f"{NODE_PROXY_CACHE_PREFIX}/keyrings", json.dumps(self.keyrings))
+ self.mgr.set_store(f'{NODE_PROXY_CACHE_PREFIX}/keyrings', json.dumps(self.keyrings))
def fullreport(self, **kw: Any) -> Dict[str, Any]:
"""
@@ -1500,19 +1500,29 @@ class NodeProxyCache:
for host in hosts:
_result[host] = {}
_result[host]['status'] = {}
+ state: str = ''
data = self.data[host]
- for component in data['status'].keys():
- values = data['status'][component].values()
- if is_error(values):
- state = 'error'
- elif is_unknown(values):
+ for component, details in data['status'].items():
+ _sys_id_res: List[str] = []
+ for element in details.values():
+ values = element.values()
+ if is_error(values):
+ state = 'error'
+ elif is_unknown(values) or not values:
+ state = 'unknown'
+ else:
+ state = 'ok'
+ _sys_id_res.append(state)
+ if any([s == 'unknown' for s in _sys_id_res]):
state = 'unknown'
+ elif any([s == 'error' for s in _sys_id_res]):
+ state = 'error'
else:
state = 'ok'
_result[host]['status'][component] = state
- _result[host]['sn'] = data['sn']
- _result[host]['host'] = data['host']
- _result[host]['firmwares'] = data['firmwares']
+ _result[host]['sn'] = data['sn']
+ _result[host]['host'] = data['host']
+ _result[host]['status']['firmwares'] = data['firmwares']
return _result
def common(self, endpoint: str, **kw: Any) -> Dict[str, Any]:
@@ -1562,18 +1572,19 @@ class NodeProxyCache:
def get_critical_from_host(self, hostname: str) -> Dict[str, Any]:
results: Dict[str, Any] = {}
- for component, data_component in self.data[hostname]['status'].items():
- if component not in results.keys():
- results[component] = {}
- for member, data_member in data_component.items():
- if component == 'power':
- data_member['status']['health'] = 'critical'
- data_member['status']['state'] = 'unplugged'
- if component == 'memory':
- data_member['status']['health'] = 'critical'
- data_member['status']['state'] = 'errors detected'
- if data_member['status']['health'].lower() != 'ok':
- results[component][member] = data_member
+ for sys_id, component in self.data[hostname]['status'].items():
+ for component_name, data_component in component.items():
+ if component_name not in results.keys():
+ results[component_name] = {}
+ for member, data_member in data_component.items():
+ if component_name == 'power':
+ data_member['status']['health'] = 'critical'
+ data_member['status']['state'] = 'unplugged'
+ if component_name == 'memory':
+ data_member['status']['health'] = 'critical'
+ data_member['status']['state'] = 'errors detected'
+ if data_member['status']['health'].lower() != 'ok':
+ results[component_name][member] = data_member
return results
def criticals(self, **kw: Any) -> Dict[str, Any]:
diff --git a/src/pybind/mgr/cephadm/tests/node_proxy_data.py b/src/pybind/mgr/cephadm/tests/node_proxy_data.py
index 37e6aaa46c8..fa768f1d4c6 100644
--- a/src/pybind/mgr/cephadm/tests/node_proxy_data.py
+++ b/src/pybind/mgr/cephadm/tests/node_proxy_data.py
@@ -1,3 +1,3 @@
-full_set_with_critical = {'host': 'host01', 'sn': '12345', 'status': {'storage': {'disk.bay.0:enclosure.internal.0-1:raid.integrated.1-1': {'description': 'Solid State Disk 0:1:0', 'entity': 'RAID.Integrated.1-1', 'capacity_bytes': 959656755200, 'model': 'KPM5XVUG960G', 'protocol': 'SAS', 'serial_number': '8080A1CRTP5F', 'status': {'health': 'Critical', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 0, 'locationtype': 'Slot'}}}, 'disk.bay.9:enclosure.internal.0-1': {'description': 'PCIe SSD in Slot 9 in Bay 1', 'entity': 'CPU.1', 'capacity_bytes': 1600321314816, 'model': 'Dell Express Flash NVMe P4610 1.6TB SFF', 'protocol': 'PCIe', 'serial_number': 'PHLN035305MN1P6AGN', 'status': {'health': 'Critical', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 9, 'locationtype': 'Slot'}}}}, 'processors': {'cpu.socket.2': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 20, 'total_threads': 40, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Gold 6230 CPU @ 2.10GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}}, 'network': {'nic.slot.1-1-1': {'description': 'NIC in Slot 1 Port 1 Partition 1', 'name': 'System Ethernet Interface', 'speed_mbps': 0, 'status': {'health': 'OK', 'state': 'StandbyOffline'}}}, 'memory': {'dimm.socket.a1': {'description': 'DIMM A1', 'memory_device_type': 'DDR4', 'capacity_mi_b': 31237, 'status': {'health': 'Critical', 'state': 'Enabled'}}}}, 'firmwares': {}}
+full_set_with_critical = {'host': 'host01', 'sn': '12345', 'status': {'storage': {'1': {'disk.bay.0:enclosure.internal.0-1:raid.integrated.1-1': {'description': 'Solid State Disk 0:1:0', 'entity': 'RAID.Integrated.1-1', 'capacity_bytes': 959656755200, 'model': 'KPM5XVUG960G', 'protocol': 'SAS', 'serial_number': '8080A1CRTP5F', 'status': {'health': 'Critical', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 0, 'locationtype': 'Slot'}}}, 'disk.bay.9:enclosure.internal.0-1': {'description': 'PCIe SSD in Slot 9 in Bay 1', 'entity': 'CPU.1', 'capacity_bytes': 1600321314816, 'model': 'Dell Express Flash NVMe P4610 1.6TB SFF', 'protocol': 'PCIe', 'serial_number': 'PHLN035305MN1P6AGN', 'status': {'health': 'Critical', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 9, 'locationtype': 'Slot'}}}}}, 'processors': {'1': {'cpu.socket.2': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 20, 'total_threads': 40, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Gold 6230 CPU @ 2.10GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}}}, 'network': {'1': {'nic.slot.1-1-1': {'description': 'NIC in Slot 1 Port 1 Partition 1', 'name': 'System Ethernet Interface', 'speed_mbps': 0, 'status': {'health': 'OK', 'state': 'StandbyOffline'}}}}, 'memory': {'1': {'dimm.socket.a1': {'description': 'DIMM A1', 'memory_device_type': 'DDR4', 'capacity_mi_b': 31237, 'status': {'health': 'Critical', 'state': 'Enabled'}}}}}, 'firmwares': {}}
mgr_inventory_cache = {'host01': {'hostname': 'host01', 'addr': '10.10.10.11', 'labels': ['_admin'], 'status': '', 'oob': {'hostname': '10.10.10.11', 'username': 'root', 'password': 'ceph123'}}, 'host02': {'hostname': 'host02', 'addr': '10.10.10.12', 'labels': [], 'status': '', 'oob': {'hostname': '10.10.10.12', 'username': 'root', 'password': 'ceph123'}}}
-full_set = {'host01': {'host': 'host01', 'sn': 'FR8Y5X3', 'status': {'storage': {'disk.bay.8:enclosure.internal.0-1:nonraid.slot.2-1': {'description': 'Disk 8 in Backplane 1 of Storage Controller in Slot 2', 'entity': 'NonRAID.Slot.2-1', 'capacity_bytes': 20000588955136, 'model': 'ST20000NM008D-3D', 'protocol': 'SATA', 'serial_number': 'ZVT99QLL', 'status': {'health': 'OK', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 8, 'locationtype': 'Slot'}}}}, 'processors': {'cpu.socket.2': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}, 'cpu.socket.1': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}}, 'network': {'oslogicalnetwork.2': {'description': 'eno8303', 'name': 'eno8303', 'speed_mbps': 0, 'status': {'health': 'OK', 'state': 'Enabled'}}}, 'memory': {'dimm.socket.a1': {'description': 'DIMM A1', 'memory_device_type': 'DDR4', 'capacity_mi_b': 16384, 'status': {'health': 'OK', 'state': 'Enabled'}}}, 'power': {'0': {'name': 'PS1 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}, '1': {'name': 'PS2 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}}, 'fans': {'0': {'name': 'System Board Fan1A', 'physical_context': 'SystemBoard', 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'firmwares': {'installed-28897-6.10.30.20__usc.embedded.1:lc.embedded.1': {'name': 'Lifecycle Controller', 'description': 'Represents Firmware Inventory', 'release_date': '00:00:00Z', 'version': '6.10.30.20', 'updateable': True, 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'host02': {'host': 'host02', 'sn': 'FR8Y5X4', 'status': {'storage': {'disk.bay.8:enclosure.internal.0-1:nonraid.slot.2-1': {'description': 'Disk 8 in Backplane 1 of Storage Controller in Slot 2', 'entity': 'NonRAID.Slot.2-1', 'capacity_bytes': 20000588955136, 'model': 'ST20000NM008D-3D', 'protocol': 'SATA', 'serial_number': 'ZVT99QLL', 'status': {'health': 'OK', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 8, 'locationtype': 'Slot'}}}}, 'processors': {'cpu.socket.2': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}, 'cpu.socket.1': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}}, 'network': {'oslogicalnetwork.2': {'description': 'eno8303', 'name': 'eno8303', 'speed_mbps': 0, 'status': {'health': 'OK', 'state': 'Enabled'}}}, 'memory': {'dimm.socket.a1': {'description': 'DIMM A1', 'memory_device_type': 'DDR4', 'capacity_mi_b': 16384, 'status': {'health': 'OK', 'state': 'Enabled'}}}, 'power': {'0': {'name': 'PS1 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}, '1': {'name': 'PS2 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}}, 'fans': {'0': {'name': 'System Board Fan1A', 'physical_context': 'SystemBoard', 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'firmwares': {'installed-28897-6.10.30.20__usc.embedded.1:lc.embedded.1': {'name': 'Lifecycle Controller', 'description': 'Represents Firmware Inventory', 'release_date': '00:00:00Z', 'version': '6.10.30.20', 'updateable': True, 'status': {'health': 'OK', 'state': 'Enabled'}}}}}
+full_set = {'host01': {'host': 'host01', 'sn': 'FR8Y5X3', 'status': {'storage': {'1': {'disk.bay.8:enclosure.internal.0-1:nonraid.slot.2-1': {'description': 'Disk 8 in Backplane 1 of Storage Controller in Slot 2', 'entity': 'NonRAID.Slot.2-1', 'capacity_bytes': 20000588955136, 'model': 'ST20000NM008D-3D', 'protocol': 'SATA', 'serial_number': 'ZVT99QLL', 'status': {'health': 'OK', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 8, 'locationtype': 'Slot'}}}}}, 'processors': {'1': {'cpu.socket.2': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}, 'cpu.socket.1': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}}}, 'network': {'1': {'oslogicalnetwork.2': {'description': 'eno8303', 'name': 'eno8303', 'speed_mbps': 0, 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'memory': {'1': {'dimm.socket.a1': {'description': 'DIMM A1', 'memory_device_type': 'DDR4', 'capacity_mi_b': 16384, 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'power': {'1': {'0': {'name': 'PS1 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}, '1': {'name': 'PS2 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'fans': {'1': {'0': {'name': 'System Board Fan1A', 'physical_context': 'SystemBoard', 'status': {'health': 'OK', 'state': 'Enabled'}}}}}, 'firmwares': {'installed-28897-6.10.30.20__usc.embedded.1:lc.embedded.1': {'name': 'Lifecycle Controller', 'description': 'Represents Firmware Inventory', 'release_date': '00:00:00Z', 'version': '6.10.30.20', 'updateable': True, 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'host02': {'host': 'host02', 'sn': 'FR8Y5X4', 'status': {'storage': {'1': {'disk.bay.8:enclosure.internal.0-1:nonraid.slot.2-1': {'description': 'Disk 8 in Backplane 1 of Storage Controller in Slot 2', 'entity': 'NonRAID.Slot.2-1', 'capacity_bytes': 20000588955136, 'model': 'ST20000NM008D-3D', 'protocol': 'SATA', 'serial_number': 'ZVT99QLL', 'status': {'health': 'OK', 'healthrollup': 'OK', 'state': 'Enabled'}, 'physical_location': {'partlocation': {'locationordinalvalue': 8, 'locationtype': 'Slot'}}}}}, 'processors': {'1': {'cpu.socket.2': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}, 'cpu.socket.1': {'description': 'Represents the properties of a Processor attached to this System', 'total_cores': 16, 'total_threads': 32, 'processor_type': 'CPU', 'model': 'Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz', 'status': {'health': 'OK', 'state': 'Enabled'}, 'manufacturer': 'Intel'}}}, 'network': {'1': {'oslogicalnetwork.2': {'description': 'eno8303', 'name': 'eno8303', 'speed_mbps': 0, 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'memory': {'1': {'dimm.socket.a1': {'description': 'DIMM A1', 'memory_device_type': 'DDR4', 'capacity_mi_b': 16384, 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'power': {'1': {'0': {'name': 'PS1 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}, '1': {'name': 'PS2 Status', 'model': 'PWR SPLY,800W,RDNT,LTON', 'manufacturer': 'DELL', 'status': {'health': 'OK', 'state': 'Enabled'}}}}, 'fans': {'1': {'0': {'name': 'System Board Fan1A', 'physical_context': 'SystemBoard', 'status': {'health': 'OK', 'state': 'Enabled'}}}}}, 'firmwares': {'installed-28897-6.10.30.20__usc.embedded.1:lc.embedded.1': {'name': 'Lifecycle Controller', 'description': 'Represents Firmware Inventory', 'release_date': '00:00:00Z', 'version': '6.10.30.20', 'updateable': True, 'status': {'health': 'OK', 'state': 'Enabled'}}}}}
diff --git a/src/pybind/mgr/cephadm/tests/test_node_proxy.py b/src/pybind/mgr/cephadm/tests/test_node_proxy.py
index b19bb5dbc50..48c881dda95 100644
--- a/src/pybind/mgr/cephadm/tests/test_node_proxy.py
+++ b/src/pybind/mgr/cephadm/tests/test_node_proxy.py
@@ -109,12 +109,12 @@ class TestNodeProxyEndpoint(helper.CPWebCase):
calls = [call('HARDWARE_STORAGE',
count=2,
- detail=['disk.bay.0:enclosure.internal.0-1:raid.integrated.1-1 is critical: Enabled',
- 'disk.bay.9:enclosure.internal.0-1 is critical: Enabled'],
+ detail=['[1]: disk.bay.0:enclosure.internal.0-1:raid.integrated.1-1 is critical: Enabled',
+ '[1]: disk.bay.9:enclosure.internal.0-1 is critical: Enabled'],
summary='2 storage members are not ok'),
call('HARDWARE_MEMORY',
count=1,
- detail=['dimm.socket.a1 is critical: Enabled'],
+ detail=['[1]: dimm.socket.a1 is critical: Enabled'],
summary='1 memory member is not ok')]
assert TestNodeProxyEndpoint.mgr.set_health_warning.mock_calls == calls
diff --git a/src/pybind/mgr/orchestrator/module.py b/src/pybind/mgr/orchestrator/module.py
index 4c08ace4dbd..4969e1f5eb7 100644
--- a/src/pybind/mgr/orchestrator/module.py
+++ b/src/pybind/mgr/orchestrator/module.py
@@ -516,16 +516,16 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
:param hostname: hostname
"""
table_heading_mapping = {
- 'summary': ['HOST', 'STORAGE', 'CPU', 'NET', 'MEMORY', 'POWER', 'FANS'],
+ 'summary': ['HOST', 'SN', 'STORAGE', 'CPU', 'NET', 'MEMORY', 'POWER', 'FANS'],
'fullreport': [],
'firmwares': ['HOST', 'COMPONENT', 'NAME', 'DATE', 'VERSION', 'STATUS'],
'criticals': ['HOST', 'COMPONENT', 'NAME', 'STATUS', 'STATE'],
- 'memory': ['HOST', 'NAME', 'STATUS', 'STATE'],
- 'storage': ['HOST', 'NAME', 'MODEL', 'SIZE', 'PROTOCOL', 'SN', 'STATUS', 'STATE'],
- 'processors': ['HOST', 'NAME', 'MODEL', 'CORES', 'THREADS', 'STATUS', 'STATE'],
- 'network': ['HOST', 'NAME', 'SPEED', 'STATUS', 'STATE'],
- 'power': ['HOST', 'ID', 'NAME', 'MODEL', 'MANUFACTURER', 'STATUS', 'STATE'],
- 'fans': ['HOST', 'ID', 'NAME', 'STATUS', 'STATE']
+ 'memory': ['HOST', 'SYS_ID', 'NAME', 'STATUS', 'STATE'],
+ 'storage': ['HOST', 'SYS_ID', 'NAME', 'MODEL', 'SIZE', 'PROTOCOL', 'SN', 'STATUS', 'STATE'],
+ 'processors': ['HOST', 'SYS_ID', 'NAME', 'MODEL', 'CORES', 'THREADS', 'STATUS', 'STATE'],
+ 'network': ['HOST', 'SYS_ID', 'NAME', 'SPEED', 'STATUS', 'STATE'],
+ 'power': ['HOST', 'CHASSIS_ID', 'ID', 'NAME', 'MODEL', 'MANUFACTURER', 'STATUS', 'STATE'],
+ 'fans': ['HOST', 'CHASSIS_ID', 'ID', 'NAME', 'STATUS', 'STATE']
}
if category not in table_heading_mapping.keys():
@@ -542,21 +542,23 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
output = json.dumps(summary)
else:
for k, v in summary.items():
- row = [k]
- row.extend([v['status'][key] for key in ['storage', 'processors', 'network', 'memory', 'power', 'fans']])
+ row = [k, v['sn']]
+ row.extend([v['status'][key] for key in ['storage', 'processors',
+ 'network', 'memory',
+ 'power', 'fans']])
table.add_row(row)
output = table.get_string()
elif category == 'fullreport':
if hostname is None:
- output = "Missing host name"
+ output = 'Missing host name'
elif format != Format.json:
- output = "fullreport only supports json output"
+ output = 'fullreport only supports json output'
else:
completion = self.node_proxy_fullreport(hostname=hostname)
fullreport: Dict[str, Any] = raise_if_exception(completion)
output = json.dumps(fullreport)
elif category == 'firmwares':
- output = "Missing host name" if hostname is None else self._firmwares_table(hostname, table, format)
+ output = 'Missing host name' if hostname is None else self._firmwares_table(hostname, table, format)
elif category == 'criticals':
output = self._criticals_table(hostname, table, format)
else:
@@ -572,7 +574,11 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
return json.dumps(data)
for host, details in data.items():
for k, v in details.items():
- table.add_row((host, k, v['name'], v['release_date'], v['version'], v['status']['health']))
+ try:
+ status = v['status']['health']
+ except (KeyError, TypeError):
+ status = 'N/A'
+ table.add_row((host, k, v['name'], v['release_date'], v['version'], status))
return table.get_string()
def _criticals_table(self, hostname: Optional[str], table: PrettyTable, format: Format) -> str:
@@ -604,20 +610,21 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
}
fields = mapping.get(category, ())
- for host, details in data.items():
- for k, v in details.items():
- row = []
- for field in fields:
- if field in v:
- row.append(v[field])
- elif field in v.get('status', {}):
- row.append(v['status'][field])
+ for host in data.keys():
+ for sys_id, details in data[host].items():
+ for k, v in details.items():
+ row = []
+ for field in fields:
+ if field in v:
+ row.append(v[field])
+ elif field in v.get('status', {}):
+ row.append(v['status'][field])
+ else:
+ row.append('')
+ if category in ('power', 'fans', 'processors'):
+ table.add_row((host, sys_id,) + (k,) + tuple(row))
else:
- row.append('')
- if category in ('power', 'fans', 'processors'):
- table.add_row((host,) + (k,) + tuple(row))
- else:
- table.add_row((host,) + tuple(row))
+ table.add_row((host, sys_id,) + tuple(row))
return table.get_string()
@@ -643,7 +650,7 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
data = raise_if_exception(completion)
output: str = ''
if action == self.HardwareLightAction.get:
- status = 'on' if data["LocationIndicatorActive"] else 'off'
+ status = 'on' if data['LocationIndicatorActive'] else 'off'
if light_type == self.HardwareLightType.device:
output = f'ident LED for {device} on {hostname} is: {status}'
else: