Introducing systems_utils.hpp and getSystemCollectionMembers
This change introduces a new a function similar to getCollectionMembers
but specific to computerSystem discovery.
Since more functionality will be added soon to support multi host
redfish and in general request handling with the long term goal not
using hardcoded URIs anymore, a new utility header for systems.hpp
is being introduced in this patch that will hold the rest of the
incoming definitions.
getSystemCollectionMembers supports multi-host platforms like
yosemite4. Currently we have to distinguish between single-
and multi-host platforms and handle both separate
from each other, thus cannot use the generic getCollectionMembers from
collection.hpp. However, this should change sometime in the future.
It should be mentioned, that functionalitywise the newly introduced
function shares almost all of the code used in getCollectionMembers from
collection.hpp. Only simplification has been done, since this function
only serves a single usecase.
In order to create the collection for a multi-host platform, the
collection handler looks for the ManagedHost dbus interface via the
ObjectMapper and adds everything it gets from a getSubTree call
to the collection.
Single-host systems do not populate this interface, so an empty result
from the ObjectMapper is treated as the request came from a single-host
system.
Testing: Full redfish service validator has been ran on a
romulus image with and without the changes, representative for a
single-host system. No regression has been observed.
A yosemite4 image has been validated constraining the validator
to only check the collection url without following sub uris.
Validation also succeeded.
In addition, the collection url has been curled manually on both
images to check the correct members are added to the collection.
curl -w "@curl-format.txt" -c cjar -b cjar -k -X GET \
'https://'"${BMC}"':4443/redfish/v1/Systems \
-H 'X-Auth-Token: '"$BMCWEB_SESSION_TOKEN"''
romulus output:
{
"@odata.id": "/redfish/v1/Systems",
"@odata.type": "#ComputerSystemCollection.ComputerSystemCollection",
"Members": [
{
"@odata.id": "/redfish/v1/Systems/system"
}
],
"Members@odata.count": 1,
"Name": "Computer System Collection"
}
yosemite4 output:
{
"@odata.id": "/redfish/v1/Systems",
"@odata.type": "#ComputerSystemCollection.ComputerSystemCollection",
"Members": [
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_1_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_2_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_3_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_4_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_5_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_6_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_7_Chassis"
},
{
"@odata.id":
"/redfish/v1/Systems/Yosemite_4_Sentinel_Dome_Slot_8_Chassis"
}
],
"Members@odata.count": 8,
"Name": "Computer System Collection"
}
Change-Id: I82d59487b7c17b22cd638acd8f687f31c96ca156
Signed-off-by: Oliver Brewka <mox669.dev@gmail.com>
diff --git a/redfish-core/include/utils/systems_utils.hpp b/redfish-core/include/utils/systems_utils.hpp
new file mode 100644
index 0000000..5eec0b2
--- /dev/null
+++ b/redfish-core/include/utils/systems_utils.hpp
@@ -0,0 +1,118 @@
+#pragma once
+
+#include "bmcweb_config.h"
+
+#include "async_resp.hpp"
+#include "dbus_utility.hpp"
+#include "error_messages.hpp"
+#include "human_sort.hpp"
+#include "logging.hpp"
+#include "utility.hpp"
+
+#include <boost/url/format.hpp>
+#include <boost/url/url.hpp>
+#include <sdbusplus/message/native_types.hpp>
+
+#include <algorithm>
+#include <array>
+#include <functional>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace redfish
+{
+
+inline void handleSystemCollectionMembers(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse& objects)
+{
+ if (ec == boost::system::errc::io_error)
+ {
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+ return;
+ }
+
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json& membersArray = asyncResp->res.jsonValue["Members"];
+ membersArray = nlohmann::json::array();
+
+ // consider an empty result as single-host, since single-host systems
+ // do not populate the ManagedHost dbus interface
+ if (objects.empty())
+ {
+ asyncResp->res.jsonValue["Members@odata.count"] = 1;
+ nlohmann::json::object_t system;
+ system["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ membersArray.emplace_back(std::move(system));
+
+ if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
+ {
+ BMCWEB_LOG_DEBUG("Hypervisor is available");
+ asyncResp->res.jsonValue["Members@odata.count"] = 2;
+
+ nlohmann::json::object_t hypervisor;
+ hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
+ membersArray.emplace_back(std::move(hypervisor));
+ }
+
+ return;
+ }
+
+ std::vector<std::string> pathNames;
+ for (const auto& object : objects)
+ {
+ sdbusplus::message::object_path path(object);
+ std::string leaf = path.filename();
+ if (leaf.empty())
+ {
+ continue;
+ }
+ pathNames.emplace_back(leaf);
+ }
+ std::ranges::sort(pathNames, AlphanumLess<std::string>());
+
+ for (const std::string& systemName : pathNames)
+ {
+ boost::urls::url url("/redfish/v1/Systems");
+ crow::utility::appendUrlPieces(url, systemName);
+ nlohmann::json::object_t member;
+ member["@odata.id"] = std::move(url);
+ membersArray.emplace_back(std::move(member));
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = membersArray.size();
+}
+
+/**
+ * @brief Populate the system collection members from a GetSubTreePaths search
+ * of the inventory based of the ManagedHost dbus interface
+ *
+ * @param[i] asyncResp Async response object
+ *
+ * @return None
+ */
+inline void getSystemCollectionMembers(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ constexpr std::array<std::string_view, 1> interfaces{
+ "xyz.openbmc_project.Inventory.Decorator.ManagedHost",
+ };
+
+ BMCWEB_LOG_DEBUG("Get system collection members for /redfish/v1/Systems");
+
+ dbus::utility::getSubTreePaths(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ std::bind_front(handleSystemCollectionMembers, asyncResp));
+}
+} // namespace redfish
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index d7aeed9..0301110 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -25,6 +25,7 @@
#include "utils/json_utils.hpp"
#include "utils/pcie_util.hpp"
#include "utils/sw_utils.hpp"
+#include "utils/systems_utils.hpp"
#include "utils/time_utils.hpp"
#include <asm-generic/errno.h>
@@ -2807,29 +2808,7 @@
asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
asyncResp->res.jsonValue["Name"] = "Computer System Collection";
- nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
- ifaceArray = nlohmann::json::array();
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
- // Option currently returns no systems. TBD
- return;
- }
- asyncResp->res.jsonValue["Members@odata.count"] = 1;
- nlohmann::json::object_t system;
- system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- ifaceArray.emplace_back(std::move(system));
-
- if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
- {
- BMCWEB_LOG_DEBUG("Hypervisor is available");
- asyncResp->res.jsonValue["Members@odata.count"] = 2;
-
- nlohmann::json::object_t hypervisor;
- hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
- ifaceArray.emplace_back(std::move(hypervisor));
- }
+ getSystemCollectionMembers(asyncResp);
}
/**