chassis: replace lambda with inline functions
It has been a convention that request route functions take inline
functions instead of lambdas. The benifets include less indents,
beging more readable + unit test-able (take a look at the unit test that
this commit adds for example).
This commit also fixed neccessary headers to make the test compile. The
headers of the unit test source is a complete list. But headers of the
core codes are not complete. These header clean up will be done in a
separate effort once https://gerrit.openbmc.org/c/openbmc/bmcweb/+/55138
is submitted.
Tested:
1. no service validator errors on real hardware.
Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Change-Id: I4b23ba54707cea947b5db771c72aa64899041511
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index cfa1832..7982281 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -17,6 +17,7 @@
#include "health.hpp"
#include "led.hpp"
+#include "utils/json_utils.hpp"
#include <app.hpp>
#include <dbus_utility.hpp>
@@ -131,6 +132,25 @@
std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
}
+inline void handleChassisCollectionGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ChassisCollection.ChassisCollection";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
+ asyncResp->res.jsonValue["Name"] = "Chassis Collection";
+
+ collection_util::getCollectionMembers(
+ asyncResp, "/redfish/v1/Chassis",
+ {"xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"});
+}
+
/**
* ChassisCollection derived class for delivering Chassis Collection Schema
* Functions triggers appropriate requests on DBus
@@ -140,22 +160,7 @@
BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
.privileges(redfish::privileges::getChassisCollection)
.methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#ChassisCollection.ChassisCollection";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
- asyncResp->res.jsonValue["Name"] = "Chassis Collection";
-
- collection_util::getCollectionMembers(
- asyncResp, "/redfish/v1/Chassis",
- {"xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"});
- });
+ std::bind_front(handleChassisCollectionGet, std::ref(app)));
}
inline void
@@ -199,6 +204,363 @@
});
}
+inline void
+ handleChassisGet(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ const std::array<const char*, 2> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, chassisId(std::string(chassisId))](
+ const boost::system::error_code ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::vector<std::string>>>>&
+ object : subtree)
+ {
+ const std::string& path = object.first;
+ const std::vector<std::pair<std::string, std::vector<std::string>>>&
+ connectionNames = object.second;
+
+ sdbusplus::message::object_path objPath(path);
+ if (objPath.filename() != chassisId)
+ {
+ continue;
+ }
+
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
+
+ sdbusplus::asio::getProperty<std::vector<std::string>>(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.ObjectMapper", path + "/all_sensors",
+ "xyz.openbmc_project.Association", "endpoints",
+ [health](const boost::system::error_code ec2,
+ const std::vector<std::string>& resp) {
+ if (ec2)
+ {
+ return; // no sensors = no failures
+ }
+ health->inventory = resp;
+ });
+
+ health->populate();
+
+ if (connectionNames.empty())
+ {
+ BMCWEB_LOG_ERROR << "Got 0 Connection names";
+ continue;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Chassis.v1_16_0.Chassis";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId;
+ asyncResp->res.jsonValue["Name"] = "Chassis Collection";
+ asyncResp->res.jsonValue["ChassisType"] = "RackMount";
+ asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
+ "/redfish/v1/Chassis/" + chassisId + "/Actions/Chassis.Reset";
+ asyncResp->res
+ .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
+ "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
+ asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
+ "/redfish/v1/Systems/system/PCIeDevices";
+
+ sdbusplus::asio::getProperty<std::vector<std::string>>(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.ObjectMapper", path + "/drive",
+ "xyz.openbmc_project.Association", "endpoints",
+ [asyncResp, chassisId](const boost::system::error_code ec3,
+ const std::vector<std::string>& resp) {
+ if (ec3 || resp.empty())
+ {
+ return; // no drives = no failures
+ }
+
+ nlohmann::json reference;
+ reference["odata.id"] = crow::utility::urlFromPieces(
+ "redfish", "v1", "Chassis", chassisId, "Drives");
+ asyncResp->res.jsonValue["Drives"] = std::move(reference);
+ });
+
+ const std::string& connectionName = connectionNames[0].first;
+
+ const std::vector<std::string>& interfaces2 =
+ connectionNames[0].second;
+ const std::array<const char*, 2> hasIndicatorLed = {
+ "xyz.openbmc_project.Inventory.Item.Panel",
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
+
+ const std::string assetTagInterface =
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag";
+ if (std::find(interfaces2.begin(), interfaces2.end(),
+ assetTagInterface) != interfaces2.end())
+ {
+ sdbusplus::asio::getProperty<std::string>(
+ *crow::connections::systemBus, connectionName, path,
+ assetTagInterface, "AssetTag",
+ [asyncResp, chassisId(std::string(chassisId))](
+ const boost::system::error_code ec2,
+ const std::string& property) {
+ if (ec2)
+ {
+ BMCWEB_LOG_DEBUG << "DBus response error for AssetTag";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["AssetTag"] = property;
+ });
+ }
+
+ for (const char* interface : hasIndicatorLed)
+ {
+ if (std::find(interfaces2.begin(), interfaces2.end(),
+ interface) != interfaces2.end())
+ {
+ getIndicatorLedState(asyncResp);
+ getLocationIndicatorActive(asyncResp);
+ break;
+ }
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, chassisId(std::string(chassisId))](
+ const boost::system::error_code /*ec2*/,
+ const dbus::utility::DBusPropertiesMap& propertiesList) {
+ for (const std::pair<std::string,
+ dbus::utility::DbusVariantType>& property :
+ propertiesList)
+ {
+ // Store DBus properties that are also
+ // Redfish properties with same name and a
+ // string value
+ const std::string& propertyName = property.first;
+ if ((propertyName == "PartNumber") ||
+ (propertyName == "SerialNumber") ||
+ (propertyName == "Manufacturer") ||
+ (propertyName == "Model") ||
+ (propertyName == "SparePartNumber"))
+ {
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+ if (value == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "Null value returned for "
+ << propertyName;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // SparePartNumber is optional on D-Bus
+ // so skip if it is empty
+ if (propertyName == "SparePartNumber")
+ {
+ if (value->empty())
+ {
+ continue;
+ }
+ }
+ asyncResp->res.jsonValue[propertyName] = *value;
+ }
+ }
+ asyncResp->res.jsonValue["Name"] = chassisId;
+ asyncResp->res.jsonValue["Id"] = chassisId;
+#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
+ asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId + "/Thermal";
+ // Power object
+ asyncResp->res.jsonValue["Power"]["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId + "/Power";
+#endif
+ // SensorCollection
+ asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId + "/Sensors";
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+
+ nlohmann::json::array_t computerSystems;
+ nlohmann::json::object_t system;
+ system["@odata.id"] = "/redfish/v1/Systems/system";
+ computerSystems.push_back(std::move(system));
+ asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
+ std::move(computerSystems);
+
+ nlohmann::json::array_t managedBy;
+ nlohmann::json::object_t manager;
+ manager["@odata.id"] = "/redfish/v1/Managers/bmc";
+ managedBy.push_back(std::move(manager));
+ asyncResp->res.jsonValue["Links"]["ManagedBy"] =
+ std::move(managedBy);
+ getChassisState(asyncResp);
+ },
+ connectionName, path, "org.freedesktop.DBus.Properties",
+ "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
+
+ for (const auto& interface : interfaces2)
+ {
+ if (interface == "xyz.openbmc_project.Common.UUID")
+ {
+ getChassisUUID(asyncResp, connectionName, path);
+ }
+ else if (interface ==
+ "xyz.openbmc_project.Inventory.Decorator.LocationCode")
+ {
+ getChassisLocationCode(asyncResp, connectionName, path);
+ }
+ }
+
+ return;
+ }
+
+ // Couldn't find an object with that name. return an error
+ messages::resourceNotFound(asyncResp->res, "#Chassis.v1_16_0.Chassis",
+ chassisId);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0, interfaces);
+
+ getPhysicalSecurityData(asyncResp);
+}
+
+inline void
+ handleChassisPatch(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ std::optional<bool> locationIndicatorActive;
+ std::optional<std::string> indicatorLed;
+
+ if (param.empty())
+ {
+ return;
+ }
+
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "LocationIndicatorActive",
+ locationIndicatorActive, "IndicatorLED", indicatorLed))
+ {
+ return;
+ }
+
+ // TODO (Gunnar): Remove IndicatorLED after enough time has passed
+ if (!locationIndicatorActive && !indicatorLed)
+ {
+ return; // delete this when we support more patch properties
+ }
+ if (indicatorLed)
+ {
+ asyncResp->res.addHeader(
+ boost::beast::http::field::warning,
+ "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
+ }
+
+ const std::array<const char*, 2> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+
+ const std::string& chassisId = param;
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, chassisId, locationIndicatorActive,
+ indicatorLed](const boost::system::error_code ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::vector<std::string>>>>&
+ object : subtree)
+ {
+ const std::string& path = object.first;
+ const std::vector<std::pair<std::string, std::vector<std::string>>>&
+ connectionNames = object.second;
+
+ sdbusplus::message::object_path objPath(path);
+ if (objPath.filename() != chassisId)
+ {
+ continue;
+ }
+
+ if (connectionNames.empty())
+ {
+ BMCWEB_LOG_ERROR << "Got 0 Connection names";
+ continue;
+ }
+
+ const std::vector<std::string>& interfaces3 =
+ connectionNames[0].second;
+
+ const std::array<const char*, 2> hasIndicatorLed = {
+ "xyz.openbmc_project.Inventory.Item.Panel",
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
+ bool indicatorChassis = false;
+ for (const char* interface : hasIndicatorLed)
+ {
+ if (std::find(interfaces3.begin(), interfaces3.end(),
+ interface) != interfaces3.end())
+ {
+ indicatorChassis = true;
+ break;
+ }
+ }
+ if (locationIndicatorActive)
+ {
+ if (indicatorChassis)
+ {
+ setLocationIndicatorActive(asyncResp,
+ *locationIndicatorActive);
+ }
+ else
+ {
+ messages::propertyUnknown(asyncResp->res,
+ "LocationIndicatorActive");
+ }
+ }
+ if (indicatorLed)
+ {
+ if (indicatorChassis)
+ {
+ setIndicatorLedState(asyncResp, *indicatorLed);
+ }
+ else
+ {
+ messages::propertyUnknown(asyncResp->res, "IndicatorLED");
+ }
+ }
+ return;
+ }
+
+ messages::resourceNotFound(asyncResp->res, "#Chassis.v1_14_0.Chassis",
+ chassisId);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0, interfaces);
+}
+
/**
* Chassis override class for delivering Chassis Schema
* Functions triggers appropriate requests on DBus
@@ -208,370 +570,12 @@
BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
.privileges(redfish::privileges::getChassis)
.methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- const std::array<const char*, 2> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"};
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- // Iterate over all retrieved ObjectPaths.
- for (const std::pair<std::string,
- std::vector<std::pair<
- std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- const std::string& path = object.first;
- const std::vector<
- std::pair<std::string, std::vector<std::string>>>&
- connectionNames = object.second;
-
- sdbusplus::message::object_path objPath(path);
- if (objPath.filename() != chassisId)
- {
- continue;
- }
-
- auto health = std::make_shared<HealthPopulate>(asyncResp);
-
- sdbusplus::asio::getProperty<std::vector<std::string>>(
- *crow::connections::systemBus,
- "xyz.openbmc_project.ObjectMapper", path + "/all_sensors",
- "xyz.openbmc_project.Association", "endpoints",
- [health](const boost::system::error_code ec2,
- const std::vector<std::string>& resp) {
- if (ec2)
- {
- return; // no sensors = no failures
- }
- health->inventory = resp;
- });
-
- health->populate();
-
- if (connectionNames.empty())
- {
- BMCWEB_LOG_ERROR << "Got 0 Connection names";
- continue;
- }
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#Chassis.v1_16_0.Chassis";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId;
- asyncResp->res.jsonValue["Name"] = "Chassis Collection";
- asyncResp->res.jsonValue["ChassisType"] = "RackMount";
- asyncResp->res
- .jsonValue["Actions"]["#Chassis.Reset"]["target"] =
- "/redfish/v1/Chassis/" + chassisId +
- "/Actions/Chassis.Reset";
- asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]
- ["@Redfish.ActionInfo"] =
- "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
- asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
- "/redfish/v1/Systems/system/PCIeDevices";
-
- sdbusplus::asio::getProperty<std::vector<std::string>>(
- *crow::connections::systemBus,
- "xyz.openbmc_project.ObjectMapper", path + "/drive",
- "xyz.openbmc_project.Association", "endpoints",
- [asyncResp,
- chassisId](const boost::system::error_code ec3,
- const std::vector<std::string>& resp) {
- if (ec3 || resp.empty())
- {
- return; // no drives = no failures
- }
-
- nlohmann::json reference;
- reference["odata.id"] = crow::utility::urlFromPieces(
- "redfish", "v1", "Chassis", chassisId, "Drives");
- asyncResp->res.jsonValue["Drives"] = std::move(reference);
- });
-
- const std::string& connectionName = connectionNames[0].first;
-
- const std::vector<std::string>& interfaces2 =
- connectionNames[0].second;
- const std::array<const char*, 2> hasIndicatorLed = {
- "xyz.openbmc_project.Inventory.Item.Panel",
- "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
-
- const std::string assetTagInterface =
- "xyz.openbmc_project.Inventory.Decorator.AssetTag";
- if (std::find(interfaces2.begin(), interfaces2.end(),
- assetTagInterface) != interfaces2.end())
- {
- sdbusplus::asio::getProperty<std::string>(
- *crow::connections::systemBus, connectionName, path,
- assetTagInterface, "AssetTag",
- [asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code ec2,
- const std::string& property) {
- if (ec2)
- {
- BMCWEB_LOG_DEBUG
- << "DBus response error for AssetTag";
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["AssetTag"] = property;
- });
- }
-
- for (const char* interface : hasIndicatorLed)
- {
- if (std::find(interfaces2.begin(), interfaces2.end(),
- interface) != interfaces2.end())
- {
- getIndicatorLedState(asyncResp);
- getLocationIndicatorActive(asyncResp);
- break;
- }
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code /*ec2*/,
- const dbus::utility::DBusPropertiesMap&
- propertiesList) {
- for (const std::pair<std::string,
- dbus::utility::DbusVariantType>&
- property : propertiesList)
- {
- // Store DBus properties that are also
- // Redfish properties with same name and a
- // string value
- const std::string& propertyName = property.first;
- if ((propertyName == "PartNumber") ||
- (propertyName == "SerialNumber") ||
- (propertyName == "Manufacturer") ||
- (propertyName == "Model") ||
- (propertyName == "SparePartNumber"))
- {
- const std::string* value =
- std::get_if<std::string>(&property.second);
- if (value == nullptr)
- {
- BMCWEB_LOG_ERROR << "Null value returned for "
- << propertyName;
- messages::internalError(asyncResp->res);
- return;
- }
- // SparePartNumber is optional on D-Bus
- // so skip if it is empty
- if (propertyName == "SparePartNumber")
- {
- if (value->empty())
- {
- continue;
- }
- }
- asyncResp->res.jsonValue[propertyName] = *value;
- }
- }
- asyncResp->res.jsonValue["Name"] = chassisId;
- asyncResp->res.jsonValue["Id"] = chassisId;
-#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
- asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId + "/Thermal";
- // Power object
- asyncResp->res.jsonValue["Power"]["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId + "/Power";
-#endif
- // SensorCollection
- asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId + "/Sensors";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
-
- nlohmann::json::array_t computerSystems;
- nlohmann::json::object_t system;
- system["@odata.id"] = "/redfish/v1/Systems/system";
- computerSystems.push_back(std::move(system));
- asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
- std::move(computerSystems);
-
- nlohmann::json::array_t managedBy;
- nlohmann::json::object_t manager;
- manager["@odata.id"] = "/redfish/v1/Managers/bmc";
- managedBy.push_back(std::move(manager));
- asyncResp->res.jsonValue["Links"]["ManagedBy"] =
- std::move(managedBy);
- getChassisState(asyncResp);
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
-
- for (const auto& interface : interfaces2)
- {
- if (interface == "xyz.openbmc_project.Common.UUID")
- {
- getChassisUUID(asyncResp, connectionName, path);
- }
- else if (
- interface ==
- "xyz.openbmc_project.Inventory.Decorator.LocationCode")
- {
- getChassisLocationCode(asyncResp, connectionName, path);
- }
- }
-
- return;
- }
-
- // Couldn't find an object with that name. return an error
- messages::resourceNotFound(asyncResp->res,
- "#Chassis.v1_16_0.Chassis", chassisId);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", 0, interfaces);
-
- getPhysicalSecurityData(asyncResp);
- });
+ std::bind_front(handleChassisGet, std::ref(app)));
BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
.privileges(redfish::privileges::patchChassis)
.methods(boost::beast::http::verb::patch)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- std::optional<bool> locationIndicatorActive;
- std::optional<std::string> indicatorLed;
-
- if (param.empty())
- {
- return;
- }
-
- if (!json_util::readJsonPatch(
- req, asyncResp->res, "LocationIndicatorActive",
- locationIndicatorActive, "IndicatorLED", indicatorLed))
- {
- return;
- }
-
- // TODO (Gunnar): Remove IndicatorLED after enough time has passed
- if (!locationIndicatorActive && !indicatorLed)
- {
- return; // delete this when we support more patch properties
- }
- if (indicatorLed)
- {
- asyncResp->res.addHeader(
- boost::beast::http::field::warning,
- "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
- }
-
- const std::array<const char*, 2> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"};
-
- const std::string& chassisId = param;
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
- const boost::system::error_code ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Iterate over all retrieved ObjectPaths.
- for (const std::pair<std::string,
- std::vector<std::pair<
- std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- const std::string& path = object.first;
- const std::vector<
- std::pair<std::string, std::vector<std::string>>>&
- connectionNames = object.second;
-
- sdbusplus::message::object_path objPath(path);
- if (objPath.filename() != chassisId)
- {
- continue;
- }
-
- if (connectionNames.empty())
- {
- BMCWEB_LOG_ERROR << "Got 0 Connection names";
- continue;
- }
-
- const std::vector<std::string>& interfaces3 =
- connectionNames[0].second;
-
- const std::array<const char*, 2> hasIndicatorLed = {
- "xyz.openbmc_project.Inventory.Item.Panel",
- "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
- bool indicatorChassis = false;
- for (const char* interface : hasIndicatorLed)
- {
- if (std::find(interfaces3.begin(), interfaces3.end(),
- interface) != interfaces3.end())
- {
- indicatorChassis = true;
- break;
- }
- }
- if (locationIndicatorActive)
- {
- if (indicatorChassis)
- {
- setLocationIndicatorActive(asyncResp,
- *locationIndicatorActive);
- }
- else
- {
- messages::propertyUnknown(asyncResp->res,
- "LocationIndicatorActive");
- }
- }
- if (indicatorLed)
- {
- if (indicatorChassis)
- {
- setIndicatorLedState(asyncResp, *indicatorLed);
- }
- else
- {
- messages::propertyUnknown(asyncResp->res,
- "IndicatorLED");
- }
- }
- return;
- }
-
- messages::resourceNotFound(asyncResp->res,
- "#Chassis.v1_14_0.Chassis", chassisId);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", 0, interfaces);
- });
+ std::bind_front(handleChassisPatch, std::ref(app)));
}
inline void
@@ -633,6 +637,36 @@
busName, path, interface, method, "/", 0, interfaces);
}
+inline void handleChassisResetActionInfoPost(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& /*chassisId*/)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
+
+ std::string resetType;
+
+ if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
+ {
+ return;
+ }
+
+ if (resetType != "PowerCycle")
+ {
+ BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
+ << resetType;
+ messages::actionParameterNotSupported(asyncResp->res, resetType,
+ "ResetType");
+
+ return;
+ }
+ doChassisPowerCycle(asyncResp);
+}
+
/**
* ChassisResetAction class supports the POST method for the Reset
* action.
@@ -645,34 +679,35 @@
BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
.privileges(redfish::privileges::postChassis)
.methods(boost::beast::http::verb::post)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string&) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
+ std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
+}
- std::string resetType;
+inline void handleChassisResetActionInfoGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
+ asyncResp->res.jsonValue["Name"] = "Reset Action Info";
- if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
- resetType))
- {
- return;
- }
+ asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
+ nlohmann::json::array_t parameters;
+ nlohmann::json::object_t parameter;
+ parameter["Name"] = "ResetType";
+ parameter["Required"] = true;
+ parameter["DataType"] = "String";
+ nlohmann::json::array_t allowed;
+ allowed.push_back("PowerCycle");
+ parameter["AllowableValues"] = std::move(allowed);
+ parameters.push_back(std::move(parameter));
- if (resetType != "PowerCycle")
- {
- BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
- << resetType;
- messages::actionParameterNotSupported(asyncResp->res, resetType,
- "ResetType");
-
- return;
- }
- doChassisPowerCycle(asyncResp);
- });
+ asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
}
/**
@@ -684,32 +719,7 @@
BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
.privileges(redfish::privileges::getActionInfo)
.methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#ActionInfo.v1_1_2.ActionInfo";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
- asyncResp->res.jsonValue["Name"] = "Reset Action Info";
-
- asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
- nlohmann::json::array_t parameters;
- nlohmann::json::object_t parameter;
- parameter["Name"] = "ResetType";
- parameter["Required"] = true;
- parameter["DataType"] = "String";
- nlohmann::json::array_t allowed;
- allowed.push_back("PowerCycle");
- parameter["AllowableValues"] = std::move(allowed);
- parameters.push_back(std::move(parameter));
-
- asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
- });
+ std::bind_front(handleChassisResetActionInfoGet, std::ref(app)));
}
} // namespace redfish
diff --git a/redfish-core/lib/chassis_test.cpp b/redfish-core/lib/chassis_test.cpp
new file mode 100644
index 0000000..a043859
--- /dev/null
+++ b/redfish-core/lib/chassis_test.cpp
@@ -0,0 +1,60 @@
+#include "app.hpp"
+#include "async_resp.hpp"
+#include "chassis.hpp"
+#include "http_request.hpp"
+#include "http_response.hpp"
+
+#include <boost/beast/core/string_type.hpp>
+#include <boost/beast/http/message.hpp>
+#include <nlohmann/json.hpp>
+
+#include <system_error>
+
+#include <gtest/gtest.h>
+
+namespace redfish
+{
+namespace
+{
+
+void assertChassisResetActionInfoGet(const std::string& chassisId,
+ crow::Response& res)
+{
+ EXPECT_EQ(res.jsonValue["@odata.type"], "#ActionInfo.v1_1_2.ActionInfo");
+ EXPECT_EQ(res.jsonValue["@odata.id"],
+ "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo");
+ EXPECT_EQ(res.jsonValue["Name"], "Reset Action Info");
+
+ EXPECT_EQ(res.jsonValue["Id"], "ResetActionInfo");
+
+ nlohmann::json::array_t parameters;
+ nlohmann::json::object_t parameter;
+ parameter["Name"] = "ResetType";
+ parameter["Required"] = true;
+ parameter["DataType"] = "String";
+ nlohmann::json::array_t allowed;
+ allowed.push_back("PowerCycle");
+ parameter["AllowableValues"] = std::move(allowed);
+ parameters.push_back(std::move(parameter));
+
+ EXPECT_EQ(res.jsonValue["Parameters"], parameters);
+}
+
+TEST(HandleChassisResetActionInfoGet, StaticAttributesAreExpected)
+{
+
+ auto response = std::make_shared<bmcweb::AsyncResp>();
+ std::error_code err;
+ crow::Request request{{boost::beast::http::verb::get, "/whatever", 11},
+ err};
+
+ std::string fakeChassis = "fakeChassis";
+ response->res.setCompleteRequestHandler(
+ std::bind_front(assertChassisResetActionInfoGet, fakeChassis));
+
+ crow::App app;
+ handleChassisResetActionInfoGet(app, request, response, fakeChassis);
+}
+
+} // namespace
+} // namespace redfish
\ No newline at end of file
diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp
index e050594..04d6ceb 100644
--- a/redfish-core/lib/redfish_util.hpp
+++ b/redfish-core/lib/redfish_util.hpp
@@ -17,6 +17,10 @@
#ifndef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
#include <dbus_utility.hpp>
+#include <sdbusplus/asio/property.hpp>
+
+#include <charconv>
+
namespace redfish
{