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
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)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 {
30*1aa375b8SEd Tanous if (jsonKeyName.empty())
31*1aa375b8SEd Tanous {
32*1aa375b8SEd Tanous messages::internalError(asyncResp->res);
33*1aa375b8SEd Tanous BMCWEB_LOG_ERROR("Json Key called empty. Did you mean /Members?");
34*1aa375b8SEd Tanous return;
35*1aa375b8SEd 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 */
9536b5f1edSLakshmi Yadlapati inline void
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)9670c4d545SLakshmi Yadlapati getCollectionToKey(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9770c4d545SLakshmi Yadlapati const boost::urls::url& collectionPath,
9870c4d545SLakshmi Yadlapati std::span<const std::string_view> interfaces,
9970c4d545SLakshmi Yadlapati const std::string& subtree,
10070c4d545SLakshmi Yadlapati const nlohmann::json::json_pointer& jsonKeyName)
10170c4d545SLakshmi Yadlapati {
10270c4d545SLakshmi Yadlapati BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
10370c4d545SLakshmi Yadlapati dbus::utility::getSubTreePaths(subtree, 0, interfaces,
10470c4d545SLakshmi Yadlapati std::bind_front(handleCollectionMembers,
10570c4d545SLakshmi Yadlapati asyncResp, collectionPath,
10670c4d545SLakshmi Yadlapati jsonKeyName));
10770c4d545SLakshmi Yadlapati }
10870c4d545SLakshmi Yadlapati inline void
getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,std::span<const std::string_view> interfaces,const std::string & subtree)10936b5f1edSLakshmi Yadlapati getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11036b5f1edSLakshmi Yadlapati const boost::urls::url& collectionPath,
11136b5f1edSLakshmi Yadlapati std::span<const std::string_view> interfaces,
11236b5f1edSLakshmi Yadlapati const std::string& subtree)
11336b5f1edSLakshmi Yadlapati {
11470c4d545SLakshmi Yadlapati getCollectionToKey(asyncResp, collectionPath, interfaces, subtree,
11570c4d545SLakshmi Yadlapati nlohmann::json::json_pointer("/Members"));
116116bcc5cSGunnar Mills }
117116bcc5cSGunnar Mills
118116bcc5cSGunnar Mills } // namespace collection_util
119116bcc5cSGunnar Mills } // namespace redfish
120