Dynamically determine ChassisType for Redfish
The function handleChassisGetSubTree will now handle properties that
are part of the xyz.openbmc_project.Inventory.Item.Chassis interface.
At time of development this is only ChassisType. The new function
"handleChassisProperties" will attempt to get the Type property from
the interface, translate it to a Redfish standard string and set it as
the ChassisType value. If the property cannot be found the default
"RackMount" will be used.
Tested: Added and ran 4 new unit tests. Ran manual tests with
ChassisType being exposed via dbus in QEMU emulated environments.
Tested on ASPEED 2600 eval board.
Change-Id: Ibbd048db5007f5154e88495ec6e651a3a2137b06
Signed-off-by: Joseph-Jonathan Salzano <joseph-jonathan.salzano@hp.com>
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index d5ca046..51effb6 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -35,12 +35,59 @@
#include <sdbusplus/unpack_properties.hpp>
#include <array>
+#include <memory>
#include <ranges>
#include <string_view>
namespace redfish
{
+inline chassis::ChassisType
+ translateChassisTypeToRedfish(const std::string_view& chassisType)
+{
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Blade")
+ {
+ return chassis::ChassisType::Blade;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Component")
+ {
+ return chassis::ChassisType::Component;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Enclosure")
+ {
+ return chassis::ChassisType::Enclosure;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Module")
+ {
+ return chassis::ChassisType::Module;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount")
+ {
+ return chassis::ChassisType::RackMount;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StandAlone")
+ {
+ return chassis::ChassisType::StandAlone;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StorageEnclosure")
+ {
+ return chassis::ChassisType::StorageEnclosure;
+ }
+ if (chassisType ==
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Zone")
+ {
+ return chassis::ChassisType::Zone;
+ }
+ return chassis::ChassisType::Invalid;
+}
+
/**
* @brief Retrieves resources over dbus to link to the chassis
*
@@ -463,6 +510,36 @@
getStorageLink(asyncResp, path);
}
+inline void handleChassisProperties(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const dbus::utility::DBusPropertiesMap& propertiesList)
+{
+ const std::string* type = nullptr;
+
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList, "Type", type);
+
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (type != nullptr)
+ {
+ auto chassisType = translateChassisTypeToRedfish(*type);
+ if (chassisType != chassis::ChassisType::Invalid)
+ {
+ asyncResp->res.jsonValue["ChassisType"] = chassisType;
+ }
+ }
+ else
+ {
+ asyncResp->res.jsonValue["ChassisType"] =
+ chassis::ChassisType::RackMount;
+ }
+}
+
inline void handleChassisGetSubTree(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& chassisId, const boost::system::error_code& ec,
@@ -502,8 +579,6 @@
asyncResp->res.jsonValue["@odata.id"] =
boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
asyncResp->res.jsonValue["Name"] = "Chassis Collection";
- asyncResp->res.jsonValue["ChassisType"] =
- chassis::ChassisType::RackMount;
asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset",
chassisId);
@@ -616,6 +691,15 @@
propertiesList);
});
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, connectionName, path,
+ "xyz.openbmc_project.Inventory.Item.Chassis",
+ [asyncResp](
+ const boost::system::error_code&,
+ const dbus::utility::DBusPropertiesMap& propertiesList) {
+ handleChassisProperties(asyncResp, propertiesList);
+ });
+
for (const auto& interface : interfaces2)
{
if (interface == "xyz.openbmc_project.Common.UUID")
diff --git a/test/redfish-core/lib/chassis_test.cpp b/test/redfish-core/lib/chassis_test.cpp
index 957b5eb..c6186cf 100644
--- a/test/redfish-core/lib/chassis_test.cpp
+++ b/test/redfish-core/lib/chassis_test.cpp
@@ -1,10 +1,13 @@
#include "app.hpp"
#include "async_resp.hpp"
#include "chassis.hpp"
+#include "dbus_utility.hpp"
+#include "generated/enums/chassis.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include <boost/beast/core/string_type.hpp>
+#include <boost/beast/http/status.hpp>
#include <boost/beast/http/verb.hpp>
#include <nlohmann/json.hpp>
@@ -59,5 +62,97 @@
handleChassisResetActionInfoGet(app, request, response, fakeChassis);
}
+TEST(TranslateChassisTypeToRedfish, TranslationsAreExpected)
+{
+ ASSERT_EQ(
+ chassis::ChassisType::Blade,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Blade"));
+ ASSERT_EQ(
+ chassis::ChassisType::Component,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Component"));
+ ASSERT_EQ(
+ chassis::ChassisType::Enclosure,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Enclosure"));
+ ASSERT_EQ(
+ chassis::ChassisType::Module,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Module"));
+ ASSERT_EQ(
+ chassis::ChassisType::RackMount,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount"));
+ ASSERT_EQ(
+ chassis::ChassisType::StandAlone,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StandAlone"));
+ ASSERT_EQ(
+ chassis::ChassisType::StorageEnclosure,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StorageEnclosure"));
+ ASSERT_EQ(
+ chassis::ChassisType::Zone,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Zone"));
+ ASSERT_EQ(
+ chassis::ChassisType::Invalid,
+ translateChassisTypeToRedfish(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Unknown"));
+}
+
+TEST(HandleChassisProperties, TypeFound)
+{
+ auto response = std::make_shared<bmcweb::AsyncResp>();
+ auto properties = dbus::utility::DBusPropertiesMap();
+ properties.emplace_back(
+ std::string("Type"),
+ dbus::utility::DbusVariantType(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount"));
+ handleChassisProperties(response, properties);
+ ASSERT_EQ("RackMount", response->res.jsonValue["ChassisType"]);
+
+ response = std::make_shared<bmcweb::AsyncResp>();
+ properties.clear();
+ properties.emplace_back(
+ std::string("Type"),
+ dbus::utility::DbusVariantType(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StandAlone"));
+ handleChassisProperties(response, properties);
+ ASSERT_EQ("StandAlone", response->res.jsonValue["ChassisType"]);
+}
+
+TEST(HandleChassisProperties, BadTypeFound)
+{
+ auto response = std::make_shared<bmcweb::AsyncResp>();
+ auto properties = dbus::utility::DBusPropertiesMap();
+ properties.emplace_back(
+ std::string("Type"),
+ dbus::utility::DbusVariantType(
+ "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Unknown"));
+ handleChassisProperties(response, properties);
+ ASSERT_FALSE(response->res.jsonValue.contains("ChassisType"));
+}
+
+TEST(HandleChassisProperties, FailToGetProperty)
+{
+ auto response = std::make_shared<bmcweb::AsyncResp>();
+ auto properties = dbus::utility::DBusPropertiesMap();
+ properties.emplace_back(std::string("Type"),
+ dbus::utility::DbusVariantType(123));
+ handleChassisProperties(response, properties);
+ ASSERT_EQ(boost::beast::http::status::internal_server_error,
+ response->res.result());
+}
+
+TEST(HandleChassisProperties, TypeNotFound)
+{
+ auto response = std::make_shared<bmcweb::AsyncResp>();
+ auto properties = dbus::utility::DBusPropertiesMap();
+ handleChassisProperties(response, properties);
+ ASSERT_EQ("RackMount", response->res.jsonValue["ChassisType"]);
+}
+
} // namespace
} // namespace redfish