1 #pragma once
2
3 #include "async_resp.hpp"
4 #include "dbus_utility.hpp"
5 #include "error_messages.hpp"
6 #include "http/utility.hpp"
7 #include "human_sort.hpp"
8
9 #include <boost/url/url.hpp>
10 #include <nlohmann/json.hpp>
11
12 #include <ranges>
13 #include <span>
14 #include <string>
15 #include <string_view>
16 #include <vector>
17
18 namespace redfish
19 {
20 namespace collection_util
21 {
22
handleCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,const nlohmann::json::json_pointer & jsonKeyName,const boost::system::error_code & ec,const dbus::utility::MapperGetSubTreePathsResponse & objects)23 inline void handleCollectionMembers(
24 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
25 const boost::urls::url& collectionPath,
26 const nlohmann::json::json_pointer& jsonKeyName,
27 const boost::system::error_code& ec,
28 const dbus::utility::MapperGetSubTreePathsResponse& objects)
29 {
30 if (jsonKeyName.empty())
31 {
32 messages::internalError(asyncResp->res);
33 BMCWEB_LOG_ERROR("Json Key called empty. Did you mean /Members?");
34 return;
35 }
36 nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName;
37 std::string back = jsonCountKeyName.back();
38 jsonCountKeyName.pop_back();
39 jsonCountKeyName /= back + "@odata.count";
40
41 if (ec == boost::system::errc::io_error)
42 {
43 asyncResp->res.jsonValue[jsonKeyName] = nlohmann::json::array();
44 asyncResp->res.jsonValue[jsonCountKeyName] = 0;
45 return;
46 }
47
48 if (ec)
49 {
50 BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
51 messages::internalError(asyncResp->res);
52 return;
53 }
54
55 std::vector<std::string> pathNames;
56 for (const auto& object : objects)
57 {
58 sdbusplus::message::object_path path(object);
59 std::string leaf = path.filename();
60 if (leaf.empty())
61 {
62 continue;
63 }
64 pathNames.push_back(leaf);
65 }
66 std::ranges::sort(pathNames, AlphanumLess<std::string>());
67
68 nlohmann::json& members = asyncResp->res.jsonValue[jsonKeyName];
69 members = nlohmann::json::array();
70 for (const std::string& leaf : pathNames)
71 {
72 boost::urls::url url = collectionPath;
73 crow::utility::appendUrlPieces(url, leaf);
74 nlohmann::json::object_t member;
75 member["@odata.id"] = std::move(url);
76 members.emplace_back(std::move(member));
77 }
78 asyncResp->res.jsonValue[jsonCountKeyName] = members.size();
79 }
80
81 /**
82 * @brief Populate the collection members from a GetSubTreePaths search of
83 * inventory
84 *
85 * @param[i,o] asyncResp Async response object
86 * @param[i] collectionPath Redfish collection path which is used for the
87 * Members Redfish Path
88 * @param[i] interfaces List of interfaces to constrain the GetSubTree search
89 * @param[in] subtree D-Bus base path to constrain search to.
90 * @param[in] jsonKeyName Key name in which the collection members will be
91 * stored.
92 *
93 * @return void
94 */
getCollectionToKey(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,std::span<const std::string_view> interfaces,const std::string & subtree,const nlohmann::json::json_pointer & jsonKeyName)95 inline void getCollectionToKey(
96 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
97 const boost::urls::url& collectionPath,
98 std::span<const std::string_view> interfaces, const std::string& subtree,
99 const nlohmann::json::json_pointer& jsonKeyName)
100 {
101 BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
102 dbus::utility::getSubTreePaths(
103 subtree, 0, interfaces,
104 std::bind_front(handleCollectionMembers, asyncResp, collectionPath,
105 jsonKeyName));
106 }
getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,std::span<const std::string_view> interfaces,const std::string & subtree)107 inline void getCollectionMembers(
108 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
109 const boost::urls::url& collectionPath,
110 std::span<const std::string_view> interfaces, const std::string& subtree)
111 {
112 getCollectionToKey(asyncResp, collectionPath, interfaces, subtree,
113 nlohmann::json::json_pointer("/Members"));
114 }
115
116 } // namespace collection_util
117 } // namespace redfish
118