xref: /openbmc/bmcweb/features/redfish/include/utils/collection.hpp (revision 70c4d545817d83819f7f0cd571e0160bacb51d11)
1116bcc5cSGunnar Mills #pragma once
2116bcc5cSGunnar Mills 
33ccb3adbSEd Tanous #include "async_resp.hpp"
47a1dbc48SGeorge Liu #include "dbus_utility.hpp"
53ccb3adbSEd Tanous #include "error_messages.hpp"
63ccb3adbSEd Tanous #include "http/utility.hpp"
73ccb3adbSEd Tanous #include "human_sort.hpp"
87a1dbc48SGeorge Liu 
93ccb3adbSEd Tanous #include <boost/url/url.hpp>
103ccb3adbSEd Tanous #include <nlohmann/json.hpp>
11116bcc5cSGunnar Mills 
123544d2a7SEd Tanous #include <ranges>
137a1dbc48SGeorge Liu #include <span>
14116bcc5cSGunnar Mills #include <string>
157a1dbc48SGeorge Liu #include <string_view>
16116bcc5cSGunnar Mills #include <vector>
17116bcc5cSGunnar Mills 
18116bcc5cSGunnar Mills namespace redfish
19116bcc5cSGunnar Mills {
20116bcc5cSGunnar Mills namespace collection_util
21116bcc5cSGunnar Mills {
22116bcc5cSGunnar Mills 
2336b5f1edSLakshmi Yadlapati inline void handleCollectionMembers(
2436b5f1edSLakshmi Yadlapati     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
25*70c4d545SLakshmi Yadlapati     const boost::urls::url& collectionPath,
26*70c4d545SLakshmi Yadlapati     const nlohmann::json::json_pointer& jsonKeyName,
27*70c4d545SLakshmi Yadlapati     const boost::system::error_code& ec,
2836b5f1edSLakshmi Yadlapati     const dbus::utility::MapperGetSubTreePathsResponse& objects)
29116bcc5cSGunnar Mills {
30*70c4d545SLakshmi Yadlapati     nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName;
31*70c4d545SLakshmi Yadlapati     std::string back = jsonCountKeyName.back();
32*70c4d545SLakshmi Yadlapati     jsonCountKeyName.pop_back();
33*70c4d545SLakshmi Yadlapati     jsonCountKeyName /= back + "@data.count";
34*70c4d545SLakshmi Yadlapati 
3527ea7db1SEd Tanous     if (ec == boost::system::errc::io_error)
3627ea7db1SEd Tanous     {
37*70c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonKeyName] = nlohmann::json::array();
38*70c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonCountKeyName] = 0;
3927ea7db1SEd Tanous         return;
4027ea7db1SEd Tanous     }
4127ea7db1SEd Tanous 
42116bcc5cSGunnar Mills     if (ec)
43116bcc5cSGunnar Mills     {
4462598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
45ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
46116bcc5cSGunnar Mills         return;
47116bcc5cSGunnar Mills     }
48116bcc5cSGunnar Mills 
4992409d0eSEd Tanous     std::vector<std::string> pathNames;
50dea43dd4SJonathan Doman     for (const auto& object : objects)
51116bcc5cSGunnar Mills     {
522dfd18efSEd Tanous         sdbusplus::message::object_path path(object);
532dfd18efSEd Tanous         std::string leaf = path.filename();
542dfd18efSEd Tanous         if (leaf.empty())
55116bcc5cSGunnar Mills         {
562dfd18efSEd Tanous             continue;
57116bcc5cSGunnar Mills         }
5892409d0eSEd Tanous         pathNames.push_back(leaf);
5992409d0eSEd Tanous     }
603544d2a7SEd Tanous     std::ranges::sort(pathNames, AlphanumLess<std::string>());
6192409d0eSEd Tanous 
62*70c4d545SLakshmi Yadlapati     nlohmann::json& members = asyncResp->res.jsonValue[jsonKeyName];
6392409d0eSEd Tanous     members = nlohmann::json::array();
6492409d0eSEd Tanous     for (const std::string& leaf : pathNames)
6592409d0eSEd Tanous     {
66ae9031f0SWilly Tu         boost::urls::url url = collectionPath;
67ae9031f0SWilly Tu         crow::utility::appendUrlPieces(url, leaf);
681476687dSEd Tanous         nlohmann::json::object_t member;
69ae9031f0SWilly Tu         member["@odata.id"] = std::move(url);
70b2ba3072SPatrick Williams         members.emplace_back(std::move(member));
71116bcc5cSGunnar Mills     }
72*70c4d545SLakshmi Yadlapati     asyncResp->res.jsonValue[jsonCountKeyName] = members.size();
7336b5f1edSLakshmi Yadlapati }
7436b5f1edSLakshmi Yadlapati 
7536b5f1edSLakshmi Yadlapati /**
76*70c4d545SLakshmi Yadlapati  * @brief Populate the collection members from a GetSubTreePaths search of
7736b5f1edSLakshmi Yadlapati  *        inventory
7836b5f1edSLakshmi Yadlapati  *
7936b5f1edSLakshmi Yadlapati  * @param[i,o] asyncResp  Async response object
8036b5f1edSLakshmi Yadlapati  * @param[i]   collectionPath  Redfish collection path which is used for the
8136b5f1edSLakshmi Yadlapati  *             Members Redfish Path
8236b5f1edSLakshmi Yadlapati  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
8336b5f1edSLakshmi Yadlapati  * @param[in]  subtree     D-Bus base path to constrain search to.
84*70c4d545SLakshmi Yadlapati  * @param[in]  jsonKeyName Key name in which the collection members will be
85*70c4d545SLakshmi Yadlapati  *             stored.
8636b5f1edSLakshmi Yadlapati  *
8736b5f1edSLakshmi Yadlapati  * @return void
8836b5f1edSLakshmi Yadlapati  */
8936b5f1edSLakshmi Yadlapati inline void
90*70c4d545SLakshmi Yadlapati     getCollectionToKey(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
91*70c4d545SLakshmi Yadlapati                        const boost::urls::url& collectionPath,
92*70c4d545SLakshmi Yadlapati                        std::span<const std::string_view> interfaces,
93*70c4d545SLakshmi Yadlapati                        const std::string& subtree,
94*70c4d545SLakshmi Yadlapati                        const nlohmann::json::json_pointer& jsonKeyName)
95*70c4d545SLakshmi Yadlapati {
96*70c4d545SLakshmi Yadlapati     BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
97*70c4d545SLakshmi Yadlapati     dbus::utility::getSubTreePaths(subtree, 0, interfaces,
98*70c4d545SLakshmi Yadlapati                                    std::bind_front(handleCollectionMembers,
99*70c4d545SLakshmi Yadlapati                                                    asyncResp, collectionPath,
100*70c4d545SLakshmi Yadlapati                                                    jsonKeyName));
101*70c4d545SLakshmi Yadlapati }
102*70c4d545SLakshmi Yadlapati inline void
10336b5f1edSLakshmi Yadlapati     getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10436b5f1edSLakshmi Yadlapati                          const boost::urls::url& collectionPath,
10536b5f1edSLakshmi Yadlapati                          std::span<const std::string_view> interfaces,
10636b5f1edSLakshmi Yadlapati                          const std::string& subtree)
10736b5f1edSLakshmi Yadlapati {
108*70c4d545SLakshmi Yadlapati     getCollectionToKey(asyncResp, collectionPath, interfaces, subtree,
109*70c4d545SLakshmi Yadlapati                        nlohmann::json::json_pointer("/Members"));
110116bcc5cSGunnar Mills }
111116bcc5cSGunnar Mills 
112116bcc5cSGunnar Mills } // namespace collection_util
113116bcc5cSGunnar Mills } // namespace redfish
114