diff options
author | Ed Tanous <ed@tanous.net> | 2024-03-08 20:05:10 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2024-03-18 20:48:13 +0300 |
commit | 53b00f5d985d055bddd175f7192128ae7c3286a2 (patch) | |
tree | f1d97cd44fbc26266e3e47c32e7e5d2f80d09273 /redfish-core/lib | |
parent | 8f79c5b6a2d53d7b2ea44a2a540369cb191a3b14 (diff) | |
download | bmcweb-53b00f5d985d055bddd175f7192128ae7c3286a2.tar.xz |
Clean up power schema
Remove some inline lambdas. This should have no impact on function,
code was just moved.
4 tiers of inline lambdas are now down to 2. Ideally should be 1.
Tested: Thank you Gaurav!
Appears to work as intended.
Change-Id: I3acd0b77bc59ece4ed5ecde5fe4257dc903456fb
Signed-off-by: Ed Tanous <ed@tanous.net>
Diffstat (limited to 'redfish-core/lib')
-rw-r--r-- | redfish-core/lib/power.hpp | 570 |
1 files changed, 291 insertions, 279 deletions
diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp index a39fab795f..2a0f300d91 100644 --- a/redfish-core/lib/power.hpp +++ b/redfish-core/lib/power.hpp @@ -30,314 +30,326 @@ namespace redfish { -inline void setPowerCapOverride( + +inline void afterGetPowerCapEnable( const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp, - std::vector<nlohmann::json>& powerControlCollections) + uint32_t valueToSet, const boost::system::error_code& ec, + bool powerCapEnable) { - auto getChassisPath = - [sensorsAsyncResp, powerControlCollections]( - const std::optional<std::string>& chassisPath) mutable { - if (!chassisPath) - { - BMCWEB_LOG_WARNING("Don't find valid chassis path "); - messages::resourceNotFound(sensorsAsyncResp->asyncResp->res, - "Chassis", sensorsAsyncResp->chassisId); - return; - } - - if (powerControlCollections.size() != 1) + if (ec) + { + messages::internalError(sensorsAsyncResp->asyncResp->res); + BMCWEB_LOG_ERROR("powerCapEnable Get handler: Dbus error {}", ec); + return; + } + if (!powerCapEnable) + { + messages::actionNotSupported( + sensorsAsyncResp->asyncResp->res, + "Setting LimitInWatts when PowerLimit feature is disabled"); + BMCWEB_LOG_ERROR("PowerLimit feature is disabled "); + return; + } + + sdbusplus::asio::setProperty( + *crow::connections::systemBus, "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/power_cap", + "xyz.openbmc_project.Control.Power.Cap", "PowerCap", valueToSet, + [sensorsAsyncResp](const boost::system::error_code& ec2) { + if (ec2) { - BMCWEB_LOG_WARNING("Don't support multiple hosts at present "); - messages::resourceNotFound(sensorsAsyncResp->asyncResp->res, - "Power", "PowerControl"); + BMCWEB_LOG_DEBUG("Power Limit Set: Dbus error: {}", ec2); + messages::internalError(sensorsAsyncResp->asyncResp->res); return; } + sensorsAsyncResp->asyncResp->res.result( + boost::beast::http::status::no_content); + }); +} - auto& item = powerControlCollections[0]; +inline void afterGetChassisPath( + const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp, + std::vector<nlohmann::json>& powerControlCollections, + const std::optional<std::string>& chassisPath) +{ + if (!chassisPath) + { + BMCWEB_LOG_WARNING("Don't find valid chassis path "); + messages::resourceNotFound(sensorsAsyncResp->asyncResp->res, "Chassis", + sensorsAsyncResp->chassisId); + return; + } + + if (powerControlCollections.size() != 1) + { + BMCWEB_LOG_WARNING("Don't support multiple hosts at present "); + messages::resourceNotFound(sensorsAsyncResp->asyncResp->res, "Power", + "PowerControl"); + return; + } + + auto& item = powerControlCollections[0]; + + std::optional<nlohmann::json> powerLimit; + if (!json_util::readJson(item, sensorsAsyncResp->asyncResp->res, + "PowerLimit", powerLimit)) + { + return; + } + if (!powerLimit) + { + return; + } + std::optional<uint32_t> value; + if (!json_util::readJson(*powerLimit, sensorsAsyncResp->asyncResp->res, + "LimitInWatts", value)) + { + return; + } + if (!value) + { + return; + } + sdbusplus::asio::getProperty<bool>( + *crow::connections::systemBus, "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/power_cap", + "xyz.openbmc_project.Control.Power.Cap", "PowerCapEnable", + std::bind_front(afterGetPowerCapEnable, sensorsAsyncResp, *value)); +} - std::optional<nlohmann::json> powerLimit; - if (!json_util::readJson(item, sensorsAsyncResp->asyncResp->res, - "PowerLimit", powerLimit)) - { - return; - } - if (!powerLimit) - { - return; - } - std::optional<uint32_t> value; - if (!json_util::readJson(*powerLimit, sensorsAsyncResp->asyncResp->res, - "LimitInWatts", value)) +inline void afterPowerCapSettingGet( + const std::shared_ptr<SensorsAsyncResp>& sensorAsyncResp, + const boost::system::error_code& ec, + const dbus::utility::DBusPropertiesMap& properties) +{ + if (ec) + { + messages::internalError(sensorAsyncResp->asyncResp->res); + BMCWEB_LOG_ERROR("Power Limit GetAll handler: Dbus error {}", ec); + return; + } + + nlohmann::json& tempArray = + sensorAsyncResp->asyncResp->res.jsonValue["PowerControl"]; + + // Put multiple "sensors" into a single PowerControl, 0, + // so only create the first one + if (tempArray.empty()) + { + // Mandatory properties odata.id and MemberId + // A warning without a odata.type + nlohmann::json::object_t powerControl; + powerControl["@odata.type"] = "#Power.v1_0_0.PowerControl"; + powerControl["@odata.id"] = "/redfish/v1/Chassis/" + + sensorAsyncResp->chassisId + + "/Power#/PowerControl/0"; + powerControl["Name"] = "Chassis Power Control"; + powerControl["MemberId"] = "0"; + tempArray.emplace_back(std::move(powerControl)); + } + + nlohmann::json& sensorJson = tempArray.back(); + bool enabled = false; + double powerCap = 0.0; + int64_t scale = 0; + + for (const std::pair<std::string, dbus::utility::DbusVariantType>& + property : properties) + { + if (property.first == "Scale") { - return; + const int64_t* i = std::get_if<int64_t>(&property.second); + + if (i != nullptr) + { + scale = *i; + } } - if (!value) + else if (property.first == "PowerCap") { - return; - } - sdbusplus::asio::getProperty<bool>( - *crow::connections::systemBus, "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/control/host0/power_cap", - "xyz.openbmc_project.Control.Power.Cap", "PowerCapEnable", - [value, sensorsAsyncResp](const boost::system::error_code& ec, - bool powerCapEnable) { - if (ec) + const double* d = std::get_if<double>(&property.second); + const int64_t* i = std::get_if<int64_t>(&property.second); + const uint32_t* u = std::get_if<uint32_t>(&property.second); + + if (d != nullptr) { - messages::internalError(sensorsAsyncResp->asyncResp->res); - BMCWEB_LOG_ERROR("powerCapEnable Get handler: Dbus error {}", - ec); - return; + powerCap = *d; } - if (!powerCapEnable) + else if (i != nullptr) { - messages::actionNotSupported( - sensorsAsyncResp->asyncResp->res, - "Setting LimitInWatts when PowerLimit feature is disabled"); - BMCWEB_LOG_ERROR("PowerLimit feature is disabled "); - return; + powerCap = static_cast<double>(*i); } - - sdbusplus::asio::setProperty( - *crow::connections::systemBus, "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/control/host0/power_cap", - "xyz.openbmc_project.Control.Power.Cap", "PowerCap", *value, - [sensorsAsyncResp](const boost::system::error_code& ec2) { - if (ec2) - { - BMCWEB_LOG_DEBUG("Power Limit Set: Dbus error: {}", ec2); - messages::internalError(sensorsAsyncResp->asyncResp->res); - return; - } - sensorsAsyncResp->asyncResp->res.result( - boost::beast::http::status::no_content); - }); - }); - }; - redfish::chassis_utils::getValidChassisPath(sensorsAsyncResp->asyncResp, - sensorsAsyncResp->chassisId, - std::move(getChassisPath)); -} -inline void requestRoutesPower(App& app) -{ - BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/") - .privileges(redfish::privileges::getPower) - .methods(boost::beast::http::verb::get)( - [&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& chassisName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp)) - { - return; - } - asyncResp->res.jsonValue["PowerControl"] = nlohmann::json::array(); - - auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( - asyncResp, chassisName, sensors::dbus::powerPaths, - sensors::node::power); - - getChassisData(sensorAsyncResp); - - // This callback verifies that the power limit is only provided - // for the chassis that implements the Chassis inventory item. - // This prevents things like power supplies providing the - // chassis power limit - - using Mapper = dbus::utility::MapperGetSubTreePathsResponse; - auto chassisHandler = - [sensorAsyncResp](const boost::system::error_code& ec2, - const Mapper& chassisPaths) { - if (ec2) + else if (u != nullptr) { - BMCWEB_LOG_ERROR( - "Power Limit GetSubTreePaths handler Dbus error {}", ec2); - return; + powerCap = *u; } + } + else if (property.first == "PowerCapEnable") + { + const bool* b = std::get_if<bool>(&property.second); - bool found = false; - for (const std::string& chassis : chassisPaths) + if (b != nullptr) { - size_t len = std::string::npos; - size_t lastPos = chassis.rfind('/'); - if (lastPos == std::string::npos) - { - continue; - } - - if (lastPos == chassis.size() - 1) - { - size_t end = lastPos; - lastPos = chassis.rfind('/', lastPos - 1); - if (lastPos == std::string::npos) - { - continue; - } - - len = end - (lastPos + 1); - } - - std::string interfaceChassisName = chassis.substr(lastPos + 1, - len); - if (interfaceChassisName == sensorAsyncResp->chassisId) - { - found = true; - break; - } + enabled = *b; } + } + } + + // LimitException is Mandatory attribute as per OCP + // Baseline Profile – v1.0.0, so currently making it + // "NoAction" as default value to make it OCP Compliant. + sensorJson["PowerLimit"]["LimitException"] = "NoAction"; + + if (enabled) + { + // Redfish specification indicates PowerLimit should + // be null if the limit is not enabled. + sensorJson["PowerLimit"]["LimitInWatts"] = powerCap * + std::pow(10, scale); + } +} + +using Mapper = dbus::utility::MapperGetSubTreePathsResponse; +inline void + afterGetChassis(const std::shared_ptr<SensorsAsyncResp>& sensorAsyncResp, + const boost::system::error_code& ec2, + const Mapper& chassisPaths) +{ + if (ec2) + { + BMCWEB_LOG_ERROR("Power Limit GetSubTreePaths handler Dbus error {}", + ec2); + return; + } + + bool found = false; + for (const std::string& chassis : chassisPaths) + { + size_t len = std::string::npos; + size_t lastPos = chassis.rfind('/'); + if (lastPos == std::string::npos) + { + continue; + } - if (!found) + if (lastPos == chassis.size() - 1) + { + size_t end = lastPos; + lastPos = chassis.rfind('/', lastPos - 1); + if (lastPos == std::string::npos) { - BMCWEB_LOG_DEBUG("Power Limit not present for {}", - sensorAsyncResp->chassisId); - return; + continue; } - auto valueHandler = - [sensorAsyncResp]( - const boost::system::error_code& ec, - const dbus::utility::DBusPropertiesMap& properties) { - if (ec) - { - messages::internalError(sensorAsyncResp->asyncResp->res); - BMCWEB_LOG_ERROR( - "Power Limit GetAll handler: Dbus error {}", ec); - return; - } - - nlohmann::json& tempArray = - sensorAsyncResp->asyncResp->res.jsonValue["PowerControl"]; - - // Put multiple "sensors" into a single PowerControl, 0, - // so only create the first one - if (tempArray.empty()) - { - // Mandatory properties odata.id and MemberId - // A warning without a odata.type - nlohmann::json::object_t powerControl; - powerControl["@odata.type"] = "#Power.v1_0_0.PowerControl"; - powerControl["@odata.id"] = "/redfish/v1/Chassis/" + - sensorAsyncResp->chassisId + - "/Power#/PowerControl/0"; - powerControl["Name"] = "Chassis Power Control"; - powerControl["MemberId"] = "0"; - tempArray.emplace_back(std::move(powerControl)); - } - - nlohmann::json& sensorJson = tempArray.back(); - bool enabled = false; - double powerCap = 0.0; - int64_t scale = 0; - - for (const std::pair<std::string, - dbus::utility::DbusVariantType>& property : - properties) - { - if (property.first == "Scale") - { - const int64_t* i = - std::get_if<int64_t>(&property.second); - - if (i != nullptr) - { - scale = *i; - } - } - else if (property.first == "PowerCap") - { - const double* d = std::get_if<double>(&property.second); - const int64_t* i = - std::get_if<int64_t>(&property.second); - const uint32_t* u = - std::get_if<uint32_t>(&property.second); - - if (d != nullptr) - { - powerCap = *d; - } - else if (i != nullptr) - { - powerCap = static_cast<double>(*i); - } - else if (u != nullptr) - { - powerCap = *u; - } - } - else if (property.first == "PowerCapEnable") - { - const bool* b = std::get_if<bool>(&property.second); - - if (b != nullptr) - { - enabled = *b; - } - } - } - - // LimitException is Mandatory attribute as per OCP - // Baseline Profile – v1.0.0, so currently making it - // "NoAction" as default value to make it OCP Compliant. - sensorJson["PowerLimit"]["LimitException"] = "NoAction"; - - if (enabled) - { - // Redfish specification indicates PowerLimit should - // be null if the limit is not enabled. - sensorJson["PowerLimit"]["LimitInWatts"] = - powerCap * std::pow(10, scale); - } - }; - - sdbusplus::asio::getAllProperties( - *crow::connections::systemBus, "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/control/host0/power_cap", - "xyz.openbmc_project.Control.Power.Cap", - std::move(valueHandler)); - }; - - constexpr std::array<std::string_view, 2> interfaces = { - "xyz.openbmc_project.Inventory.Item.Board", - "xyz.openbmc_project.Inventory.Item.Chassis"}; - - dbus::utility::getSubTreePaths("/xyz/openbmc_project/inventory", 0, - interfaces, std::move(chassisHandler)); - }); + len = end - (lastPos + 1); + } - BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/") - .privileges(redfish::privileges::patchPower) - .methods(boost::beast::http::verb::patch)( - [&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& chassisName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + std::string interfaceChassisName = chassis.substr(lastPos + 1, len); + if (interfaceChassisName == sensorAsyncResp->chassisId) { - return; + found = true; + break; } - auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( - asyncResp, chassisName, sensors::dbus::powerPaths, - sensors::node::power); + } + + if (!found) + { + BMCWEB_LOG_DEBUG("Power Limit not present for {}", + sensorAsyncResp->chassisId); + return; + } + + sdbusplus::asio::getAllProperties( + *crow::connections::systemBus, "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/power_cap", + "xyz.openbmc_project.Control.Power.Cap", + [sensorAsyncResp](const boost::system::error_code& ec, + const dbus::utility::DBusPropertiesMap& properties + + ) { afterPowerCapSettingGet(sensorAsyncResp, ec, properties); }); +} - std::optional<std::vector<nlohmann::json>> voltageCollections; - std::optional<std::vector<nlohmann::json>> powerCtlCollections; +inline void + handleChassisPowerGet(App& app, const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& chassisName) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + asyncResp->res.jsonValue["PowerControl"] = nlohmann::json::array(); + + auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( + asyncResp, chassisName, sensors::dbus::powerPaths, + sensors::node::power); + + getChassisData(sensorAsyncResp); + + // This callback verifies that the power limit is only provided + // for the chassis that implements the Chassis inventory item. + // This prevents things like power supplies providing the + // chassis power limit + + constexpr std::array<std::string_view, 2> interfaces = { + "xyz.openbmc_project.Inventory.Item.Board", + "xyz.openbmc_project.Inventory.Item.Chassis"}; + + dbus::utility::getSubTreePaths( + "/xyz/openbmc_project/inventory", 0, interfaces, + std::bind_front(afterGetChassis, sensorAsyncResp)); +} - if (!json_util::readJsonPatch(req, sensorAsyncResp->asyncResp->res, - "PowerControl", powerCtlCollections, - "Voltages", voltageCollections)) - { - return; - } +inline void + handleChassisPowerPatch(App& app, const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& chassisName) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( + asyncResp, chassisName, sensors::dbus::powerPaths, + sensors::node::power); + + std::optional<std::vector<nlohmann::json>> voltageCollections; + std::optional<std::vector<nlohmann::json>> powerCtlCollections; + + if (!json_util::readJsonPatch(req, sensorAsyncResp->asyncResp->res, + "PowerControl", powerCtlCollections, + "Voltages", voltageCollections)) + { + return; + } + + if (powerCtlCollections) + { + redfish::chassis_utils::getValidChassisPath( + sensorAsyncResp->asyncResp, sensorAsyncResp->chassisId, + std::bind_front(afterGetChassisPath, sensorAsyncResp, + *powerCtlCollections)); + } + if (voltageCollections) + { + std::unordered_map<std::string, std::vector<nlohmann::json>> + allCollections; + allCollections.emplace("Voltages", *std::move(voltageCollections)); + setSensorsOverride(sensorAsyncResp, allCollections); + } +} - if (powerCtlCollections) - { - setPowerCapOverride(sensorAsyncResp, *powerCtlCollections); - } - if (voltageCollections) - { - std::unordered_map<std::string, std::vector<nlohmann::json>> - allCollections; - allCollections.emplace("Voltages", *std::move(voltageCollections)); - setSensorsOverride(sensorAsyncResp, allCollections); - } - }); +inline void requestRoutesPower(App& app) +{ + BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/") + .privileges(redfish::privileges::getPower) + .methods(boost::beast::http::verb::get)( + std::bind_front(handleChassisPowerGet, std::ref(app))); + + BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/") + .privileges(redfish::privileges::patchPower) + .methods(boost::beast::http::verb::patch)( + std::bind_front(handleChassisPowerPatch, std::ref(app))); } } // namespace redfish |