xref: /openbmc/bmcweb/features/redfish/include/utils/collection.hpp (revision 7a1dbc4803bf78bfc0c574e6676b3c5def4cdae3)
1 #pragma once
2 
3 #include "dbus_utility.hpp"
4 
5 #include <human_sort.hpp>
6 
7 #include <span>
8 #include <string>
9 #include <string_view>
10 #include <vector>
11 
12 namespace redfish
13 {
14 namespace collection_util
15 {
16 
17 /**
18  * @brief Populate the collection "Members" from a GetSubTreePaths search of
19  *        inventory
20  *
21  * @param[i,o] aResp  Async response object
22  * @param[i]   collectionPath  Redfish collection path which is used for the
23  *             Members Redfish Path
24  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
25  * @param[in]  subtree     D-Bus base path to constrain search to.
26  *
27  * @return void
28  */
29 inline void
30     getCollectionMembers(std::shared_ptr<bmcweb::AsyncResp> aResp,
31                          const boost::urls::url& collectionPath,
32                          std::span<const std::string_view> interfaces,
33                          const char* subtree = "/xyz/openbmc_project/inventory")
34 {
35     BMCWEB_LOG_DEBUG << "Get collection members for: "
36                      << collectionPath.buffer();
37     dbus::utility::getSubTreePaths(
38         subtree, 0, interfaces,
39         [collectionPath, aResp{std::move(aResp)}](
40             const boost::system::error_code& ec,
41             const dbus::utility::MapperGetSubTreePathsResponse& objects) {
42         if (ec == boost::system::errc::io_error)
43         {
44             aResp->res.jsonValue["Members"] = nlohmann::json::array();
45             aResp->res.jsonValue["Members@odata.count"] = 0;
46             return;
47         }
48 
49         if (ec)
50         {
51             BMCWEB_LOG_DEBUG << "DBUS response error " << ec.value();
52             messages::internalError(aResp->res);
53             return;
54         }
55 
56         std::vector<std::string> pathNames;
57         for (const auto& object : objects)
58         {
59             sdbusplus::message::object_path path(object);
60             std::string leaf = path.filename();
61             if (leaf.empty())
62             {
63                 continue;
64             }
65             pathNames.push_back(leaf);
66         }
67         std::sort(pathNames.begin(), pathNames.end(),
68                   AlphanumLess<std::string>());
69 
70         nlohmann::json& members = aResp->res.jsonValue["Members"];
71         members = nlohmann::json::array();
72         for (const std::string& leaf : pathNames)
73         {
74             boost::urls::url url = collectionPath;
75             crow::utility::appendUrlPieces(url, leaf);
76             nlohmann::json::object_t member;
77             member["@odata.id"] = std::move(url);
78             members.push_back(std::move(member));
79         }
80         aResp->res.jsonValue["Members@odata.count"] = members.size();
81         });
82 }
83 
84 } // namespace collection_util
85 } // namespace redfish
86