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