1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #pragma once 4 5 #include "bmcweb_config.h" 6 7 #include "async_resp.hpp" 8 #include "dbus_utility.hpp" 9 #include "error_messages.hpp" 10 #include "human_sort.hpp" 11 #include "logging.hpp" 12 #include "utility.hpp" 13 14 #include <boost/url/format.hpp> 15 #include <boost/url/url.hpp> 16 #include <sdbusplus/message/native_types.hpp> 17 18 #include <algorithm> 19 #include <array> 20 #include <functional> 21 #include <memory> 22 #include <string> 23 #include <string_view> 24 #include <utility> 25 #include <vector> 26 27 namespace redfish 28 { 29 30 inline void handleSystemCollectionMembers( 31 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 32 const boost::system::error_code& ec, 33 const dbus::utility::MapperGetSubTreePathsResponse& objects) 34 { 35 if (ec == boost::system::errc::io_error) 36 { 37 asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 38 asyncResp->res.jsonValue["Members@odata.count"] = 0; 39 return; 40 } 41 42 if (ec) 43 { 44 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value()); 45 messages::internalError(asyncResp->res); 46 return; 47 } 48 49 nlohmann::json& membersArray = asyncResp->res.jsonValue["Members"]; 50 membersArray = nlohmann::json::array(); 51 52 // consider an empty result as single-host, since single-host systems 53 // do not populate the ManagedHost dbus interface 54 if (objects.empty()) 55 { 56 asyncResp->res.jsonValue["Members@odata.count"] = 1; 57 nlohmann::json::object_t system; 58 system["@odata.id"] = boost::urls::format( 59 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME); 60 membersArray.emplace_back(std::move(system)); 61 62 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM) 63 { 64 BMCWEB_LOG_DEBUG("Hypervisor is available"); 65 asyncResp->res.jsonValue["Members@odata.count"] = 2; 66 67 nlohmann::json::object_t hypervisor; 68 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor"; 69 membersArray.emplace_back(std::move(hypervisor)); 70 } 71 72 return; 73 } 74 75 std::vector<std::string> pathNames; 76 for (const auto& object : objects) 77 { 78 sdbusplus::message::object_path path(object); 79 std::string leaf = path.filename(); 80 if (leaf.empty()) 81 { 82 continue; 83 } 84 pathNames.emplace_back(leaf); 85 } 86 std::ranges::sort(pathNames, AlphanumLess<std::string>()); 87 88 for (const std::string& systemName : pathNames) 89 { 90 nlohmann::json::object_t member; 91 member["@odata.id"] = 92 boost::urls::format("/redfish/v1/Systems/{}", systemName); 93 membersArray.emplace_back(std::move(member)); 94 } 95 asyncResp->res.jsonValue["Members@odata.count"] = membersArray.size(); 96 } 97 98 /** 99 * @brief Populate the system collection members from a GetSubTreePaths search 100 * of the inventory based of the ManagedHost dbus interface 101 * 102 * @param[i] asyncResp Async response object 103 * 104 * @return None 105 */ 106 inline void getSystemCollectionMembers( 107 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 108 { 109 constexpr std::array<std::string_view, 1> interfaces{ 110 "xyz.openbmc_project.Inventory.Decorator.ManagedHost", 111 }; 112 113 BMCWEB_LOG_DEBUG("Get system collection members for /redfish/v1/Systems"); 114 115 dbus::utility::getSubTreePaths( 116 "/xyz/openbmc_project/inventory", 0, interfaces, 117 std::bind_front(handleSystemCollectionMembers, asyncResp)); 118 } 119 } // namespace redfish 120