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 2100ef5dc6SGeorge Liu inline void 2200ef5dc6SGeorge Liu updatePowerSupplyList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2300ef5dc6SGeorge Liu const std::string& chassisId, 2400ef5dc6SGeorge Liu const std::string& powerSupplyPath) 25a7210020SGeorge Liu { 2600ef5dc6SGeorge Liu std::string powerSupplyName = 2700ef5dc6SGeorge Liu sdbusplus::message::object_path(powerSupplyPath).filename(); 2800ef5dc6SGeorge Liu if (powerSupplyName.empty()) 2900ef5dc6SGeorge Liu { 3000ef5dc6SGeorge Liu return; 3100ef5dc6SGeorge Liu } 3200ef5dc6SGeorge Liu 3300ef5dc6SGeorge Liu nlohmann::json item = nlohmann::json::object(); 3400ef5dc6SGeorge Liu item["@odata.id"] = boost::urls::format( 3500ef5dc6SGeorge Liu "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId, 3600ef5dc6SGeorge Liu powerSupplyName); 3700ef5dc6SGeorge Liu 3800ef5dc6SGeorge Liu nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"]; 3900ef5dc6SGeorge Liu powerSupplyList.emplace_back(std::move(item)); 4000ef5dc6SGeorge Liu asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size(); 41a7210020SGeorge Liu } 42a7210020SGeorge Liu 43a7210020SGeorge Liu inline void 44a7210020SGeorge Liu doPowerSupplyCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 45a7210020SGeorge Liu const std::string& chassisId, 46a7210020SGeorge Liu const std::optional<std::string>& validChassisPath) 47a7210020SGeorge Liu { 48a7210020SGeorge Liu if (!validChassisPath) 49a7210020SGeorge Liu { 50a7210020SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 51a7210020SGeorge Liu return; 52a7210020SGeorge Liu } 53a7210020SGeorge Liu 54a7210020SGeorge Liu asyncResp->res.addHeader( 55a7210020SGeorge Liu boost::beast::http::field::link, 56a7210020SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby"); 57a7210020SGeorge Liu asyncResp->res.jsonValue["@odata.type"] = 58a7210020SGeorge Liu "#PowerSupplyCollection.PowerSupplyCollection"; 59a7210020SGeorge Liu asyncResp->res.jsonValue["Name"] = "Power Supply Collection"; 60ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 61ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId); 62a7210020SGeorge Liu asyncResp->res.jsonValue["Description"] = 63a7210020SGeorge Liu "The collection of PowerSupply resource instances."; 647a2bb2c9SGeorge Liu asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 657a2bb2c9SGeorge Liu asyncResp->res.jsonValue["Members@odata.count"] = 0; 66a7210020SGeorge Liu 67a7210020SGeorge Liu std::string powerPath = *validChassisPath + "/powered_by"; 68a7210020SGeorge Liu dbus::utility::getAssociationEndPoints( 69a7210020SGeorge Liu powerPath, [asyncResp, chassisId]( 70a7210020SGeorge Liu const boost::system::error_code& ec, 71a7210020SGeorge Liu const dbus::utility::MapperEndPoints& endpoints) { 72a7210020SGeorge Liu if (ec) 73a7210020SGeorge Liu { 74a7210020SGeorge Liu if (ec.value() != EBADR) 75a7210020SGeorge Liu { 76a7210020SGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error" << ec.value(); 77a7210020SGeorge Liu messages::internalError(asyncResp->res); 78a7210020SGeorge Liu } 79a7210020SGeorge Liu return; 80a7210020SGeorge Liu } 81a7210020SGeorge Liu 82a7210020SGeorge Liu for (const auto& endpoint : endpoints) 83a7210020SGeorge Liu { 84a7210020SGeorge Liu updatePowerSupplyList(asyncResp, chassisId, endpoint); 85a7210020SGeorge Liu } 86a7210020SGeorge Liu }); 87a7210020SGeorge Liu } 88a7210020SGeorge Liu 89a7210020SGeorge Liu inline void handlePowerSupplyCollectionHead( 90a7210020SGeorge Liu App& app, const crow::Request& req, 91a7210020SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 92a7210020SGeorge Liu const std::string& chassisId) 93a7210020SGeorge Liu { 94a7210020SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 95a7210020SGeorge Liu { 96a7210020SGeorge Liu return; 97a7210020SGeorge Liu } 98a7210020SGeorge Liu 99a7210020SGeorge Liu redfish::chassis_utils::getValidChassisPath( 100a7210020SGeorge Liu asyncResp, chassisId, 101a7210020SGeorge Liu [asyncResp, 102a7210020SGeorge Liu chassisId](const std::optional<std::string>& validChassisPath) { 103a7210020SGeorge Liu if (!validChassisPath) 104a7210020SGeorge Liu { 105a7210020SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 106a7210020SGeorge Liu return; 107a7210020SGeorge Liu } 108a7210020SGeorge Liu asyncResp->res.addHeader( 109a7210020SGeorge Liu boost::beast::http::field::link, 110a7210020SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby"); 111a7210020SGeorge Liu }); 112a7210020SGeorge Liu } 113a7210020SGeorge Liu 114a7210020SGeorge Liu inline void handlePowerSupplyCollectionGet( 115a7210020SGeorge Liu App& app, const crow::Request& req, 116a7210020SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 117a7210020SGeorge Liu const std::string& chassisId) 118a7210020SGeorge Liu { 119a7210020SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 120a7210020SGeorge Liu { 121a7210020SGeorge Liu return; 122a7210020SGeorge Liu } 123a7210020SGeorge Liu 124a7210020SGeorge Liu redfish::chassis_utils::getValidChassisPath( 125a7210020SGeorge Liu asyncResp, chassisId, 126a7210020SGeorge Liu std::bind_front(doPowerSupplyCollection, asyncResp, chassisId)); 127a7210020SGeorge Liu } 128a7210020SGeorge Liu 129a7210020SGeorge Liu inline void requestRoutesPowerSupplyCollection(App& app) 130a7210020SGeorge Liu { 131a7210020SGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/") 132a7210020SGeorge Liu .privileges(redfish::privileges::headPowerSupplyCollection) 133a7210020SGeorge Liu .methods(boost::beast::http::verb::head)( 134a7210020SGeorge Liu std::bind_front(handlePowerSupplyCollectionHead, std::ref(app))); 135a7210020SGeorge Liu 136a7210020SGeorge Liu BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/") 137a7210020SGeorge Liu .privileges(redfish::privileges::getPowerSupplyCollection) 138a7210020SGeorge Liu .methods(boost::beast::http::verb::get)( 139a7210020SGeorge Liu std::bind_front(handlePowerSupplyCollectionGet, std::ref(app))); 140a7210020SGeorge Liu } 141a7210020SGeorge Liu 14200ef5dc6SGeorge Liu inline bool checkPowerSupplyId(const std::string& powerSupplyPath, 14300ef5dc6SGeorge Liu const std::string& powerSupplyId) 14400ef5dc6SGeorge Liu { 14500ef5dc6SGeorge Liu std::string powerSupplyName = 14600ef5dc6SGeorge Liu sdbusplus::message::object_path(powerSupplyPath).filename(); 14700ef5dc6SGeorge Liu 14800ef5dc6SGeorge Liu return !(powerSupplyName.empty() || powerSupplyName != powerSupplyId); 14900ef5dc6SGeorge Liu } 15000ef5dc6SGeorge Liu 15134dfcb94SGeorge Liu inline void getValidPowerSupplyPath( 15234dfcb94SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15334dfcb94SGeorge Liu const std::string& validChassisPath, const std::string& powerSupplyId, 15434dfcb94SGeorge Liu std::function<void(const std::string& powerSupplyPath)>&& callback) 15500ef5dc6SGeorge Liu { 15600ef5dc6SGeorge Liu std::string powerPath = validChassisPath + "/powered_by"; 15700ef5dc6SGeorge Liu dbus::utility::getAssociationEndPoints( 15800ef5dc6SGeorge Liu powerPath, [asyncResp, powerSupplyId, callback{std::move(callback)}]( 15900ef5dc6SGeorge Liu const boost::system::error_code& ec, 16000ef5dc6SGeorge Liu const dbus::utility::MapperEndPoints& endpoints) { 16100ef5dc6SGeorge Liu if (ec) 16200ef5dc6SGeorge Liu { 16300ef5dc6SGeorge Liu if (ec.value() != EBADR) 16400ef5dc6SGeorge Liu { 16500ef5dc6SGeorge Liu BMCWEB_LOG_ERROR 16600ef5dc6SGeorge Liu << "DBUS response error for getAssociationEndPoints" 16700ef5dc6SGeorge Liu << ec.value(); 16800ef5dc6SGeorge Liu messages::internalError(asyncResp->res); 16900ef5dc6SGeorge Liu return; 17000ef5dc6SGeorge Liu } 17100ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "PowerSupplies", 17200ef5dc6SGeorge Liu powerSupplyId); 17300ef5dc6SGeorge Liu return; 17400ef5dc6SGeorge Liu } 17500ef5dc6SGeorge Liu 17600ef5dc6SGeorge Liu for (const auto& endpoint : endpoints) 17700ef5dc6SGeorge Liu { 17800ef5dc6SGeorge Liu if (checkPowerSupplyId(endpoint, powerSupplyId)) 17900ef5dc6SGeorge Liu { 18034dfcb94SGeorge Liu callback(endpoint); 18100ef5dc6SGeorge Liu return; 18200ef5dc6SGeorge Liu } 18300ef5dc6SGeorge Liu } 18400ef5dc6SGeorge Liu 18500ef5dc6SGeorge Liu if (!endpoints.empty()) 18600ef5dc6SGeorge Liu { 18700ef5dc6SGeorge Liu BMCWEB_LOG_WARNING << "Power supply not found: " 18800ef5dc6SGeorge Liu << powerSupplyId; 18900ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "PowerSupplies", 19000ef5dc6SGeorge Liu powerSupplyId); 19100ef5dc6SGeorge Liu return; 19200ef5dc6SGeorge Liu } 19300ef5dc6SGeorge Liu }); 19400ef5dc6SGeorge Liu } 19500ef5dc6SGeorge Liu 19600ef5dc6SGeorge Liu inline void 19734dfcb94SGeorge Liu getPowerSupplyState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 19834dfcb94SGeorge Liu const std::string& service, const std::string& path) 19934dfcb94SGeorge Liu { 20034dfcb94SGeorge Liu sdbusplus::asio::getProperty<bool>( 20134dfcb94SGeorge Liu *crow::connections::systemBus, service, path, 20234dfcb94SGeorge Liu "xyz.openbmc_project.Inventory.Item", "Present", 20334dfcb94SGeorge Liu [asyncResp](const boost::system::error_code& ec, const bool value) { 20434dfcb94SGeorge Liu if (ec) 20534dfcb94SGeorge Liu { 20634dfcb94SGeorge Liu if (ec.value() != EBADR) 20734dfcb94SGeorge Liu { 20834dfcb94SGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for State " 20934dfcb94SGeorge Liu << ec.value(); 21034dfcb94SGeorge Liu messages::internalError(asyncResp->res); 21134dfcb94SGeorge Liu } 21234dfcb94SGeorge Liu return; 21334dfcb94SGeorge Liu } 21434dfcb94SGeorge Liu 21534dfcb94SGeorge Liu if (!value) 21634dfcb94SGeorge Liu { 21734dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["State"] = "Absent"; 21834dfcb94SGeorge Liu } 21934dfcb94SGeorge Liu }); 22034dfcb94SGeorge Liu } 22134dfcb94SGeorge Liu 22234dfcb94SGeorge Liu inline void 22334dfcb94SGeorge Liu getPowerSupplyHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 22434dfcb94SGeorge Liu const std::string& service, const std::string& path) 22534dfcb94SGeorge Liu { 22634dfcb94SGeorge Liu sdbusplus::asio::getProperty<bool>( 22734dfcb94SGeorge Liu *crow::connections::systemBus, service, path, 22834dfcb94SGeorge Liu "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional", 22934dfcb94SGeorge Liu [asyncResp](const boost::system::error_code& ec, const bool value) { 23034dfcb94SGeorge Liu if (ec) 23134dfcb94SGeorge Liu { 23234dfcb94SGeorge Liu if (ec.value() != EBADR) 23334dfcb94SGeorge Liu { 23434dfcb94SGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for Health " 23534dfcb94SGeorge Liu << ec.value(); 23634dfcb94SGeorge Liu messages::internalError(asyncResp->res); 23734dfcb94SGeorge Liu } 23834dfcb94SGeorge Liu return; 23934dfcb94SGeorge Liu } 24034dfcb94SGeorge Liu 24134dfcb94SGeorge Liu if (!value) 24234dfcb94SGeorge Liu { 24334dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["Health"] = "Critical"; 24434dfcb94SGeorge Liu } 24534dfcb94SGeorge Liu }); 24634dfcb94SGeorge Liu } 24734dfcb94SGeorge Liu 24834dfcb94SGeorge Liu inline void 2492b45fb3bSGeorge Liu getPowerSupplyAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2502b45fb3bSGeorge Liu const std::string& service, const std::string& path) 2512b45fb3bSGeorge Liu { 2522b45fb3bSGeorge Liu sdbusplus::asio::getAllProperties( 2532b45fb3bSGeorge Liu *crow::connections::systemBus, service, path, 2542b45fb3bSGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 2552b45fb3bSGeorge Liu [asyncResp](const boost::system::error_code& ec, 2562b45fb3bSGeorge Liu const dbus::utility::DBusPropertiesMap& propertiesList) { 2572b45fb3bSGeorge Liu if (ec) 2582b45fb3bSGeorge Liu { 2592b45fb3bSGeorge Liu if (ec.value() != EBADR) 2602b45fb3bSGeorge Liu { 2612b45fb3bSGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for Asset " 2622b45fb3bSGeorge Liu << ec.value(); 2632b45fb3bSGeorge Liu messages::internalError(asyncResp->res); 2642b45fb3bSGeorge Liu } 2652b45fb3bSGeorge Liu return; 2662b45fb3bSGeorge Liu } 2672b45fb3bSGeorge Liu 2682b45fb3bSGeorge Liu const std::string* partNumber = nullptr; 2692b45fb3bSGeorge Liu const std::string* serialNumber = nullptr; 2702b45fb3bSGeorge Liu const std::string* manufacturer = nullptr; 2712b45fb3bSGeorge Liu const std::string* model = nullptr; 2722b45fb3bSGeorge Liu const std::string* sparePartNumber = nullptr; 2732b45fb3bSGeorge Liu 2742b45fb3bSGeorge Liu const bool success = sdbusplus::unpackPropertiesNoThrow( 2752b45fb3bSGeorge Liu dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 2762b45fb3bSGeorge Liu partNumber, "SerialNumber", serialNumber, "Manufacturer", 2772b45fb3bSGeorge Liu manufacturer, "Model", model, "SparePartNumber", sparePartNumber); 2782b45fb3bSGeorge Liu 2792b45fb3bSGeorge Liu if (!success) 2802b45fb3bSGeorge Liu { 2812b45fb3bSGeorge Liu messages::internalError(asyncResp->res); 2822b45fb3bSGeorge Liu return; 2832b45fb3bSGeorge Liu } 2842b45fb3bSGeorge Liu 2852b45fb3bSGeorge Liu if (partNumber != nullptr) 2862b45fb3bSGeorge Liu { 2872b45fb3bSGeorge Liu asyncResp->res.jsonValue["PartNumber"] = *partNumber; 2882b45fb3bSGeorge Liu } 2892b45fb3bSGeorge Liu 2902b45fb3bSGeorge Liu if (serialNumber != nullptr) 2912b45fb3bSGeorge Liu { 2922b45fb3bSGeorge Liu asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 2932b45fb3bSGeorge Liu } 2942b45fb3bSGeorge Liu 2952b45fb3bSGeorge Liu if (manufacturer != nullptr) 2962b45fb3bSGeorge Liu { 2972b45fb3bSGeorge Liu asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 2982b45fb3bSGeorge Liu } 2992b45fb3bSGeorge Liu 3002b45fb3bSGeorge Liu if (model != nullptr) 3012b45fb3bSGeorge Liu { 3022b45fb3bSGeorge Liu asyncResp->res.jsonValue["Model"] = *model; 3032b45fb3bSGeorge Liu } 3042b45fb3bSGeorge Liu 3052b45fb3bSGeorge Liu // SparePartNumber is optional on D-Bus so skip if it is empty 3062b45fb3bSGeorge Liu if (sparePartNumber != nullptr && !sparePartNumber->empty()) 3072b45fb3bSGeorge Liu { 3082b45fb3bSGeorge Liu asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 3092b45fb3bSGeorge Liu } 3102b45fb3bSGeorge Liu }); 3112b45fb3bSGeorge Liu } 3122b45fb3bSGeorge Liu 313a0dba87bSGeorge Liu inline void getPowerSupplyFirmwareVersion( 314a0dba87bSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 315a0dba87bSGeorge Liu const std::string& service, const std::string& path) 316a0dba87bSGeorge Liu { 317a0dba87bSGeorge Liu sdbusplus::asio::getProperty<std::string>( 318a0dba87bSGeorge Liu *crow::connections::systemBus, service, path, 319a0dba87bSGeorge Liu "xyz.openbmc_project.Software.Version", "Version", 320a0dba87bSGeorge Liu [asyncResp](const boost::system::error_code& ec, 321a0dba87bSGeorge Liu const std::string& value) { 322a0dba87bSGeorge Liu if (ec) 323a0dba87bSGeorge Liu { 324a0dba87bSGeorge Liu if (ec.value() != EBADR) 325a0dba87bSGeorge Liu { 326a0dba87bSGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for FirmwareVersion " 327a0dba87bSGeorge Liu << ec.value(); 328a0dba87bSGeorge Liu messages::internalError(asyncResp->res); 329a0dba87bSGeorge Liu } 330a0dba87bSGeorge Liu return; 331a0dba87bSGeorge Liu } 332a0dba87bSGeorge Liu asyncResp->res.jsonValue["FirmwareVersion"] = value; 333a0dba87bSGeorge Liu }); 334a0dba87bSGeorge Liu } 335a0dba87bSGeorge Liu 3362b45fb3bSGeorge Liu inline void 337*44845e5fSGeorge Liu getPowerSupplyLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 338*44845e5fSGeorge Liu const std::string& service, const std::string& path) 339*44845e5fSGeorge Liu { 340*44845e5fSGeorge Liu sdbusplus::asio::getProperty<std::string>( 341*44845e5fSGeorge Liu *crow::connections::systemBus, service, path, 342*44845e5fSGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 343*44845e5fSGeorge Liu [asyncResp](const boost::system::error_code& ec, 344*44845e5fSGeorge Liu const std::string& value) { 345*44845e5fSGeorge Liu if (ec) 346*44845e5fSGeorge Liu { 347*44845e5fSGeorge Liu if (ec.value() != EBADR) 348*44845e5fSGeorge Liu { 349*44845e5fSGeorge Liu BMCWEB_LOG_ERROR << "DBUS response error for Location " 350*44845e5fSGeorge Liu << ec.value(); 351*44845e5fSGeorge Liu messages::internalError(asyncResp->res); 352*44845e5fSGeorge Liu } 353*44845e5fSGeorge Liu return; 354*44845e5fSGeorge Liu } 355*44845e5fSGeorge Liu asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 356*44845e5fSGeorge Liu value; 357*44845e5fSGeorge Liu }); 358*44845e5fSGeorge Liu } 359*44845e5fSGeorge Liu 360*44845e5fSGeorge Liu inline void 36100ef5dc6SGeorge Liu doPowerSupplyGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 36200ef5dc6SGeorge Liu const std::string& chassisId, 36300ef5dc6SGeorge Liu const std::string& powerSupplyId, 36400ef5dc6SGeorge Liu const std::optional<std::string>& validChassisPath) 36500ef5dc6SGeorge Liu { 36600ef5dc6SGeorge Liu if (!validChassisPath) 36700ef5dc6SGeorge Liu { 36800ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 36900ef5dc6SGeorge Liu return; 37000ef5dc6SGeorge Liu } 37100ef5dc6SGeorge Liu 37200ef5dc6SGeorge Liu // Get the correct Path and Service that match the input parameters 37300ef5dc6SGeorge Liu getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId, 37434dfcb94SGeorge Liu [asyncResp, chassisId, powerSupplyId]( 37534dfcb94SGeorge Liu const std::string& powerSupplyPath) { 37600ef5dc6SGeorge Liu asyncResp->res.addHeader( 37700ef5dc6SGeorge Liu boost::beast::http::field::link, 37800ef5dc6SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby"); 37900ef5dc6SGeorge Liu asyncResp->res.jsonValue["@odata.type"] = 38000ef5dc6SGeorge Liu "#PowerSupply.v1_5_0.PowerSupply"; 38100ef5dc6SGeorge Liu asyncResp->res.jsonValue["Name"] = "Power Supply"; 38200ef5dc6SGeorge Liu asyncResp->res.jsonValue["Id"] = powerSupplyId; 38300ef5dc6SGeorge Liu asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 38400ef5dc6SGeorge Liu "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId, 38500ef5dc6SGeorge Liu powerSupplyId); 38634dfcb94SGeorge Liu 38734dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 38834dfcb94SGeorge Liu asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 38934dfcb94SGeorge Liu 39034dfcb94SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 39134dfcb94SGeorge Liu "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 39234dfcb94SGeorge Liu dbus::utility::getDbusObject( 39334dfcb94SGeorge Liu powerSupplyPath, interfaces, 39434dfcb94SGeorge Liu [asyncResp, 39534dfcb94SGeorge Liu powerSupplyPath](const boost::system::error_code& ec, 39634dfcb94SGeorge Liu const dbus::utility::MapperGetObject& object) { 39734dfcb94SGeorge Liu if (ec || object.empty()) 39834dfcb94SGeorge Liu { 39934dfcb94SGeorge Liu messages::internalError(asyncResp->res); 40034dfcb94SGeorge Liu return; 40134dfcb94SGeorge Liu } 40234dfcb94SGeorge Liu 40334dfcb94SGeorge Liu getPowerSupplyState(asyncResp, object.begin()->first, 40434dfcb94SGeorge Liu powerSupplyPath); 40534dfcb94SGeorge Liu getPowerSupplyHealth(asyncResp, object.begin()->first, 40634dfcb94SGeorge Liu powerSupplyPath); 4072b45fb3bSGeorge Liu getPowerSupplyAsset(asyncResp, object.begin()->first, 4082b45fb3bSGeorge Liu powerSupplyPath); 409a0dba87bSGeorge Liu getPowerSupplyFirmwareVersion(asyncResp, object.begin()->first, 410a0dba87bSGeorge Liu powerSupplyPath); 411*44845e5fSGeorge Liu getPowerSupplyLocation(asyncResp, object.begin()->first, 412*44845e5fSGeorge Liu powerSupplyPath); 41334dfcb94SGeorge Liu }); 41400ef5dc6SGeorge Liu }); 41500ef5dc6SGeorge Liu } 41600ef5dc6SGeorge Liu 41700ef5dc6SGeorge Liu inline void 41800ef5dc6SGeorge Liu handlePowerSupplyHead(App& app, const crow::Request& req, 41900ef5dc6SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 42000ef5dc6SGeorge Liu const std::string& chassisId, 42100ef5dc6SGeorge Liu const std::string& powerSupplyId) 42200ef5dc6SGeorge Liu { 42300ef5dc6SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 42400ef5dc6SGeorge Liu { 42500ef5dc6SGeorge Liu return; 42600ef5dc6SGeorge Liu } 42700ef5dc6SGeorge Liu 42800ef5dc6SGeorge Liu redfish::chassis_utils::getValidChassisPath( 42900ef5dc6SGeorge Liu asyncResp, chassisId, 43000ef5dc6SGeorge Liu [asyncResp, chassisId, 43100ef5dc6SGeorge Liu powerSupplyId](const std::optional<std::string>& validChassisPath) { 43200ef5dc6SGeorge Liu if (!validChassisPath) 43300ef5dc6SGeorge Liu { 43400ef5dc6SGeorge Liu messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 43500ef5dc6SGeorge Liu return; 43600ef5dc6SGeorge Liu } 43700ef5dc6SGeorge Liu 43800ef5dc6SGeorge Liu // Get the correct Path and Service that match the input parameters 43900ef5dc6SGeorge Liu getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId, 44034dfcb94SGeorge Liu [asyncResp](const std::string&) { 44100ef5dc6SGeorge Liu asyncResp->res.addHeader( 44200ef5dc6SGeorge Liu boost::beast::http::field::link, 44300ef5dc6SGeorge Liu "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby"); 44400ef5dc6SGeorge Liu }); 44500ef5dc6SGeorge Liu }); 44600ef5dc6SGeorge Liu } 44700ef5dc6SGeorge Liu 44800ef5dc6SGeorge Liu inline void 44900ef5dc6SGeorge Liu handlePowerSupplyGet(App& app, const crow::Request& req, 45000ef5dc6SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 45100ef5dc6SGeorge Liu const std::string& chassisId, 45200ef5dc6SGeorge Liu const std::string& powerSupplyId) 45300ef5dc6SGeorge Liu { 45400ef5dc6SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 45500ef5dc6SGeorge Liu { 45600ef5dc6SGeorge Liu return; 45700ef5dc6SGeorge Liu } 45800ef5dc6SGeorge Liu 45900ef5dc6SGeorge Liu redfish::chassis_utils::getValidChassisPath( 46000ef5dc6SGeorge Liu asyncResp, chassisId, 46100ef5dc6SGeorge Liu std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId)); 46200ef5dc6SGeorge Liu } 46300ef5dc6SGeorge Liu 46400ef5dc6SGeorge Liu inline void requestRoutesPowerSupply(App& app) 46500ef5dc6SGeorge Liu { 46600ef5dc6SGeorge Liu BMCWEB_ROUTE( 46700ef5dc6SGeorge Liu app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/") 46800ef5dc6SGeorge Liu .privileges(redfish::privileges::headPowerSupply) 46900ef5dc6SGeorge Liu .methods(boost::beast::http::verb::head)( 47000ef5dc6SGeorge Liu std::bind_front(handlePowerSupplyHead, std::ref(app))); 47100ef5dc6SGeorge Liu 47200ef5dc6SGeorge Liu BMCWEB_ROUTE( 47300ef5dc6SGeorge Liu app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/") 47400ef5dc6SGeorge Liu .privileges(redfish::privileges::getPowerSupply) 47500ef5dc6SGeorge Liu .methods(boost::beast::http::verb::get)( 47600ef5dc6SGeorge Liu std::bind_front(handlePowerSupplyGet, std::ref(app))); 47700ef5dc6SGeorge Liu } 47800ef5dc6SGeorge Liu 479a7210020SGeorge Liu } // namespace redfish 480