blob: a2d0277407ddefafc235432d61dfd726da6e0717 [file] [log] [blame]
#pragma once
#include "bmcweb_config.h"
#include "error_messages.hpp"
#include "managed_store_types.hpp"
// TODO(wltu): Move to a different file until this is fully cleaned up.
#include <sdbusplus/asio/property.hpp>
#include "managed_store.hpp"
#include "utility.hpp"
#include "utils/dbus_utils.hpp"
#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif
namespace redfish
{
inline static void
getRelatedItemsDrive(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
const sdbusplus::message::object_path& objPath)
{
// Drive is expected to be under a Chassis
constexpr std::array<std::string_view, 2> interfaces = {
"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis"};
managedStore::ManagedObjectStoreContext requestContext(aResp);
managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
objPath / "chassis",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
interfaces, requestContext,
[aResp, objPath](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
if (ec)
{
BMCWEB_LOG_DEBUG
<< "Failed to call getProperty for Drive -> Chassis Association: "
<< ec;
messages::internalError(aResp->res);
return;
}
if (chassisList.empty())
{
BMCWEB_LOG_DEBUG << "Can not find the Chassis containing the drive";
return;
}
if (chassisList.size() != 1)
{
BMCWEB_LOG_ERROR << "Resource can only be included in one storage";
messages::internalError(aResp->res);
return;
}
nlohmann::json::array_t relatedItems;
nlohmann::json::object_t relatedItem;
relatedItem["@odata.id"] = crow::utility::urlFromPieces(
"redfish", "v1", "Chassis",
sdbusplus::message::object_path(chassisList[0]).filename(),
"Drives", objPath.filename());
relatedItems.emplace_back(std::move(relatedItem));
aResp->res.jsonValue["RelatedItem@odata.count"] = relatedItems.size();
aResp->res.jsonValue["RelatedItem"] = std::move(relatedItems);
});
}
inline static void getRelatedItemsStorageController(
const std::shared_ptr<bmcweb::AsyncResp>& aResp,
const sdbusplus::message::object_path& objPath)
{
constexpr std::array<std::string_view, 1> interfaces = {
"xyz.openbmc_project.Inventory.Item.Storage"};
managedStore::ManagedObjectStoreContext requestContext(aResp);
managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
objPath / "storage",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
interfaces, requestContext,
[aResp, objPath,
requestContext](const boost::system::error_code ec,
const std::vector<std::string>& storageList) {
if (ec)
{
BMCWEB_LOG_DEBUG
<< "Failed to call getProperty for Storage Association: " << ec;
return;
}
if (storageList.size() != 1)
{
BMCWEB_LOG_ERROR << "Resource can only be included in one storage";
messages::internalError(aResp->res);
return;
}
sdbusplus::message::object_path storage(storageList[0]);
constexpr std::array<std::string_view, 1> storageControllerInterfaces =
{"xyz.openbmc_project.Inventory.Item.StorageController"};
managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
storage / "storage_controller",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory"),
0, storageControllerInterfaces, requestContext,
[aResp, storage,
objPath](const boost::system::error_code ec2,
const std::vector<std::string>& storageControllerList) {
if (ec2)
{
BMCWEB_LOG_DEBUG
<< "Failed to call getProperty for Storage -> StorageController Association: "
<< ec2;
return;
}
for (const std::string& storageController : storageControllerList)
{
const std::string& id =
sdbusplus::message::object_path(storageController)
.filename();
if (id.empty())
{
BMCWEB_LOG_ERROR << "filename() is empty in "
<< storageController;
continue;
}
if (storageController != objPath.str)
{
continue;
}
nlohmann::json::array_t relatedItems;
nlohmann::json::object_t relatedItem;
relatedItem["@odata.id"] = crow::utility::urlFromPieces(
"redfish", "v1", "Systems", "system", "Storage",
storage.filename(), "Controllers", id);
relatedItems.emplace_back(std::move(relatedItem));
aResp->res.jsonValue["RelatedItem@odata.count"] =
relatedItems.size();
aResp->res.jsonValue["RelatedItem"] = std::move(relatedItems);
break;
}
});
});
}
inline static void
getRelatedItemsOther(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
const sdbusplus::message::object_path& association)
{
constexpr std::array<std::string_view, 6> inventoryInterfaces = {
"xyz.openbmc_project.Inventory.Item.Accelerator",
"xyz.openbmc_project.Inventory.Item.Cpu",
"xyz.openbmc_project.Inventory.Item.Drive",
"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis",
"xyz.openbmc_project.Inventory.Item.StorageController"};
// Find supported device types.
managedStore::ManagedObjectStoreContext context(aResp);
managedStore::GetManagedObjectStore()->getDbusObject(
association.str, inventoryInterfaces, context,
[aResp, association](
const boost::system::error_code ec,
const std::vector<std::pair<std::string, std::vector<std::string>>>&
objects) {
if (ec)
{
BMCWEB_LOG_ERROR << "error_code = " << ec
<< ", error msg = " << ec.message();
return;
}
if (objects.empty())
{
return;
}
nlohmann::json& relatedItem = aResp->res.jsonValue["RelatedItem"];
nlohmann::json& relatedItemCount =
aResp->res.jsonValue["RelatedItem@odata.count"];
for (const std::pair<std::string, std::vector<std::string>>& object :
objects)
{
for (const std::string& interfaces : object.second)
{
if (interfaces == "xyz.openbmc_project.Inventory.Item.Drive")
{
getRelatedItemsDrive(aResp, association);
}
if (interfaces ==
"xyz.openbmc_project.Inventory.Item.Accelerator" ||
interfaces == "xyz.openbmc_project.Inventory.Item.Cpu")
{
relatedItem.emplace_back(
nlohmann::json({{"@odata.id",
"/redfish/v1/Systems/system/Processors/" +
association.filename()}}));
}
if (interfaces == "xyz.openbmc_project.Inventory.Item.Board" ||
interfaces == "xyz.openbmc_project.Inventory.Item.Chassis")
{
relatedItem.emplace_back(
nlohmann::json({{"@odata.id",
"/redfish/v1/Chassis/" + association.filename()}}));
}
if (interfaces == "xyz.openbmc_project.Inventory."
"Item.StorageController")
{
getRelatedItemsStorageController(aResp, association);
}
}
}
relatedItemCount = relatedItem.size();
});
}
/*
Fill related item links for Software with other purposes.
Use other purpose for device level softwares.
*/
inline static void
getRelatedItemsOthers(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
std::string_view path)
{
BMCWEB_LOG_DEBUG << "getRelatedItemsOthers enter";
aResp->res.jsonValue["RelatedItem"] = nlohmann::json::array();
aResp->res.jsonValue["RelatedItem@odata.count"] = 0;
BMCWEB_LOG_DEBUG << "GetReltatedItemsOthers for " << std::string(path)
<< "/software_related";
managedStore::ManagedObjectStoreContext requestContext(aResp);
dbus_utils::getProperty<std::vector<std::string>>(
"xyz.openbmc_project.ObjectMapper",
std::string(path) + "/software_related",
"xyz.openbmc_project.Association", "endpoints", requestContext,
[aResp](const boost::system::error_code ec,
const std::vector<std::string>& relatedList) {
if (ec)
{
BMCWEB_LOG_DEBUG << "Failed to call dbus for getLogEntry";
return;
}
for (const auto& item : relatedList)
{
sdbusplus::message::object_path itemPath(item);
if (itemPath.filename().empty())
{
continue;
}
getRelatedItemsOther(aResp, itemPath);
}
});
}
} // namespace redfish