xref: /openbmc/bmcweb/features/redfish/include/utils/collection.hpp (revision bd79bce8c3f1deb1fb2773868b9ece25233cf27b)
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,
2570c4d545SLakshmi Yadlapati     const boost::urls::url& collectionPath,
2670c4d545SLakshmi Yadlapati     const nlohmann::json::json_pointer& jsonKeyName,
2770c4d545SLakshmi Yadlapati     const boost::system::error_code& ec,
2836b5f1edSLakshmi Yadlapati     const dbus::utility::MapperGetSubTreePathsResponse& objects)
29116bcc5cSGunnar Mills {
301aa375b8SEd Tanous     if (jsonKeyName.empty())
311aa375b8SEd Tanous     {
321aa375b8SEd Tanous         messages::internalError(asyncResp->res);
331aa375b8SEd Tanous         BMCWEB_LOG_ERROR("Json Key called empty.  Did you mean /Members?");
341aa375b8SEd Tanous         return;
351aa375b8SEd Tanous     }
3670c4d545SLakshmi Yadlapati     nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName;
3770c4d545SLakshmi Yadlapati     std::string back = jsonCountKeyName.back();
3870c4d545SLakshmi Yadlapati     jsonCountKeyName.pop_back();
39c48377dbSMyung Bae     jsonCountKeyName /= back + "@odata.count";
4070c4d545SLakshmi Yadlapati 
4127ea7db1SEd Tanous     if (ec == boost::system::errc::io_error)
4227ea7db1SEd Tanous     {
4370c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonKeyName] = nlohmann::json::array();
4470c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonCountKeyName] = 0;
4527ea7db1SEd Tanous         return;
4627ea7db1SEd Tanous     }
4727ea7db1SEd Tanous 
48116bcc5cSGunnar Mills     if (ec)
49116bcc5cSGunnar Mills     {
5062598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
51ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
52116bcc5cSGunnar Mills         return;
53116bcc5cSGunnar Mills     }
54116bcc5cSGunnar Mills 
5592409d0eSEd Tanous     std::vector<std::string> pathNames;
56dea43dd4SJonathan Doman     for (const auto& object : objects)
57116bcc5cSGunnar Mills     {
582dfd18efSEd Tanous         sdbusplus::message::object_path path(object);
592dfd18efSEd Tanous         std::string leaf = path.filename();
602dfd18efSEd Tanous         if (leaf.empty())
61116bcc5cSGunnar Mills         {
622dfd18efSEd Tanous             continue;
63116bcc5cSGunnar Mills         }
6492409d0eSEd Tanous         pathNames.push_back(leaf);
6592409d0eSEd Tanous     }
663544d2a7SEd Tanous     std::ranges::sort(pathNames, AlphanumLess<std::string>());
6792409d0eSEd Tanous 
6870c4d545SLakshmi Yadlapati     nlohmann::json& members = asyncResp->res.jsonValue[jsonKeyName];
6992409d0eSEd Tanous     members = nlohmann::json::array();
7092409d0eSEd Tanous     for (const std::string& leaf : pathNames)
7192409d0eSEd Tanous     {
72ae9031f0SWilly Tu         boost::urls::url url = collectionPath;
73ae9031f0SWilly Tu         crow::utility::appendUrlPieces(url, leaf);
741476687dSEd Tanous         nlohmann::json::object_t member;
75ae9031f0SWilly Tu         member["@odata.id"] = std::move(url);
76b2ba3072SPatrick Williams         members.emplace_back(std::move(member));
77116bcc5cSGunnar Mills     }
7870c4d545SLakshmi Yadlapati     asyncResp->res.jsonValue[jsonCountKeyName] = members.size();
7936b5f1edSLakshmi Yadlapati }
8036b5f1edSLakshmi Yadlapati 
8136b5f1edSLakshmi Yadlapati /**
8270c4d545SLakshmi Yadlapati  * @brief Populate the collection members from a GetSubTreePaths search of
8336b5f1edSLakshmi Yadlapati  *        inventory
8436b5f1edSLakshmi Yadlapati  *
8536b5f1edSLakshmi Yadlapati  * @param[i,o] asyncResp  Async response object
8636b5f1edSLakshmi Yadlapati  * @param[i]   collectionPath  Redfish collection path which is used for the
8736b5f1edSLakshmi Yadlapati  *             Members Redfish Path
8836b5f1edSLakshmi Yadlapati  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
8936b5f1edSLakshmi Yadlapati  * @param[in]  subtree     D-Bus base path to constrain search to.
9070c4d545SLakshmi Yadlapati  * @param[in]  jsonKeyName Key name in which the collection members will be
9170c4d545SLakshmi Yadlapati  *             stored.
9236b5f1edSLakshmi Yadlapati  *
9336b5f1edSLakshmi Yadlapati  * @return void
9436b5f1edSLakshmi Yadlapati  */
95*bd79bce8SPatrick Williams inline void getCollectionToKey(
96*bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9770c4d545SLakshmi Yadlapati     const boost::urls::url& collectionPath,
98*bd79bce8SPatrick Williams     std::span<const std::string_view> interfaces, const std::string& subtree,
9970c4d545SLakshmi Yadlapati     const nlohmann::json::json_pointer& jsonKeyName)
10070c4d545SLakshmi Yadlapati {
10170c4d545SLakshmi Yadlapati     BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
102*bd79bce8SPatrick Williams     dbus::utility::getSubTreePaths(
103*bd79bce8SPatrick Williams         subtree, 0, interfaces,
104*bd79bce8SPatrick Williams         std::bind_front(handleCollectionMembers, asyncResp, collectionPath,
10570c4d545SLakshmi Yadlapati                         jsonKeyName));
10670c4d545SLakshmi Yadlapati }
107*bd79bce8SPatrick Williams inline void getCollectionMembers(
108*bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10936b5f1edSLakshmi Yadlapati     const boost::urls::url& collectionPath,
110*bd79bce8SPatrick Williams     std::span<const std::string_view> interfaces, const std::string& subtree)
11136b5f1edSLakshmi Yadlapati {
11270c4d545SLakshmi Yadlapati     getCollectionToKey(asyncResp, collectionPath, interfaces, subtree,
11370c4d545SLakshmi Yadlapati                        nlohmann::json::json_pointer("/Members"));
114116bcc5cSGunnar Mills }
115116bcc5cSGunnar Mills 
116116bcc5cSGunnar Mills } // namespace collection_util
117116bcc5cSGunnar Mills } // namespace redfish
118