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