summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redfish-core/include/redfish.hpp2
-rw-r--r--redfish-core/lib/storage.hpp392
2 files changed, 245 insertions, 149 deletions
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 8e7b4116b1..5a51dc0333 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -111,6 +111,8 @@ class RedfishService
requestRoutesUpdateService(app);
requestRoutesStorageCollection(app);
requestRoutesStorage(app);
+ requestRoutesStorageControllerCollection(app);
+ requestRoutesStorageController(app);
requestRoutesDrive(app);
requestRoutesCable(app);
requestRoutesCableCollection(app);
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index 5ec6b5c80f..44b7746c7f 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -120,153 +120,6 @@ inline void getDrives(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
});
}
-inline void
- getStorageControllers(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::shared_ptr<HealthPopulate>& health)
-{
- constexpr std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.Inventory.Item.StorageController"};
- dbus::utility::getSubTree(
- "/xyz/openbmc_project/inventory", 0, interfaces,
- [asyncResp,
- health](const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec || subtree.empty())
- {
- // doesn't have to be there
- return;
- }
-
- nlohmann::json& root = asyncResp->res.jsonValue["StorageControllers"];
- root = nlohmann::json::array();
- for (const auto& [path, interfaceDict] : subtree)
- {
- sdbusplus::message::object_path object(path);
- std::string id = object.filename();
- if (id.empty())
- {
- BMCWEB_LOG_ERROR << "Failed to find filename in " << path;
- return;
- }
-
- if (interfaceDict.size() != 1)
- {
- BMCWEB_LOG_ERROR << "Connection size " << interfaceDict.size()
- << ", greater than 1";
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& connectionName = interfaceDict.front().first;
-
- size_t index = root.size();
- nlohmann::json& storageController =
- root.emplace_back(nlohmann::json::object());
-
- storageController["@odata.type"] =
- "#Storage.v1_7_0.StorageController";
- storageController["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/system/Storage/1#{}",
- ("/StorageControllers"_json_pointer / index).to_string());
- storageController["Name"] = id;
- storageController["MemberId"] = id;
- storageController["Status"]["State"] = "Enabled";
-
- sdbusplus::asio::getProperty<bool>(
- *crow::connections::systemBus, connectionName, path,
- "xyz.openbmc_project.Inventory.Item", "Present",
- [asyncResp, index](const boost::system::error_code& ec2,
- bool isPresent) {
- // this interface isn't necessary, only check it
- // if we get a good return
- if (ec2)
- {
- return;
- }
- if (!isPresent)
- {
- asyncResp->res.jsonValue["StorageControllers"][index]
- ["Status"]["State"] = "Absent";
- }
- });
-
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, connectionName, path,
- "xyz.openbmc_project.Inventory.Decorator.Asset",
- [asyncResp, index](
- const boost::system::error_code& ec2,
- const std::vector<
- std::pair<std::string, dbus::utility::DbusVariantType>>&
- propertiesList) {
- if (ec2)
- {
- // this interface isn't necessary
- return;
- }
-
- const std::string* partNumber = nullptr;
- const std::string* serialNumber = nullptr;
- const std::string* manufacturer = nullptr;
- const std::string* model = nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList,
- "PartNumber", partNumber, "SerialNumber", serialNumber,
- "Manufacturer", manufacturer, "Model", model);
-
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- nlohmann::json& controller =
- asyncResp->res.jsonValue["StorageControllers"][index];
-
- if (partNumber != nullptr)
- {
- controller["PartNumber"] = *partNumber;
- }
-
- if (serialNumber != nullptr)
- {
- controller["SerialNumber"] = *serialNumber;
- }
-
- if (manufacturer != nullptr)
- {
- controller["Manufacturer"] = *manufacturer;
- }
-
- if (model != nullptr)
- {
- controller["Model"] = *model;
- }
- });
- }
-
- if constexpr (bmcwebEnableHealthPopulate)
- {
- // this is done after we know the json array will no longer
- // be resized, as json::array uses vector underneath and we
- // need references to its members that won't change
- size_t count = 0;
- // Pointer based on |asyncResp->res.jsonValue|
- nlohmann::json::json_pointer rootPtr =
- "/StorageControllers"_json_pointer;
- for (const auto& [path, interfaceDict] : subtree)
- {
- auto subHealth = std::make_shared<HealthPopulate>(
- asyncResp, rootPtr / count / "Status");
- subHealth->inventory.emplace_back(path);
- health->inventory.emplace_back(path);
- health->children.emplace_back(subHealth);
- count++;
- }
- }
- });
-}
-
inline void requestRoutesStorage(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/")
@@ -278,7 +131,7 @@ inline void requestRoutesStorage(App& app)
{
return;
}
- asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage";
+ asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_13_0.Storage";
asyncResp->res.jsonValue["@odata.id"] =
"/redfish/v1/Systems/system/Storage/1";
asyncResp->res.jsonValue["Name"] = "Storage";
@@ -292,7 +145,8 @@ inline void requestRoutesStorage(App& app)
}
getDrives(asyncResp, health);
- getStorageControllers(asyncResp, health);
+ asyncResp->res.jsonValue["Controllers"]["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage/1/Controllers";
});
}
@@ -973,4 +827,244 @@ inline void requestRoutesChassisDriveName(App& app)
std::bind_front(handleChassisDriveGet, std::ref(app)));
}
+inline void getStorageControllerAsset(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec,
+ const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
+ propertiesList)
+{
+ if (ec)
+ {
+ // this interface isn't necessary
+ BMCWEB_LOG_DEBUG << "Failed to get StorageControllerAsset";
+ return;
+ }
+
+ const std::string* partNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* manufacturer = nullptr;
+ const std::string* model = nullptr;
+ if (!sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
+ partNumber, "SerialNumber", serialNumber, "Manufacturer",
+ manufacturer, "Model", model))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
+
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
+
+ if (manufacturer != nullptr)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+ }
+
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] = *model;
+ }
+}
+
+inline void populateStorageController(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& controllerId, const std::string& connectionName,
+ const std::string& path)
+{
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#StorageController.v1_6_0.StorageController";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/system/Storage/1/Controllers/{}", controllerId);
+ asyncResp->res.jsonValue["Name"] = controllerId;
+ asyncResp->res.jsonValue["Id"] = controllerId;
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+
+ sdbusplus::asio::getProperty<bool>(
+ *crow::connections::systemBus, connectionName, path,
+ "xyz.openbmc_project.Inventory.Item", "Present",
+ [asyncResp](const boost::system::error_code& ec, bool isPresent) {
+ // this interface isn't necessary, only check it
+ // if we get a good return
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "Failed to get Present property";
+ return;
+ }
+ if (!isPresent)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] = "Absent";
+ }
+ });
+
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, connectionName, path,
+ "xyz.openbmc_project.Inventory.Decorator.Asset",
+ [asyncResp](const boost::system::error_code& ec,
+ const std::vector<
+ std::pair<std::string, dbus::utility::DbusVariantType>>&
+ propertiesList) {
+ getStorageControllerAsset(asyncResp, ec, propertiesList);
+ });
+}
+
+inline void getStorageControllerHandler(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& controllerId, const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree)
+{
+ if (ec || subtree.empty())
+ {
+ // doesn't have to be there
+ BMCWEB_LOG_DEBUG << "Failed to handle StorageController";
+ return;
+ }
+
+ for (const auto& [path, interfaceDict] : subtree)
+ {
+ sdbusplus::message::object_path object(path);
+ std::string id = object.filename();
+ if (id.empty())
+ {
+ BMCWEB_LOG_ERROR << "Failed to find filename in " << path;
+ return;
+ }
+ if (id != controllerId)
+ {
+ continue;
+ }
+
+ if (interfaceDict.size() != 1)
+ {
+ BMCWEB_LOG_ERROR << "Connection size " << interfaceDict.size()
+ << ", greater than 1";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string& connectionName = interfaceDict.front().first;
+ populateStorageController(asyncResp, controllerId, connectionName,
+ path);
+ }
+}
+
+inline void populateStorageControllerCollection(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse& controllerList)
+{
+ nlohmann::json::array_t members;
+ if (ec || controllerList.empty())
+ {
+ asyncResp->res.jsonValue["Members"] = std::move(members);
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+ BMCWEB_LOG_DEBUG << "Failed to find any StorageController";
+ return;
+ }
+
+ for (const std::string& path : controllerList)
+ {
+ std::string id = sdbusplus::message::object_path(path).filename();
+ if (id.empty())
+ {
+ BMCWEB_LOG_ERROR << "Failed to find filename in " << path;
+ return;
+ }
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/system/Storage/1/Controllers/{}", id);
+ members.emplace_back(member);
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = members.size();
+ asyncResp->res.jsonValue["Members"] = std::move(members);
+}
+
+inline void storageControllerCollectionHandler(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ BMCWEB_LOG_DEBUG
+ << "Failed to setup Redfish Route for StorageController Collection";
+ return;
+ }
+ if (systemName != "system")
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ BMCWEB_LOG_DEBUG << "Failed to find ComputerSystem of " << systemName;
+ return;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#StorageControllerCollection.StorageControllerCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage/1/Controllers";
+ asyncResp->res.jsonValue["Name"] = "Storage Controller Collection";
+
+ constexpr std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.StorageController"};
+ dbus::utility::getSubTreePaths(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ [asyncResp](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse&
+ controllerList) {
+ populateStorageControllerCollection(asyncResp, ec, controllerList);
+ });
+}
+
+inline void storageControllerHandler(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& controllerId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ BMCWEB_LOG_DEBUG
+ << "Failed to setup Redfish Route for StorageController";
+ return;
+ }
+ if (systemName != "system")
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ BMCWEB_LOG_DEBUG << "Failed to find ComputerSystem of " << systemName;
+ return;
+ }
+ constexpr std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.StorageController"};
+ dbus::utility::getSubTree(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ [asyncResp,
+ controllerId](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ getStorageControllerHandler(asyncResp, controllerId, ec, subtree);
+ });
+}
+
+inline void requestRoutesStorageControllerCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Controllers/")
+ .privileges(redfish::privileges::getStorageControllerCollection)
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(storageControllerCollectionHandler, std::ref(app)));
+}
+
+inline void requestRoutesStorageController(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Controllers/<str>")
+ .privileges(redfish::privileges::getStorageController)
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(storageControllerHandler, std::ref(app)));
+}
+
} // namespace redfish