summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Liu <liuxiwei@inspur.com>2022-09-29 12:21:41 +0300
committerGunnar Mills <gmills@us.ibm.com>2023-07-13 06:01:21 +0300
commit9516f41f9295170ad5d59ded36584d22776417d5 (patch)
tree6e7289ba637b4c9e4be8bd13d436aea0eb63faa1
parent2c6ffdb08b2207ff7c31041f77cc3755508d45c4 (diff)
downloadbmcweb-9516f41f9295170ad5d59ded36584d22776417d5.tar.xz
Implements FanCollection schema
The FanCollection schema is a resource in Redifsh version 2022.2 [1] that represents the management properties for the monitoring and management of cooling fans implemented by Redfish [2]. This commit retrieves the fan collection by obtaining the endpoints of the `cooled_by` association. The `cooled_by` association represents the relationship between a chassis and the fans responsible for providing cooling to the chassis. ref: [1] https://www.dmtf.org/sites/default/files/standards/documents/DSP0268_2022.2.pdf [2] http://redfish.dmtf.org/schemas/v1/Fan.v1_3_0.json Redfish validator is currently failing. In order for the validator to pass, it is necessary to merge this commit with https://gerrit.openbmc.org/c/openbmc/bmcweb/+/57559 Tested: 1. doGet method to get FanCollection ``` curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans", "@odata.type": "#FanCollection.FanCollection", "Description": "The collection of Fan resource instances chassis", "Members": [ { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans/fan5" }, { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans/fan4" }, { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans/fan3" }, { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans/fan2" }, { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans/fan1" }, { "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/Fans/fan0" } ], "Members@odata.count": 6, "Name": "Fan Collection" } 2. Input the wrong chassisId with the doGet method curl -k https://${bmc}/redfish/v1/Chassis/chassis11/ThermalSubsystem/Fans { "error": { "@Message.ExtendedInfo": [ { "@odata.type": "#Message.v1_1_1.Message", "Message": "The requested resource of type Chassis named 'chassis11' was not found.", "MessageArgs": [ "Chassis", "chassis11" ], "MessageId": "Base.1.13.0.ResourceNotFound", "MessageSeverity": "Critical", "Resolution": "Provide a valid resource identifier and resubmit the request." } ], "code": "Base.1.13.0.ResourceNotFound", "message": "The requested resource of type Chassis named 'chassis11' was not found." } } ``` Signed-off-by: George Liu <liuxiwei@inspur.com> Change-Id: If5e9ff5655f444694c7ca1aea95d45e2c9222625 Signed-off-by: Lakshmi Yadlapati <lakshmiy@us.ibm.com>
-rw-r--r--Redfish.md8
-rw-r--r--redfish-core/include/redfish.hpp2
-rw-r--r--redfish-core/lib/fan.hpp159
-rw-r--r--redfish-core/lib/thermal_subsystem.hpp3
4 files changed, 172 insertions, 0 deletions
diff --git a/Redfish.md b/Redfish.md
index f2fb141916..4607589af2 100644
--- a/Redfish.md
+++ b/Redfish.md
@@ -312,6 +312,14 @@ Fields common to all schemas
- Status
+#### /redfish/v1/Chassis/{ChassisId}/ThermalSubsystem/Fans
+
+##### FansCollection
+
+- Description
+- Members
+- Members@odata.count
+
### /redfish/v1/Chassis/{ChassisId}/Power#/PowerControl/{ControlName}/
#### PowerControl
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index e97a83286f..dc8dc81b58 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -26,6 +26,7 @@
#include "event_service.hpp"
#include "eventservice_sse.hpp"
#include "fabric_adapters.hpp"
+#include "fan.hpp"
#include "hypervisor_system.hpp"
#include "log_services.hpp"
#include "manager_diagnostic_data.hpp"
@@ -95,6 +96,7 @@ class RedfishService
requestRoutesPowerSupply(app);
requestRoutesPowerSupplyCollection(app);
requestRoutesThermalSubsystem(app);
+ requestRoutesFanCollection(app);
#endif
requestRoutesManagerCollection(app);
requestRoutesManager(app);
diff --git a/redfish-core/lib/fan.hpp b/redfish-core/lib/fan.hpp
new file mode 100644
index 0000000000..3a9572ffcd
--- /dev/null
+++ b/redfish-core/lib/fan.hpp
@@ -0,0 +1,159 @@
+#pragma once
+
+#include "app.hpp"
+#include "dbus_utility.hpp"
+#include "error_messages.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/chassis_utils.hpp"
+
+#include <boost/url/format.hpp>
+#include <sdbusplus/message/types.hpp>
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+
+namespace redfish
+{
+constexpr std::array<std::string_view, 1> fanInterface = {
+ "xyz.openbmc_project.Inventory.Item.Fan"};
+
+inline void
+ updateFanList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId,
+ const dbus::utility::MapperGetSubTreePathsResponse& fanPaths)
+{
+ nlohmann::json& fanList = asyncResp->res.jsonValue["Members"];
+ for (const std::string& fanPath : fanPaths)
+ {
+ std::string fanName =
+ sdbusplus::message::object_path(fanPath).filename();
+ if (fanName.empty())
+ {
+ continue;
+ }
+
+ nlohmann::json item = nlohmann::json::object();
+ item["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId,
+ fanName);
+
+ fanList.emplace_back(std::move(item));
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = fanList.size();
+}
+
+inline void getFanPaths(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::optional<std::string>& validChassisPath,
+ const std::function<void(const dbus::utility::MapperGetSubTreePathsResponse&
+ fanPaths)>& callback)
+{
+ sdbusplus::message::object_path endpointPath{*validChassisPath};
+ endpointPath /= "cooled_by";
+
+ dbus::utility::getAssociatedSubTreePaths(
+ endpointPath,
+ sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
+ fanInterface,
+ [asyncResp, callback](
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
+ if (ec)
+ {
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR
+ << "DBUS response error for getAssociatedSubTreePaths "
+ << ec.value();
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+ callback(subtreePaths);
+ });
+}
+
+inline void doFanCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId,
+ const std::optional<std::string>& validChassisPath)
+{
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+ return;
+ }
+
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby");
+ asyncResp->res.jsonValue["@odata.type"] = "#FanCollection.FanCollection";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans", chassisId);
+ asyncResp->res.jsonValue["Name"] = "Fan Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "The collection of Fan resource instances " + chassisId;
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ getFanPaths(asyncResp, validChassisPath,
+ std::bind_front(updateFanList, asyncResp, chassisId));
+}
+
+inline void
+ handleFanCollectionHead(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ redfish::chassis_utils::getValidChassisPath(
+ asyncResp, chassisId,
+ [asyncResp,
+ chassisId](const std::optional<std::string>& validChassisPath) {
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+ return;
+ }
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby");
+ });
+}
+
+inline void
+ handleFanCollectionGet(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ redfish::chassis_utils::getValidChassisPath(
+ asyncResp, chassisId,
+ std::bind_front(doFanCollection, asyncResp, chassisId));
+}
+
+inline void requestRoutesFanCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/")
+ .privileges(redfish::privileges::headFanCollection)
+ .methods(boost::beast::http::verb::head)(
+ std::bind_front(handleFanCollectionHead, std::ref(app)));
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/")
+ .privileges(redfish::privileges::getFanCollection)
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(handleFanCollectionGet, std::ref(app)));
+}
+
+} // namespace redfish
diff --git a/redfish-core/lib/thermal_subsystem.hpp b/redfish-core/lib/thermal_subsystem.hpp
index 6528a55fc6..804b849ea0 100644
--- a/redfish-core/lib/thermal_subsystem.hpp
+++ b/redfish-core/lib/thermal_subsystem.hpp
@@ -38,6 +38,9 @@ inline void doThermalSubsystemCollection(
asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
"/redfish/v1/Chassis/{}/ThermalSubsystem", chassisId);
+ asyncResp->res.jsonValue["Fans"]["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans", chassisId);
+
asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
asyncResp->res.jsonValue["Status"]["Health"] = "OK";
}