diff --git a/prometheus_hardware_exporter/collectors/redfish.py b/prometheus_hardware_exporter/collectors/redfish.py index 16146d0..f4eb5d1 100644 --- a/prometheus_hardware_exporter/collectors/redfish.py +++ b/prometheus_hardware_exporter/collectors/redfish.py @@ -221,7 +221,29 @@ def _storage_root_uri(cls, system_id: str, storage_name: str) -> str: system_id: "S1" storage_name" "Storage" """ - return cls.systems_root_uri + f"{system_id}/{storage_name}/" + return cls.systems_root_uri + f"{system_id}/{storage_name}" + + def _find_storage_controller_data(self, storage_controllers: Dict) -> List[Dict]: + """Return storage controller list. + + Returns: + storage_controller_list: list of storage controllers for + requested storage id. + + """ + if "StorageControllers" in storage_controllers: + storage_controllers_list: List[Dict] = storage_controllers.get("StorageControllers") + elif "Controllers" in storage_controllers: + storage_controllers_list: List[Dict] = [] + controller_list = storage_controllers.get("Controllers") + for controller in controller_list.values(): + all_controller_data = self.redfish_obj.get(controller).dict + for controller in all_controller_data["Members"]: + storage_controllers_list.append(self.redfish_obj.get(controller["@odata.id"]).dict) + else: + raise KeyError("Couldn't fetch storage controller data") + + return storage_controllers_list def get_storage_controller_data(self) -> Tuple[Dict[str, int], Dict[str, List]]: """Return storage controller data and count. @@ -287,21 +309,22 @@ def get_storage_controller_data(self) -> Tuple[Dict[str, int], Dict[str, List]]: for storage_id in storage_ids: # eg: /redfish/v1/Systems/1/Storage/XYZ123 curr_storage_uri = ( - RedfishHelper._storage_root_uri(system_id, storage_name) + storage_id + RedfishHelper._storage_root_uri(system_id, storage_name) + "/" + storage_id ) # list of storage controllers for that storage id - storage_controllers_list: List[Dict] = self.redfish_obj.get(curr_storage_uri).dict[ - "StorageControllers" - ] + storage_controllers_list: List[Dict] = self._find_storage_controller_data( + self.redfish_obj.get(curr_storage_uri).dict + ) storage_controller_count[system_id] += len(storage_controllers_list) # picking out the required data from each storage controller in the list for data in storage_controllers_list: + print(data) storage_controller_data_in_curr_system.append( { "storage_id": storage_id, - "controller_id": data["MemberId"], + "controller_id": data["MemberId"] if data.get("MemberId", None) else data.get("Id"), "state": data["Status"]["State"], "health": data["Status"]["Health"] or "NA", } @@ -455,7 +478,7 @@ def get_storage_drive_data(self) -> Tuple[Dict[str, int], Dict[str, List]]: for storage_id in storage_ids: # eg: /redfish/v1/Systems/1/Storage/XYZ123/ curr_storage_uri = ( - RedfishHelper._storage_root_uri(system_id, storage_name) + storage_id + RedfishHelper._storage_root_uri(system_id, storage_name) + "/" + storage_id ) # list of storage drives for that storage id diff --git a/tests/unit/test_redfish.py b/tests/unit/test_redfish.py index d73f9a6..e835686 100644 --- a/tests/unit/test_redfish.py +++ b/tests/unit/test_redfish.py @@ -474,7 +474,7 @@ def mock_get_response(uri): def test__storage_root_uri(self): """Test RedfishHelper._storage_root_uri method.""" for storage_name in ["Storage", "Storages", "TestStorage"]: - expected_uri = f"/redfish/v1/Systems/S1/{storage_name}/" + expected_uri = f"/redfish/v1/Systems/S1/{storage_name}" uri = RedfishHelper._storage_root_uri("S1", storage_name) assert uri == expected_uri @@ -485,7 +485,7 @@ def test__storage_root_uri(self): @patch( "prometheus_hardware_exporter.collectors.redfish.redfish_utilities.systems.get_system_ids" ) - def test_get_storage_controller_data_success( + def test_get_storage_controller_data_success_with_storagecontrollers( self, mock_get_system_ids, mock_get_collection_ids, mock_redfish_client ): mock_redfish_obj = Mock() @@ -550,6 +550,105 @@ def mock_get_response(uri): }, ) + @patch("prometheus_hardware_exporter.collectors.redfish.redfish_client") + @patch( + "prometheus_hardware_exporter.collectors.redfish.redfish_utilities.collections.get_collection_ids" # noqa: E501 + ) + @patch( + "prometheus_hardware_exporter.collectors.redfish.redfish_utilities.systems.get_system_ids" + ) + + def test_get_storage_controller_data_success_with_controllers( + self, mock_get_system_ids, mock_get_collection_ids, mock_redfish_client + ): + mock_redfish_obj = Mock() + mock_system_ids = ["s1"] + mock_storage_ids = ["STOR1", "STOR2"] + + mock_get_system_ids.return_value = mock_system_ids + mock_redfish_client.return_value = mock_redfish_obj + mock_get_collection_ids.return_value = mock_storage_ids + + def mock_get_response(uri): + response = Mock() + if uri.endswith("Systems/s1/Storage/STOR1"): + response.dict = { + "Controllers": { + "@odata.id": "/redfish/v1/Systems/s1/Storage/STOR1/Controllers" + } + } + elif uri.endswith("Systems/s1/Storage/STOR2"): + response.dict = { + "Controllers": { + "@odata.id": "/redfish/v1/Systems/s1/Storage/STOR2/Controllers" + } + } + elif uri.endswith("Systems/s1/Storage/STOR1/Controllers"): + response.dict = { + "Members": [ + { + "@odata.id": "/redfish/v1/Systems/s1/Storage/STOR1/Controllers/sc0" + } + ] + } + elif uri.endswith("Systems/s1/Storage/STOR2/Controllers"): + response.dict = { + "Members": [ + { + "@odata.id": "/redfish/v1/Systems/s1/Storage/STOR2/Controllers/sc1" + } + ] + } + elif uri.endswith("Systems/s1/Storage/STOR1/Controllers/sc0"): + response.dict = { + "Status": { + "State": "Enabled", + "Health": "OK", + }, + "Id": "sc0" + } + elif uri.endswith("Systems/s1/Storage/STOR2/Controllers/sc1"): + response.dict = { + "Status": { + "State": "Enabled", + "Health": "OK", + }, + "Id": "sc1" + } + # response for GET request to /redfish/v1/Systems// + elif "Systems" in uri: + response.dict = {"Storage": {"@odata.id": "/redfish/v1/Systems/sX/Storage"}} + return response + + mock_redfish_obj.get.side_effect = mock_get_response + + with RedfishHelper(Mock()) as helper: + ( + storage_controller_count, + storage_controller_data, + ) = helper.get_storage_controller_data() + + self.assertEqual(storage_controller_count, {"s1": 2}) + self.assertEqual( + storage_controller_data, + { + "s1": [ + { + "storage_id": "STOR1", + "controller_id": "sc0", + "health": "OK", + "state": "Enabled", + }, + { + "storage_id": "STOR2", + "controller_id": "sc1", + "health": "OK", + "state": "Enabled", + }, + ] + } + ) + @patch("prometheus_hardware_exporter.collectors.redfish.redfish_client") @patch( "prometheus_hardware_exporter.collectors.redfish.redfish_utilities.collections.get_collection_ids" # noqa: E501