redfish: Add Chassis listing associated drive
If chassis has drives a drive url is added to the chassis, of the form:
redfish/v1/Chassis/<chassis>/Drives
When queried, the drive URL will list all drives associated with the
chassis. This is in accordance with the redfish schema.
Samples for the following URLs are below
wget -qO- http://localhost:80/redfish/v1/Chassis/DC_SCM/Drives
{
"@odata.id": "/redfish/v1/Chassis/DC_SCM/Drives",
"@odata.type": "#DriveCollection.DriveCollection",
"Members": [
{
"@odata.id": "/redfish/v1/Chassis/DC_SCM/Drives/mmcblk0"
}
],
"Members@odata.count": "1",
"Name": "Drive Collection"
}
Tested:
With the redfish validator: No new errors
Change-Id: Ibdbe7fee5014d6515a77683c8eaca9ca86b6b148
Signed-off-by: John Edward Broadbent <jebr@google.com>
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index 998ae60..a276be1 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -571,4 +571,121 @@
"xyz.openbmc_project.Inventory.Item.Drive"});
});
}
+
+/**
+ * Chassis drives, this URL will show all the DriveCollection
+ * information
+ */
+void chassisDriveCollectionGet(
+ crow::App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
+ {
+ return;
+ }
+
+ // mapper call lambda
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ chassisId](const boost::system::error_code ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ if (ec)
+ {
+ if (ec == boost::system::errc::host_unreachable)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis",
+ chassisId);
+ return;
+ }
+ 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 dbus::utility::MapperGetObject& 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;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#DriveCollection.DriveCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ crow::utility::urlFromPieces("redfish", "v1",
+ "Chassis" + chassisId + "Drives");
+ asyncResp->res.jsonValue["Name"] = "Drive Collection";
+
+ // Association lambda
+ 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)
+ {
+ BMCWEB_LOG_ERROR << "Error in chassis Drive association ";
+ }
+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
+ // important if array is empty
+ members = nlohmann::json::array();
+
+ std::vector<std::string> leafNames;
+ for (const auto& drive : resp)
+ {
+ sdbusplus::message::object_path path(drive);
+ leafNames.push_back(path.filename());
+ }
+
+ std::sort(leafNames.begin(), leafNames.end(),
+ AlphanumLess<std::string>());
+
+ for (const auto& leafName : leafNames)
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] = crow::utility::urlFromPieces(
+ "redfish", "v1", "Chassis", chassisId, "Drives",
+ leafName);
+ members.push_back(std::move(member));
+ // navigation links will be registered in next patch set
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = resp.size();
+ }); // end association lambda
+
+ } // end Iterate over all retrieved ObjectPaths
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0,
+ std::array<const char*, 2>{
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"});
+}
+
+inline void requestRoutesChassisDrive(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Drives/")
+ .privileges(redfish::privileges::getDriveCollection)
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(chassisDriveCollectionGet, std::ref(app)));
+}
+
} // namespace redfish