diff options
-rw-r--r-- | Redfish.md | 8 | ||||
-rw-r--r-- | redfish-core/include/redfish.hpp | 2 | ||||
-rw-r--r-- | redfish-core/lib/fan.hpp | 159 | ||||
-rw-r--r-- | redfish-core/lib/thermal_subsystem.hpp | 3 |
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"; } |