summaryrefslogtreecommitdiff
path: root/redfish-core
diff options
context:
space:
mode:
authorEd Tanous <ed@tanous.net>2024-03-08 20:05:10 +0300
committerEd Tanous <ed@tanous.net>2024-03-18 20:48:13 +0300
commit53b00f5d985d055bddd175f7192128ae7c3286a2 (patch)
treef1d97cd44fbc26266e3e47c32e7e5d2f80d09273 /redfish-core
parent8f79c5b6a2d53d7b2ea44a2a540369cb191a3b14 (diff)
downloadbmcweb-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')
-rw-r--r--redfish-core/lib/power.hpp570
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