1a7210020SGeorge Liu #pragma once 2a7210020SGeorge Liu 3a7210020SGeorge Liu #include "app.hpp" 4a7210020SGeorge Liu #include "dbus_utility.hpp" 5a7210020SGeorge Liu #include "query.hpp" 6a7210020SGeorge Liu #include "registries/privilege_registry.hpp" 7a7210020SGeorge Liu #include "utils/chassis_utils.hpp" 82b45fb3bSGeorge Liu #include "utils/dbus_utils.hpp" 92b45fb3bSGeorge Liu #include "utils/json_utils.hpp" 10a7210020SGeorge Liu 1134dfcb94SGeorge Liu #include <boost/system/error_code.hpp> 12ef4c65b7SEd Tanous #include <boost/url/format.hpp> 13ef4c65b7SEd Tanous 14a7210020SGeorge Liu #include <memory> 15a7210020SGeorge Liu #include <optional> 16a7210020SGeorge Liu #include <string> 17a7210020SGeorge Liu 18a7210020SGeorge Liu namespace redfish 19a7210020SGeorge Liu { 20a7210020SGeorge Liu 21*788fe6cfSLakshmi Yadlapati static constexpr std::array<std::string_view, 1> powerSupplyInterface = { 22*788fe6cfSLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 23*788fe6cfSLakshmi Yadlapati 24*788fe6cfSLakshmi Yadlapati inline void updatePowerSupplyList( 25*788fe6cfSLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2600ef5dc6SGeorge Liu const std::string& chassisId, 27*788fe6cfSLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& powerSupplyPaths) 28*788fe6cfSLakshmi Yadlapati { 29*788fe6cfSLakshmi Yadlapati nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"]; 30*788fe6cfSLakshmi Yadlapati for (const std::string& powerSupplyPath : powerSupplyPaths) 31a7210020SGeorge Liu { 3200ef5dc6SGeorge Liu std::string powerSupplyName = 3300ef5dc6SGeorge Liu sdbusplus::message::object_path(powerSupplyPath).filename(); 3400ef5dc6SGeorge Liu if (powerSupplyName.empty()) 3500ef5dc6SGeorge Liu { 36*788fe6cfSLakshmi Yadlapati continue; 3700ef5dc6SGeorge Liu } 3800ef5dc6SGeorge Liu 3900ef5dc6SGeorge Liu nlohmann::json item = nlohmann::json::object(); 4000ef5dc6SGeorge Liu item["@odata.id"] = boost::urls::format( 4100ef5dc6SGeorge Liu "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId, 4200ef5dc6SGeorge Liu powerSupplyName); 4300ef5dc6SGeorge Liu 4400ef5dc6SGeorge Liu powerSupplyList.emplace_back(std::move(item)); 45*788fe6cfSLakshmi Yadlapati } 4600ef5dc6SGeorge Liu asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size(); 47a7210020SGeorge Liu } 48a7210020SGeorge Liu 49a7210020SGeorge Liu inline void 50a7210020SGeorge Liu doPowerSupplyCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 51a7210020SGeorge Liu const std::string& chassisId, 52a7210020SGeorge Liu const std::optional<std::string>& validChassisPath) 53a7210020SGeorge Liu { 54a7210020SGeorge Liu if (!validChassisPath) 55a7210020SGeorge Liu { 56a7210020SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 57a7210020SGeorge Liu return; 58a7210020SGeorge Liu } 59a7210020SGeorge Liu 60a7210020SGeorge Liu asyncResp->res.addHeader( 61a7210020SGeorge Liu boost::beast::http::field::link, 62a7210020SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby"); 63a7210020SGeorge Liu asyncResp->res.jsonValue["@odata.type"] = 64a7210020SGeorge Liu "#PowerSupplyCollection.PowerSupplyCollection"; 65a7210020SGeorge Liu asyncResp->res.jsonValue["Name"] = "Power Supply Collection"; 66ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 67ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId); 68a7210020SGeorge Liu asyncResp->res.jsonValue["Description"] = 69a7210020SGeorge Liu "The collection of PowerSupply resource instances."; 707a2bb2c9SGeorge Liu asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 717a2bb2c9SGeorge Liu asyncResp->res.jsonValue["Members@odata.count"] = 0; 72a7210020SGeorge Liu 73a7210020SGeorge Liu std::string powerPath = *validChassisPath + "/powered_by"; 74*788fe6cfSLakshmi Yadlapati dbus::utility::getAssociatedSubTreePaths( 75*788fe6cfSLakshmi Yadlapati powerPath, 76*788fe6cfSLakshmi Yadlapati sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 77*788fe6cfSLakshmi Yadlapati powerSupplyInterface, 78*788fe6cfSLakshmi Yadlapati [asyncResp, chassisId]( 79a7210020SGeorge Liu const boost::system::error_code& ec, 80*788fe6cfSLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) { 81a7210020SGeorge Liu if (ec) 82a7210020SGeorge Liu { 83a7210020SGeorge Liu if (ec.value() != EBADR) 84a7210020SGeorge Liu { 85a7210020SGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error" << ec.value(); 86a7210020SGeorge Liu messages::internalError(asyncResp->res); 87a7210020SGeorge Liu } 88a7210020SGeorge Liu return; 89a7210020SGeorge Liu } 90a7210020SGeorge Liu 91*788fe6cfSLakshmi Yadlapati updatePowerSupplyList(asyncResp, chassisId, subtreePaths); 92a7210020SGeorge Liu }); 93a7210020SGeorge Liu } 94a7210020SGeorge Liu 95a7210020SGeorge Liu inline void handlePowerSupplyCollectionHead( 96a7210020SGeorge Liu App& app, const crow::Request& req, 97a7210020SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 98a7210020SGeorge Liu const std::string& chassisId) 99a7210020SGeorge Liu { 100a7210020SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 101a7210020SGeorge Liu { 102a7210020SGeorge Liu return; 103a7210020SGeorge Liu } 104a7210020SGeorge Liu 105a7210020SGeorge Liu redfish::chassis_utils::getValidChassisPath( 106a7210020SGeorge Liu asyncResp, chassisId, 107a7210020SGeorge Liu [asyncResp, 108a7210020SGeorge Liu chassisId](const std::optional<std::string>& validChassisPath) { 109a7210020SGeorge Liu if (!validChassisPath) 110a7210020SGeorge Liu { 111a7210020SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 112a7210020SGeorge Liu return; 113a7210020SGeorge Liu } 114a7210020SGeorge Liu asyncResp->res.addHeader( 115a7210020SGeorge Liu boost::beast::http::field::link, 116a7210020SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby"); 117a7210020SGeorge Liu }); 118a7210020SGeorge Liu } 119a7210020SGeorge Liu 120a7210020SGeorge Liu inline void handlePowerSupplyCollectionGet( 121a7210020SGeorge Liu App& app, const crow::Request& req, 122a7210020SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 123a7210020SGeorge Liu const std::string& chassisId) 124a7210020SGeorge Liu { 125a7210020SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 126a7210020SGeorge Liu { 127a7210020SGeorge Liu return; 128a7210020SGeorge Liu } 129a7210020SGeorge Liu 130a7210020SGeorge Liu redfish::chassis_utils::getValidChassisPath( 131a7210020SGeorge Liu asyncResp, chassisId, 132a7210020SGeorge Liu std::bind_front(doPowerSupplyCollection, asyncResp, chassisId)); 133a7210020SGeorge Liu } 134a7210020SGeorge Liu 135a7210020SGeorge Liu inline void requestRoutesPowerSupplyCollection(App& app) 136a7210020SGeorge Liu { 137a7210020SGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/") 138a7210020SGeorge Liu .privileges(redfish::privileges::headPowerSupplyCollection) 139a7210020SGeorge Liu .methods(boost::beast::http::verb::head)( 140a7210020SGeorge Liu std::bind_front(handlePowerSupplyCollectionHead, std::ref(app))); 141a7210020SGeorge Liu 142a7210020SGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/") 143a7210020SGeorge Liu .privileges(redfish::privileges::getPowerSupplyCollection) 144a7210020SGeorge Liu .methods(boost::beast::http::verb::get)( 145a7210020SGeorge Liu std::bind_front(handlePowerSupplyCollectionGet, std::ref(app))); 146a7210020SGeorge Liu } 147a7210020SGeorge Liu 14800ef5dc6SGeorge Liu inline bool checkPowerSupplyId(const std::string& powerSupplyPath, 14900ef5dc6SGeorge Liu const std::string& powerSupplyId) 15000ef5dc6SGeorge Liu { 15100ef5dc6SGeorge Liu std::string powerSupplyName = 15200ef5dc6SGeorge Liu sdbusplus::message::object_path(powerSupplyPath).filename(); 15300ef5dc6SGeorge Liu 15400ef5dc6SGeorge Liu return !(powerSupplyName.empty() || powerSupplyName != powerSupplyId); 15500ef5dc6SGeorge Liu } 15600ef5dc6SGeorge Liu 15734dfcb94SGeorge Liu inline void getValidPowerSupplyPath( 15834dfcb94SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15934dfcb94SGeorge Liu const std::string& validChassisPath, const std::string& powerSupplyId, 16034dfcb94SGeorge Liu std::function<void(const std::string& powerSupplyPath)>&& callback) 16100ef5dc6SGeorge Liu { 16200ef5dc6SGeorge Liu std::string powerPath = validChassisPath + "/powered_by"; 163*788fe6cfSLakshmi Yadlapati dbus::utility::getAssociatedSubTreePaths( 164*788fe6cfSLakshmi Yadlapati powerPath, 165*788fe6cfSLakshmi Yadlapati sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 166*788fe6cfSLakshmi Yadlapati powerSupplyInterface, 167*788fe6cfSLakshmi Yadlapati [asyncResp, powerSupplyId, callback{std::move(callback)}]( 16800ef5dc6SGeorge Liu const boost::system::error_code& ec, 169*788fe6cfSLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) { 17000ef5dc6SGeorge Liu if (ec) 17100ef5dc6SGeorge Liu { 17200ef5dc6SGeorge Liu if (ec.value() != EBADR) 17300ef5dc6SGeorge Liu { 17400ef5dc6SGeorge Liu BMCWEB_LOG_ERROR 175*788fe6cfSLakshmi Yadlapati << "DBUS response error for getAssociatedSubTreePaths" 17600ef5dc6SGeorge Liu << ec.value(); 17700ef5dc6SGeorge Liu messages::internalError(asyncResp->res); 17800ef5dc6SGeorge Liu return; 17900ef5dc6SGeorge Liu } 18000ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "PowerSupplies", 18100ef5dc6SGeorge Liu powerSupplyId); 18200ef5dc6SGeorge Liu return; 18300ef5dc6SGeorge Liu } 18400ef5dc6SGeorge Liu 185*788fe6cfSLakshmi Yadlapati for (const std::string& path : subtreePaths) 18600ef5dc6SGeorge Liu { 187*788fe6cfSLakshmi Yadlapati if (checkPowerSupplyId(path, powerSupplyId)) 18800ef5dc6SGeorge Liu { 189*788fe6cfSLakshmi Yadlapati callback(path); 19000ef5dc6SGeorge Liu return; 19100ef5dc6SGeorge Liu } 19200ef5dc6SGeorge Liu } 19300ef5dc6SGeorge Liu 194*788fe6cfSLakshmi Yadlapati if (!subtreePaths.empty()) 19500ef5dc6SGeorge Liu { 196*788fe6cfSLakshmi Yadlapati BMCWEB_LOG_WARNING << "Power supply not found: " << powerSupplyId; 19700ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "PowerSupplies", 19800ef5dc6SGeorge Liu powerSupplyId); 19900ef5dc6SGeorge Liu return; 20000ef5dc6SGeorge Liu } 20100ef5dc6SGeorge Liu }); 20200ef5dc6SGeorge Liu } 20300ef5dc6SGeorge Liu 20400ef5dc6SGeorge Liu inline void 20534dfcb94SGeorge Liu getPowerSupplyState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 20634dfcb94SGeorge Liu const std::string& service, const std::string& path) 20734dfcb94SGeorge Liu { 20834dfcb94SGeorge Liu sdbusplus::asio::getProperty<bool>( 20934dfcb94SGeorge Liu *crow::connections::systemBus, service, path, 21034dfcb94SGeorge Liu "xyz.openbmc_project.Inventory.Item", "Present", 21134dfcb94SGeorge Liu [asyncResp](const boost::system::error_code& ec, const bool value) { 21234dfcb94SGeorge Liu if (ec) 21334dfcb94SGeorge Liu { 21434dfcb94SGeorge Liu if (ec.value() != EBADR) 21534dfcb94SGeorge Liu { 21634dfcb94SGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for State " 21734dfcb94SGeorge Liu << ec.value(); 21834dfcb94SGeorge Liu messages::internalError(asyncResp->res); 21934dfcb94SGeorge Liu } 22034dfcb94SGeorge Liu return; 22134dfcb94SGeorge Liu } 22234dfcb94SGeorge Liu 22334dfcb94SGeorge Liu if (!value) 22434dfcb94SGeorge Liu { 22534dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["State"] = "Absent"; 22634dfcb94SGeorge Liu } 22734dfcb94SGeorge Liu }); 22834dfcb94SGeorge Liu } 22934dfcb94SGeorge Liu 23034dfcb94SGeorge Liu inline void 23134dfcb94SGeorge Liu getPowerSupplyHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23234dfcb94SGeorge Liu const std::string& service, const std::string& path) 23334dfcb94SGeorge Liu { 23434dfcb94SGeorge Liu sdbusplus::asio::getProperty<bool>( 23534dfcb94SGeorge Liu *crow::connections::systemBus, service, path, 23634dfcb94SGeorge Liu "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional", 23734dfcb94SGeorge Liu [asyncResp](const boost::system::error_code& ec, const bool value) { 23834dfcb94SGeorge Liu if (ec) 23934dfcb94SGeorge Liu { 24034dfcb94SGeorge Liu if (ec.value() != EBADR) 24134dfcb94SGeorge Liu { 24234dfcb94SGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for Health " 24334dfcb94SGeorge Liu << ec.value(); 24434dfcb94SGeorge Liu messages::internalError(asyncResp->res); 24534dfcb94SGeorge Liu } 24634dfcb94SGeorge Liu return; 24734dfcb94SGeorge Liu } 24834dfcb94SGeorge Liu 24934dfcb94SGeorge Liu if (!value) 25034dfcb94SGeorge Liu { 25134dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["Health"] = "Critical"; 25234dfcb94SGeorge Liu } 25334dfcb94SGeorge Liu }); 25434dfcb94SGeorge Liu } 25534dfcb94SGeorge Liu 25634dfcb94SGeorge Liu inline void 2572b45fb3bSGeorge Liu getPowerSupplyAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2582b45fb3bSGeorge Liu const std::string& service, const std::string& path) 2592b45fb3bSGeorge Liu { 2602b45fb3bSGeorge Liu sdbusplus::asio::getAllProperties( 2612b45fb3bSGeorge Liu *crow::connections::systemBus, service, path, 2622b45fb3bSGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 2632b45fb3bSGeorge Liu [asyncResp](const boost::system::error_code& ec, 2642b45fb3bSGeorge Liu const dbus::utility::DBusPropertiesMap& propertiesList) { 2652b45fb3bSGeorge Liu if (ec) 2662b45fb3bSGeorge Liu { 2672b45fb3bSGeorge Liu if (ec.value() != EBADR) 2682b45fb3bSGeorge Liu { 2692b45fb3bSGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for Asset " 2702b45fb3bSGeorge Liu << ec.value(); 2712b45fb3bSGeorge Liu messages::internalError(asyncResp->res); 2722b45fb3bSGeorge Liu } 2732b45fb3bSGeorge Liu return; 2742b45fb3bSGeorge Liu } 2752b45fb3bSGeorge Liu 2762b45fb3bSGeorge Liu const std::string* partNumber = nullptr; 2772b45fb3bSGeorge Liu const std::string* serialNumber = nullptr; 2782b45fb3bSGeorge Liu const std::string* manufacturer = nullptr; 2792b45fb3bSGeorge Liu const std::string* model = nullptr; 2802b45fb3bSGeorge Liu const std::string* sparePartNumber = nullptr; 2812b45fb3bSGeorge Liu 2822b45fb3bSGeorge Liu const bool success = sdbusplus::unpackPropertiesNoThrow( 2832b45fb3bSGeorge Liu dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 2842b45fb3bSGeorge Liu partNumber, "SerialNumber", serialNumber, "Manufacturer", 2852b45fb3bSGeorge Liu manufacturer, "Model", model, "SparePartNumber", sparePartNumber); 2862b45fb3bSGeorge Liu 2872b45fb3bSGeorge Liu if (!success) 2882b45fb3bSGeorge Liu { 2892b45fb3bSGeorge Liu messages::internalError(asyncResp->res); 2902b45fb3bSGeorge Liu return; 2912b45fb3bSGeorge Liu } 2922b45fb3bSGeorge Liu 2932b45fb3bSGeorge Liu if (partNumber != nullptr) 2942b45fb3bSGeorge Liu { 2952b45fb3bSGeorge Liu asyncResp->res.jsonValue["PartNumber"] = *partNumber; 2962b45fb3bSGeorge Liu } 2972b45fb3bSGeorge Liu 2982b45fb3bSGeorge Liu if (serialNumber != nullptr) 2992b45fb3bSGeorge Liu { 3002b45fb3bSGeorge Liu asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 3012b45fb3bSGeorge Liu } 3022b45fb3bSGeorge Liu 3032b45fb3bSGeorge Liu if (manufacturer != nullptr) 3042b45fb3bSGeorge Liu { 3052b45fb3bSGeorge Liu asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 3062b45fb3bSGeorge Liu } 3072b45fb3bSGeorge Liu 3082b45fb3bSGeorge Liu if (model != nullptr) 3092b45fb3bSGeorge Liu { 3102b45fb3bSGeorge Liu asyncResp->res.jsonValue["Model"] = *model; 3112b45fb3bSGeorge Liu } 3122b45fb3bSGeorge Liu 3132b45fb3bSGeorge Liu // SparePartNumber is optional on D-Bus so skip if it is empty 3142b45fb3bSGeorge Liu if (sparePartNumber != nullptr && !sparePartNumber->empty()) 3152b45fb3bSGeorge Liu { 3162b45fb3bSGeorge Liu asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 3172b45fb3bSGeorge Liu } 3182b45fb3bSGeorge Liu }); 3192b45fb3bSGeorge Liu } 3202b45fb3bSGeorge Liu 321a0dba87bSGeorge Liu inline void getPowerSupplyFirmwareVersion( 322a0dba87bSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 323a0dba87bSGeorge Liu const std::string& service, const std::string& path) 324a0dba87bSGeorge Liu { 325a0dba87bSGeorge Liu sdbusplus::asio::getProperty<std::string>( 326a0dba87bSGeorge Liu *crow::connections::systemBus, service, path, 327a0dba87bSGeorge Liu "xyz.openbmc_project.Software.Version", "Version", 328a0dba87bSGeorge Liu [asyncResp](const boost::system::error_code& ec, 329a0dba87bSGeorge Liu const std::string& value) { 330a0dba87bSGeorge Liu if (ec) 331a0dba87bSGeorge Liu { 332a0dba87bSGeorge Liu if (ec.value() != EBADR) 333a0dba87bSGeorge Liu { 334a0dba87bSGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for FirmwareVersion " 335a0dba87bSGeorge Liu << ec.value(); 336a0dba87bSGeorge Liu messages::internalError(asyncResp->res); 337a0dba87bSGeorge Liu } 338a0dba87bSGeorge Liu return; 339a0dba87bSGeorge Liu } 340a0dba87bSGeorge Liu asyncResp->res.jsonValue["FirmwareVersion"] = value; 341a0dba87bSGeorge Liu }); 342a0dba87bSGeorge Liu } 343a0dba87bSGeorge Liu 3442b45fb3bSGeorge Liu inline void 34544845e5fSGeorge Liu getPowerSupplyLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 34644845e5fSGeorge Liu const std::string& service, const std::string& path) 34744845e5fSGeorge Liu { 34844845e5fSGeorge Liu sdbusplus::asio::getProperty<std::string>( 34944845e5fSGeorge Liu *crow::connections::systemBus, service, path, 35044845e5fSGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 35144845e5fSGeorge Liu [asyncResp](const boost::system::error_code& ec, 35244845e5fSGeorge Liu const std::string& value) { 35344845e5fSGeorge Liu if (ec) 35444845e5fSGeorge Liu { 35544845e5fSGeorge Liu if (ec.value() != EBADR) 35644845e5fSGeorge Liu { 35744845e5fSGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for Location " 35844845e5fSGeorge Liu << ec.value(); 35944845e5fSGeorge Liu messages::internalError(asyncResp->res); 36044845e5fSGeorge Liu } 36144845e5fSGeorge Liu return; 36244845e5fSGeorge Liu } 36344845e5fSGeorge Liu asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 36444845e5fSGeorge Liu value; 36544845e5fSGeorge Liu }); 36644845e5fSGeorge Liu } 36744845e5fSGeorge Liu 36844845e5fSGeorge Liu inline void 36900ef5dc6SGeorge Liu doPowerSupplyGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 37000ef5dc6SGeorge Liu const std::string& chassisId, 37100ef5dc6SGeorge Liu const std::string& powerSupplyId, 37200ef5dc6SGeorge Liu const std::optional<std::string>& validChassisPath) 37300ef5dc6SGeorge Liu { 37400ef5dc6SGeorge Liu if (!validChassisPath) 37500ef5dc6SGeorge Liu { 37600ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 37700ef5dc6SGeorge Liu return; 37800ef5dc6SGeorge Liu } 37900ef5dc6SGeorge Liu 38000ef5dc6SGeorge Liu // Get the correct Path and Service that match the input parameters 38100ef5dc6SGeorge Liu getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId, 38234dfcb94SGeorge Liu [asyncResp, chassisId, powerSupplyId]( 38334dfcb94SGeorge Liu const std::string& powerSupplyPath) { 38400ef5dc6SGeorge Liu asyncResp->res.addHeader( 38500ef5dc6SGeorge Liu boost::beast::http::field::link, 38600ef5dc6SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby"); 38700ef5dc6SGeorge Liu asyncResp->res.jsonValue["@odata.type"] = 38800ef5dc6SGeorge Liu "#PowerSupply.v1_5_0.PowerSupply"; 38900ef5dc6SGeorge Liu asyncResp->res.jsonValue["Name"] = "Power Supply"; 39000ef5dc6SGeorge Liu asyncResp->res.jsonValue["Id"] = powerSupplyId; 39100ef5dc6SGeorge Liu asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 39200ef5dc6SGeorge Liu "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId, 39300ef5dc6SGeorge Liu powerSupplyId); 39434dfcb94SGeorge Liu 39534dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 39634dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 39734dfcb94SGeorge Liu 39834dfcb94SGeorge Liu dbus::utility::getDbusObject( 399*788fe6cfSLakshmi Yadlapati powerSupplyPath, powerSupplyInterface, 40034dfcb94SGeorge Liu [asyncResp, 40134dfcb94SGeorge Liu powerSupplyPath](const boost::system::error_code& ec, 40234dfcb94SGeorge Liu const dbus::utility::MapperGetObject& object) { 40334dfcb94SGeorge Liu if (ec || object.empty()) 40434dfcb94SGeorge Liu { 40534dfcb94SGeorge Liu messages::internalError(asyncResp->res); 40634dfcb94SGeorge Liu return; 40734dfcb94SGeorge Liu } 40834dfcb94SGeorge Liu 40934dfcb94SGeorge Liu getPowerSupplyState(asyncResp, object.begin()->first, 41034dfcb94SGeorge Liu powerSupplyPath); 41134dfcb94SGeorge Liu getPowerSupplyHealth(asyncResp, object.begin()->first, 41234dfcb94SGeorge Liu powerSupplyPath); 4132b45fb3bSGeorge Liu getPowerSupplyAsset(asyncResp, object.begin()->first, 4142b45fb3bSGeorge Liu powerSupplyPath); 415a0dba87bSGeorge Liu getPowerSupplyFirmwareVersion(asyncResp, object.begin()->first, 416a0dba87bSGeorge Liu powerSupplyPath); 41744845e5fSGeorge Liu getPowerSupplyLocation(asyncResp, object.begin()->first, 41844845e5fSGeorge Liu powerSupplyPath); 41934dfcb94SGeorge Liu }); 42000ef5dc6SGeorge Liu }); 42100ef5dc6SGeorge Liu } 42200ef5dc6SGeorge Liu 42300ef5dc6SGeorge Liu inline void 42400ef5dc6SGeorge Liu handlePowerSupplyHead(App& app, const crow::Request& req, 42500ef5dc6SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 42600ef5dc6SGeorge Liu const std::string& chassisId, 42700ef5dc6SGeorge Liu const std::string& powerSupplyId) 42800ef5dc6SGeorge Liu { 42900ef5dc6SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 43000ef5dc6SGeorge Liu { 43100ef5dc6SGeorge Liu return; 43200ef5dc6SGeorge Liu } 43300ef5dc6SGeorge Liu 43400ef5dc6SGeorge Liu redfish::chassis_utils::getValidChassisPath( 43500ef5dc6SGeorge Liu asyncResp, chassisId, 43600ef5dc6SGeorge Liu [asyncResp, chassisId, 43700ef5dc6SGeorge Liu powerSupplyId](const std::optional<std::string>& validChassisPath) { 43800ef5dc6SGeorge Liu if (!validChassisPath) 43900ef5dc6SGeorge Liu { 44000ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 44100ef5dc6SGeorge Liu return; 44200ef5dc6SGeorge Liu } 44300ef5dc6SGeorge Liu 44400ef5dc6SGeorge Liu // Get the correct Path and Service that match the input parameters 44500ef5dc6SGeorge Liu getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId, 44634dfcb94SGeorge Liu [asyncResp](const std::string&) { 44700ef5dc6SGeorge Liu asyncResp->res.addHeader( 44800ef5dc6SGeorge Liu boost::beast::http::field::link, 44900ef5dc6SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby"); 45000ef5dc6SGeorge Liu }); 45100ef5dc6SGeorge Liu }); 45200ef5dc6SGeorge Liu } 45300ef5dc6SGeorge Liu 45400ef5dc6SGeorge Liu inline void 45500ef5dc6SGeorge Liu handlePowerSupplyGet(App& app, const crow::Request& req, 45600ef5dc6SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 45700ef5dc6SGeorge Liu const std::string& chassisId, 45800ef5dc6SGeorge Liu const std::string& powerSupplyId) 45900ef5dc6SGeorge Liu { 46000ef5dc6SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 46100ef5dc6SGeorge Liu { 46200ef5dc6SGeorge Liu return; 46300ef5dc6SGeorge Liu } 46400ef5dc6SGeorge Liu 46500ef5dc6SGeorge Liu redfish::chassis_utils::getValidChassisPath( 46600ef5dc6SGeorge Liu asyncResp, chassisId, 46700ef5dc6SGeorge Liu std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId)); 46800ef5dc6SGeorge Liu } 46900ef5dc6SGeorge Liu 47000ef5dc6SGeorge Liu inline void requestRoutesPowerSupply(App& app) 47100ef5dc6SGeorge Liu { 47200ef5dc6SGeorge Liu BMCWEB_ROUTE( 47300ef5dc6SGeorge Liu app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/") 47400ef5dc6SGeorge Liu .privileges(redfish::privileges::headPowerSupply) 47500ef5dc6SGeorge Liu .methods(boost::beast::http::verb::head)( 47600ef5dc6SGeorge Liu std::bind_front(handlePowerSupplyHead, std::ref(app))); 47700ef5dc6SGeorge Liu 47800ef5dc6SGeorge Liu BMCWEB_ROUTE( 47900ef5dc6SGeorge Liu app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/") 48000ef5dc6SGeorge Liu .privileges(redfish::privileges::getPowerSupply) 48100ef5dc6SGeorge Liu .methods(boost::beast::http::verb::get)( 48200ef5dc6SGeorge Liu std::bind_front(handlePowerSupplyGet, std::ref(app))); 48300ef5dc6SGeorge Liu } 48400ef5dc6SGeorge Liu 485a7210020SGeorge Liu } // namespace redfish 486