19516f41fSGeorge Liu #pragma once 29516f41fSGeorge Liu 39516f41fSGeorge Liu #include "app.hpp" 49516f41fSGeorge Liu #include "dbus_utility.hpp" 59516f41fSGeorge Liu #include "error_messages.hpp" 6*539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 79516f41fSGeorge Liu #include "query.hpp" 89516f41fSGeorge Liu #include "registries/privilege_registry.hpp" 99516f41fSGeorge Liu #include "utils/chassis_utils.hpp" 109516f41fSGeorge Liu 119f1ae5aeSAlbert Zhang #include <boost/system/error_code.hpp> 129516f41fSGeorge Liu #include <boost/url/format.hpp> 139f1ae5aeSAlbert Zhang #include <sdbusplus/asio/property.hpp> 149516f41fSGeorge Liu #include <sdbusplus/message/types.hpp> 159516f41fSGeorge Liu 169516f41fSGeorge Liu #include <functional> 179516f41fSGeorge Liu #include <memory> 189516f41fSGeorge Liu #include <optional> 199516f41fSGeorge Liu #include <string> 209516f41fSGeorge Liu #include <string_view> 219516f41fSGeorge Liu 229516f41fSGeorge Liu namespace redfish 239516f41fSGeorge Liu { 249516f41fSGeorge Liu constexpr std::array<std::string_view, 1> fanInterface = { 259516f41fSGeorge Liu "xyz.openbmc_project.Inventory.Item.Fan"}; 269516f41fSGeorge Liu 279516f41fSGeorge Liu inline void 289516f41fSGeorge Liu updateFanList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 299516f41fSGeorge Liu const std::string& chassisId, 309516f41fSGeorge Liu const dbus::utility::MapperGetSubTreePathsResponse& fanPaths) 319516f41fSGeorge Liu { 329516f41fSGeorge Liu nlohmann::json& fanList = asyncResp->res.jsonValue["Members"]; 339516f41fSGeorge Liu for (const std::string& fanPath : fanPaths) 349516f41fSGeorge Liu { 359516f41fSGeorge Liu std::string fanName = 369516f41fSGeorge Liu sdbusplus::message::object_path(fanPath).filename(); 379516f41fSGeorge Liu if (fanName.empty()) 389516f41fSGeorge Liu { 399516f41fSGeorge Liu continue; 409516f41fSGeorge Liu } 419516f41fSGeorge Liu 429516f41fSGeorge Liu nlohmann::json item = nlohmann::json::object(); 439516f41fSGeorge Liu item["@odata.id"] = boost::urls::format( 449516f41fSGeorge Liu "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId, 459516f41fSGeorge Liu fanName); 469516f41fSGeorge Liu 479516f41fSGeorge Liu fanList.emplace_back(std::move(item)); 489516f41fSGeorge Liu } 499516f41fSGeorge Liu asyncResp->res.jsonValue["Members@odata.count"] = fanList.size(); 509516f41fSGeorge Liu } 519516f41fSGeorge Liu 529516f41fSGeorge Liu inline void getFanPaths( 539516f41fSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 54d547d8d2SEd Tanous const std::string& validChassisPath, 559516f41fSGeorge Liu const std::function<void(const dbus::utility::MapperGetSubTreePathsResponse& 569516f41fSGeorge Liu fanPaths)>& callback) 579516f41fSGeorge Liu { 58d547d8d2SEd Tanous sdbusplus::message::object_path endpointPath{validChassisPath}; 599516f41fSGeorge Liu endpointPath /= "cooled_by"; 609516f41fSGeorge Liu 619516f41fSGeorge Liu dbus::utility::getAssociatedSubTreePaths( 629516f41fSGeorge Liu endpointPath, 639516f41fSGeorge Liu sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 649516f41fSGeorge Liu fanInterface, 659516f41fSGeorge Liu [asyncResp, callback]( 669516f41fSGeorge Liu const boost::system::error_code& ec, 679516f41fSGeorge Liu const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) { 689516f41fSGeorge Liu if (ec) 699516f41fSGeorge Liu { 709516f41fSGeorge Liu if (ec.value() != EBADR) 719516f41fSGeorge Liu { 7262598e31SEd Tanous BMCWEB_LOG_ERROR( 7362598e31SEd Tanous "DBUS response error for getAssociatedSubTreePaths {}", 7462598e31SEd Tanous ec.value()); 759516f41fSGeorge Liu messages::internalError(asyncResp->res); 769516f41fSGeorge Liu } 779516f41fSGeorge Liu return; 789516f41fSGeorge Liu } 799516f41fSGeorge Liu callback(subtreePaths); 809516f41fSGeorge Liu }); 819516f41fSGeorge Liu } 829516f41fSGeorge Liu 839516f41fSGeorge Liu inline void doFanCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 849516f41fSGeorge Liu const std::string& chassisId, 859516f41fSGeorge Liu const std::optional<std::string>& validChassisPath) 869516f41fSGeorge Liu { 879516f41fSGeorge Liu if (!validChassisPath) 889516f41fSGeorge Liu { 899516f41fSGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 909516f41fSGeorge Liu return; 919516f41fSGeorge Liu } 929516f41fSGeorge Liu 939516f41fSGeorge Liu asyncResp->res.addHeader( 949516f41fSGeorge Liu boost::beast::http::field::link, 959516f41fSGeorge Liu "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby"); 969516f41fSGeorge Liu asyncResp->res.jsonValue["@odata.type"] = "#FanCollection.FanCollection"; 979516f41fSGeorge Liu asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 989516f41fSGeorge Liu "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans", chassisId); 999516f41fSGeorge Liu asyncResp->res.jsonValue["Name"] = "Fan Collection"; 1009516f41fSGeorge Liu asyncResp->res.jsonValue["Description"] = 1019516f41fSGeorge Liu "The collection of Fan resource instances " + chassisId; 1029516f41fSGeorge Liu asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 1039516f41fSGeorge Liu asyncResp->res.jsonValue["Members@odata.count"] = 0; 1049516f41fSGeorge Liu 105d547d8d2SEd Tanous getFanPaths(asyncResp, *validChassisPath, 1069516f41fSGeorge Liu std::bind_front(updateFanList, asyncResp, chassisId)); 1079516f41fSGeorge Liu } 1089516f41fSGeorge Liu 1099516f41fSGeorge Liu inline void 1109516f41fSGeorge Liu handleFanCollectionHead(App& app, const crow::Request& req, 1119516f41fSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1129516f41fSGeorge Liu const std::string& chassisId) 1139516f41fSGeorge Liu { 1149516f41fSGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1159516f41fSGeorge Liu { 1169516f41fSGeorge Liu return; 1179516f41fSGeorge Liu } 1189516f41fSGeorge Liu 1199516f41fSGeorge Liu redfish::chassis_utils::getValidChassisPath( 1209516f41fSGeorge Liu asyncResp, chassisId, 1219516f41fSGeorge Liu [asyncResp, 1229516f41fSGeorge Liu chassisId](const std::optional<std::string>& validChassisPath) { 1239516f41fSGeorge Liu if (!validChassisPath) 1249516f41fSGeorge Liu { 1259516f41fSGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 1269516f41fSGeorge Liu return; 1279516f41fSGeorge Liu } 1289516f41fSGeorge Liu asyncResp->res.addHeader( 1299516f41fSGeorge Liu boost::beast::http::field::link, 1309516f41fSGeorge Liu "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby"); 1319516f41fSGeorge Liu }); 1329516f41fSGeorge Liu } 1339516f41fSGeorge Liu 1349516f41fSGeorge Liu inline void 1359516f41fSGeorge Liu handleFanCollectionGet(App& app, const crow::Request& req, 1369516f41fSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1379516f41fSGeorge Liu const std::string& chassisId) 1389516f41fSGeorge Liu { 1399516f41fSGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1409516f41fSGeorge Liu { 1419516f41fSGeorge Liu return; 1429516f41fSGeorge Liu } 1439516f41fSGeorge Liu 1449516f41fSGeorge Liu redfish::chassis_utils::getValidChassisPath( 1459516f41fSGeorge Liu asyncResp, chassisId, 1469516f41fSGeorge Liu std::bind_front(doFanCollection, asyncResp, chassisId)); 1479516f41fSGeorge Liu } 1489516f41fSGeorge Liu 1499516f41fSGeorge Liu inline void requestRoutesFanCollection(App& app) 1509516f41fSGeorge Liu { 1519516f41fSGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/") 1529516f41fSGeorge Liu .privileges(redfish::privileges::headFanCollection) 1539516f41fSGeorge Liu .methods(boost::beast::http::verb::head)( 1549516f41fSGeorge Liu std::bind_front(handleFanCollectionHead, std::ref(app))); 1559516f41fSGeorge Liu 1569516f41fSGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/") 1579516f41fSGeorge Liu .privileges(redfish::privileges::getFanCollection) 1589516f41fSGeorge Liu .methods(boost::beast::http::verb::get)( 1599516f41fSGeorge Liu std::bind_front(handleFanCollectionGet, std::ref(app))); 1609516f41fSGeorge Liu } 1619516f41fSGeorge Liu 162e4e54232SGeorge Liu inline bool checkFanId(const std::string& fanPath, const std::string& fanId) 163e4e54232SGeorge Liu { 164e4e54232SGeorge Liu std::string fanName = sdbusplus::message::object_path(fanPath).filename(); 165e4e54232SGeorge Liu 166e4e54232SGeorge Liu return !(fanName.empty() || fanName != fanId); 167e4e54232SGeorge Liu } 168e4e54232SGeorge Liu 169e4e54232SGeorge Liu static inline void handleFanPath( 170e4e54232SGeorge Liu const std::string& fanId, 171e4e54232SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 172e4e54232SGeorge Liu const dbus::utility::MapperGetSubTreePathsResponse& fanPaths, 173e4e54232SGeorge Liu const std::function<void(const std::string& fanPath, 174e4e54232SGeorge Liu const std::string& service)>& callback) 175e4e54232SGeorge Liu { 176e4e54232SGeorge Liu for (const auto& fanPath : fanPaths) 177e4e54232SGeorge Liu { 178e4e54232SGeorge Liu if (!checkFanId(fanPath, fanId)) 179e4e54232SGeorge Liu { 180e4e54232SGeorge Liu continue; 181e4e54232SGeorge Liu } 182e4e54232SGeorge Liu dbus::utility::getDbusObject( 183e4e54232SGeorge Liu fanPath, fanInterface, 184e4e54232SGeorge Liu [fanPath, asyncResp, 185e4e54232SGeorge Liu callback](const boost::system::error_code& ec, 186e4e54232SGeorge Liu const dbus::utility::MapperGetObject& object) { 187e4e54232SGeorge Liu if (ec || object.empty()) 188e4e54232SGeorge Liu { 18962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error on getDbusObject {}", 19062598e31SEd Tanous ec.value()); 191e4e54232SGeorge Liu messages::internalError(asyncResp->res); 192e4e54232SGeorge Liu return; 193e4e54232SGeorge Liu } 194e4e54232SGeorge Liu callback(fanPath, object.begin()->first); 195e4e54232SGeorge Liu }); 196e4e54232SGeorge Liu 197e4e54232SGeorge Liu return; 198e4e54232SGeorge Liu } 19962598e31SEd Tanous BMCWEB_LOG_WARNING("Fan not found {}", fanId); 200e4e54232SGeorge Liu messages::resourceNotFound(asyncResp->res, "Fan", fanId); 201e4e54232SGeorge Liu } 202e4e54232SGeorge Liu 203e4e54232SGeorge Liu inline void getValidFanPath( 204e4e54232SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 205e4e54232SGeorge Liu const std::string& validChassisPath, const std::string& fanId, 206e4e54232SGeorge Liu const std::function<void(const std::string& fanPath, 207e4e54232SGeorge Liu const std::string& service)>& callback) 208e4e54232SGeorge Liu { 209e4e54232SGeorge Liu getFanPaths( 210e4e54232SGeorge Liu asyncResp, validChassisPath, 211e4e54232SGeorge Liu [fanId, asyncResp, callback]( 212e4e54232SGeorge Liu const dbus::utility::MapperGetSubTreePathsResponse& fanPaths) { 213e4e54232SGeorge Liu handleFanPath(fanId, asyncResp, fanPaths, callback); 214e4e54232SGeorge Liu }); 215e4e54232SGeorge Liu } 216e4e54232SGeorge Liu 217e4e54232SGeorge Liu inline void addFanCommonProperties(crow::Response& resp, 218e4e54232SGeorge Liu const std::string& chassisId, 219e4e54232SGeorge Liu const std::string& fanId) 220e4e54232SGeorge Liu { 221e4e54232SGeorge Liu resp.addHeader(boost::beast::http::field::link, 222e4e54232SGeorge Liu "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby"); 223e4e54232SGeorge Liu resp.jsonValue["@odata.type"] = "#Fan.v1_3_0.Fan"; 224e4e54232SGeorge Liu resp.jsonValue["Name"] = "Fan"; 225e4e54232SGeorge Liu resp.jsonValue["Id"] = fanId; 226e4e54232SGeorge Liu resp.jsonValue["@odata.id"] = boost::urls::format( 227e4e54232SGeorge Liu "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId, fanId); 228*539d8c6bSEd Tanous resp.jsonValue["Status"]["State"] = resource::State::Enabled; 229*539d8c6bSEd Tanous resp.jsonValue["Status"]["Health"] = resource::Health::OK; 2309f1ae5aeSAlbert Zhang } 2319f1ae5aeSAlbert Zhang 2329f1ae5aeSAlbert Zhang inline void getFanHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2339f1ae5aeSAlbert Zhang const std::string& fanPath, const std::string& service) 2349f1ae5aeSAlbert Zhang { 2359f1ae5aeSAlbert Zhang sdbusplus::asio::getProperty<bool>( 2369f1ae5aeSAlbert Zhang *crow::connections::systemBus, service, fanPath, 2379f1ae5aeSAlbert Zhang "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional", 2389f1ae5aeSAlbert Zhang [asyncResp](const boost::system::error_code& ec, const bool value) { 2399f1ae5aeSAlbert Zhang if (ec) 2409f1ae5aeSAlbert Zhang { 2419f1ae5aeSAlbert Zhang if (ec.value() != EBADR) 2429f1ae5aeSAlbert Zhang { 24362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Health {}", 24462598e31SEd Tanous ec.value()); 2459f1ae5aeSAlbert Zhang messages::internalError(asyncResp->res); 2469f1ae5aeSAlbert Zhang } 2479f1ae5aeSAlbert Zhang return; 2489f1ae5aeSAlbert Zhang } 2499f1ae5aeSAlbert Zhang 2509f1ae5aeSAlbert Zhang if (!value) 2519f1ae5aeSAlbert Zhang { 252*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 253*539d8c6bSEd Tanous resource::Health::Critical; 2549f1ae5aeSAlbert Zhang } 2559f1ae5aeSAlbert Zhang }); 2569f1ae5aeSAlbert Zhang } 2579f1ae5aeSAlbert Zhang 2589f1ae5aeSAlbert Zhang inline void getFanState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2599f1ae5aeSAlbert Zhang const std::string& fanPath, const std::string& service) 2609f1ae5aeSAlbert Zhang { 2619f1ae5aeSAlbert Zhang sdbusplus::asio::getProperty<bool>( 2629f1ae5aeSAlbert Zhang *crow::connections::systemBus, service, fanPath, 2639f1ae5aeSAlbert Zhang "xyz.openbmc_project.Inventory.Item", "Present", 2649f1ae5aeSAlbert Zhang [asyncResp](const boost::system::error_code& ec, const bool value) { 2659f1ae5aeSAlbert Zhang if (ec) 2669f1ae5aeSAlbert Zhang { 2679f1ae5aeSAlbert Zhang if (ec.value() != EBADR) 2689f1ae5aeSAlbert Zhang { 26962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for State {}", 27062598e31SEd Tanous ec.value()); 2719f1ae5aeSAlbert Zhang messages::internalError(asyncResp->res); 2729f1ae5aeSAlbert Zhang } 2739f1ae5aeSAlbert Zhang return; 2749f1ae5aeSAlbert Zhang } 2759f1ae5aeSAlbert Zhang 2769f1ae5aeSAlbert Zhang if (!value) 2779f1ae5aeSAlbert Zhang { 278*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 279*539d8c6bSEd Tanous resource::State::Absent; 2809f1ae5aeSAlbert Zhang } 2819f1ae5aeSAlbert Zhang }); 282e4e54232SGeorge Liu } 283e4e54232SGeorge Liu 284090ae7baSGeorge Liu inline void getFanAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 285090ae7baSGeorge Liu const std::string& fanPath, const std::string& service) 286090ae7baSGeorge Liu { 287090ae7baSGeorge Liu sdbusplus::asio::getAllProperties( 288090ae7baSGeorge Liu *crow::connections::systemBus, service, fanPath, 289090ae7baSGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 290090ae7baSGeorge Liu [fanPath, asyncResp{asyncResp}]( 291090ae7baSGeorge Liu const boost::system::error_code& ec, 292090ae7baSGeorge Liu const dbus::utility::DBusPropertiesMap& assetList) { 293090ae7baSGeorge Liu if (ec) 294090ae7baSGeorge Liu { 295090ae7baSGeorge Liu if (ec.value() != EBADR) 296090ae7baSGeorge Liu { 29762598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Properties{}", 29862598e31SEd Tanous ec.value()); 299090ae7baSGeorge Liu messages::internalError(asyncResp->res); 300090ae7baSGeorge Liu } 301090ae7baSGeorge Liu return; 302090ae7baSGeorge Liu } 303090ae7baSGeorge Liu const std::string* manufacturer = nullptr; 304090ae7baSGeorge Liu const std::string* model = nullptr; 305090ae7baSGeorge Liu const std::string* partNumber = nullptr; 306090ae7baSGeorge Liu const std::string* serialNumber = nullptr; 307090ae7baSGeorge Liu const std::string* sparePartNumber = nullptr; 308090ae7baSGeorge Liu 309090ae7baSGeorge Liu const bool success = sdbusplus::unpackPropertiesNoThrow( 310090ae7baSGeorge Liu dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer", 311090ae7baSGeorge Liu manufacturer, "Model", model, "PartNumber", partNumber, 312090ae7baSGeorge Liu "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber); 313090ae7baSGeorge Liu if (!success) 314090ae7baSGeorge Liu { 315090ae7baSGeorge Liu messages::internalError(asyncResp->res); 316090ae7baSGeorge Liu return; 317090ae7baSGeorge Liu } 318090ae7baSGeorge Liu if (manufacturer != nullptr) 319090ae7baSGeorge Liu { 320090ae7baSGeorge Liu asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 321090ae7baSGeorge Liu } 322090ae7baSGeorge Liu if (model != nullptr) 323090ae7baSGeorge Liu { 324090ae7baSGeorge Liu asyncResp->res.jsonValue["Model"] = *model; 325090ae7baSGeorge Liu } 326090ae7baSGeorge Liu if (partNumber != nullptr) 327090ae7baSGeorge Liu { 328090ae7baSGeorge Liu asyncResp->res.jsonValue["PartNumber"] = *partNumber; 329090ae7baSGeorge Liu } 330090ae7baSGeorge Liu if (serialNumber != nullptr) 331090ae7baSGeorge Liu { 332090ae7baSGeorge Liu asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 333090ae7baSGeorge Liu } 334090ae7baSGeorge Liu if (sparePartNumber != nullptr && !sparePartNumber->empty()) 335090ae7baSGeorge Liu { 336090ae7baSGeorge Liu asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 337090ae7baSGeorge Liu } 338090ae7baSGeorge Liu }); 339090ae7baSGeorge Liu } 340090ae7baSGeorge Liu 341fc3edfddSEd Tanous inline void getFanLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3424a2e485dSGeorge Liu const std::string& fanPath, 3434a2e485dSGeorge Liu const std::string& service) 3444a2e485dSGeorge Liu { 3454a2e485dSGeorge Liu sdbusplus::asio::getProperty<std::string>( 3464a2e485dSGeorge Liu *crow::connections::systemBus, service, fanPath, 3474a2e485dSGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 348fc3edfddSEd Tanous [asyncResp](const boost::system::error_code& ec, 3494a2e485dSGeorge Liu const std::string& property) { 3504a2e485dSGeorge Liu if (ec) 3514a2e485dSGeorge Liu { 3524a2e485dSGeorge Liu if (ec.value() != EBADR) 3534a2e485dSGeorge Liu { 35462598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Location{}", 35562598e31SEd Tanous ec.value()); 356fc3edfddSEd Tanous messages::internalError(asyncResp->res); 3574a2e485dSGeorge Liu } 3584a2e485dSGeorge Liu return; 3594a2e485dSGeorge Liu } 360fc3edfddSEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 3614a2e485dSGeorge Liu property; 3624a2e485dSGeorge Liu }); 3634a2e485dSGeorge Liu } 3644a2e485dSGeorge Liu 365e4e54232SGeorge Liu inline void 366e4e54232SGeorge Liu afterGetValidFanPath(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 367e4e54232SGeorge Liu const std::string& chassisId, const std::string& fanId, 368e4e54232SGeorge Liu const std::string& fanPath, const std::string& service) 369e4e54232SGeorge Liu { 370e4e54232SGeorge Liu addFanCommonProperties(asyncResp->res, chassisId, fanId); 3719f1ae5aeSAlbert Zhang getFanState(asyncResp, fanPath, service); 3729f1ae5aeSAlbert Zhang getFanHealth(asyncResp, fanPath, service); 373090ae7baSGeorge Liu getFanAsset(asyncResp, fanPath, service); 3744a2e485dSGeorge Liu getFanLocation(asyncResp, fanPath, service); 375e4e54232SGeorge Liu } 376e4e54232SGeorge Liu 377e4e54232SGeorge Liu inline void doFanGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 378e4e54232SGeorge Liu const std::string& chassisId, const std::string& fanId, 379e4e54232SGeorge Liu const std::optional<std::string>& validChassisPath) 380e4e54232SGeorge Liu { 381e4e54232SGeorge Liu if (!validChassisPath) 382e4e54232SGeorge Liu { 383e4e54232SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 384e4e54232SGeorge Liu return; 385e4e54232SGeorge Liu } 386e4e54232SGeorge Liu 387e4e54232SGeorge Liu getValidFanPath( 388e4e54232SGeorge Liu asyncResp, *validChassisPath, fanId, 389e4e54232SGeorge Liu std::bind_front(afterGetValidFanPath, asyncResp, chassisId, fanId)); 390e4e54232SGeorge Liu } 391e4e54232SGeorge Liu 392e4e54232SGeorge Liu inline void handleFanHead(App& app, const crow::Request& req, 393e4e54232SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 394e4e54232SGeorge Liu const std::string& chassisId, 395e4e54232SGeorge Liu const std::string& fanId) 396e4e54232SGeorge Liu { 397e4e54232SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 398e4e54232SGeorge Liu { 399e4e54232SGeorge Liu return; 400e4e54232SGeorge Liu } 401e4e54232SGeorge Liu 402e4e54232SGeorge Liu redfish::chassis_utils::getValidChassisPath( 403e4e54232SGeorge Liu asyncResp, chassisId, 404e4e54232SGeorge Liu [asyncResp, chassisId, 405e4e54232SGeorge Liu fanId](const std::optional<std::string>& validChassisPath) { 406e4e54232SGeorge Liu if (!validChassisPath) 407e4e54232SGeorge Liu { 408e4e54232SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 409e4e54232SGeorge Liu return; 410e4e54232SGeorge Liu } 411e4e54232SGeorge Liu getValidFanPath(asyncResp, *validChassisPath, fanId, 412e4e54232SGeorge Liu [asyncResp](const std::string&, const std::string&) { 413e4e54232SGeorge Liu asyncResp->res.addHeader( 414e4e54232SGeorge Liu boost::beast::http::field::link, 415e4e54232SGeorge Liu "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby"); 416e4e54232SGeorge Liu }); 417e4e54232SGeorge Liu }); 418e4e54232SGeorge Liu } 419e4e54232SGeorge Liu 420e4e54232SGeorge Liu inline void handleFanGet(App& app, const crow::Request& req, 421e4e54232SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 422e4e54232SGeorge Liu const std::string& chassisId, const std::string& fanId) 423e4e54232SGeorge Liu { 424e4e54232SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 425e4e54232SGeorge Liu { 426e4e54232SGeorge Liu return; 427e4e54232SGeorge Liu } 428e4e54232SGeorge Liu 429e4e54232SGeorge Liu redfish::chassis_utils::getValidChassisPath( 430e4e54232SGeorge Liu asyncResp, chassisId, 431e4e54232SGeorge Liu std::bind_front(doFanGet, asyncResp, chassisId, fanId)); 432e4e54232SGeorge Liu } 433e4e54232SGeorge Liu 434e4e54232SGeorge Liu inline void requestRoutesFan(App& app) 435e4e54232SGeorge Liu { 436e4e54232SGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/") 437e4e54232SGeorge Liu .privileges(redfish::privileges::headFan) 438e4e54232SGeorge Liu .methods(boost::beast::http::verb::head)( 439e4e54232SGeorge Liu std::bind_front(handleFanHead, std::ref(app))); 440e4e54232SGeorge Liu 441e4e54232SGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/") 442e4e54232SGeorge Liu .privileges(redfish::privileges::getFan) 443e4e54232SGeorge Liu .methods(boost::beast::http::verb::get)( 444e4e54232SGeorge Liu std::bind_front(handleFanGet, std::ref(app))); 445e4e54232SGeorge Liu } 446e4e54232SGeorge Liu 4479516f41fSGeorge Liu } // namespace redfish 448