xref: /openbmc/bmcweb/features/redfish/include/utils/collection.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3116bcc5cSGunnar Mills #pragma once
4116bcc5cSGunnar Mills 
53ccb3adbSEd Tanous #include "async_resp.hpp"
67a1dbc48SGeorge Liu #include "dbus_utility.hpp"
73ccb3adbSEd Tanous #include "error_messages.hpp"
83ccb3adbSEd Tanous #include "http/utility.hpp"
93ccb3adbSEd Tanous #include "human_sort.hpp"
107a1dbc48SGeorge Liu 
113ccb3adbSEd Tanous #include <boost/url/url.hpp>
123ccb3adbSEd Tanous #include <nlohmann/json.hpp>
13116bcc5cSGunnar Mills 
143544d2a7SEd Tanous #include <ranges>
157a1dbc48SGeorge Liu #include <span>
16116bcc5cSGunnar Mills #include <string>
177a1dbc48SGeorge Liu #include <string_view>
18116bcc5cSGunnar Mills #include <vector>
19116bcc5cSGunnar Mills 
20116bcc5cSGunnar Mills namespace redfish
21116bcc5cSGunnar Mills {
22116bcc5cSGunnar Mills namespace collection_util
23116bcc5cSGunnar Mills {
24116bcc5cSGunnar Mills 
2536b5f1edSLakshmi Yadlapati inline void handleCollectionMembers(
2636b5f1edSLakshmi Yadlapati     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2770c4d545SLakshmi Yadlapati     const boost::urls::url& collectionPath,
2870c4d545SLakshmi Yadlapati     const nlohmann::json::json_pointer& jsonKeyName,
2970c4d545SLakshmi Yadlapati     const boost::system::error_code& ec,
3036b5f1edSLakshmi Yadlapati     const dbus::utility::MapperGetSubTreePathsResponse& objects)
31116bcc5cSGunnar Mills {
321aa375b8SEd Tanous     if (jsonKeyName.empty())
331aa375b8SEd Tanous     {
341aa375b8SEd Tanous         messages::internalError(asyncResp->res);
351aa375b8SEd Tanous         BMCWEB_LOG_ERROR("Json Key called empty.  Did you mean /Members?");
361aa375b8SEd Tanous         return;
371aa375b8SEd Tanous     }
3870c4d545SLakshmi Yadlapati     nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName;
3970c4d545SLakshmi Yadlapati     std::string back = jsonCountKeyName.back();
4070c4d545SLakshmi Yadlapati     jsonCountKeyName.pop_back();
41c48377dbSMyung Bae     jsonCountKeyName /= back + "@odata.count";
4270c4d545SLakshmi Yadlapati 
4327ea7db1SEd Tanous     if (ec == boost::system::errc::io_error)
4427ea7db1SEd Tanous     {
4570c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonKeyName] = nlohmann::json::array();
4670c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonCountKeyName] = 0;
4727ea7db1SEd Tanous         return;
4827ea7db1SEd Tanous     }
4927ea7db1SEd Tanous 
50116bcc5cSGunnar Mills     if (ec)
51116bcc5cSGunnar Mills     {
5262598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
53ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
54116bcc5cSGunnar Mills         return;
55116bcc5cSGunnar Mills     }
56116bcc5cSGunnar Mills 
5792409d0eSEd Tanous     std::vector<std::string> pathNames;
58dea43dd4SJonathan Doman     for (const auto& object : objects)
59116bcc5cSGunnar Mills     {
602dfd18efSEd Tanous         sdbusplus::message::object_path path(object);
612dfd18efSEd Tanous         std::string leaf = path.filename();
622dfd18efSEd Tanous         if (leaf.empty())
63116bcc5cSGunnar Mills         {
642dfd18efSEd Tanous             continue;
65116bcc5cSGunnar Mills         }
6692409d0eSEd Tanous         pathNames.push_back(leaf);
6792409d0eSEd Tanous     }
683544d2a7SEd Tanous     std::ranges::sort(pathNames, AlphanumLess<std::string>());
6992409d0eSEd Tanous 
7070c4d545SLakshmi Yadlapati     nlohmann::json& members = asyncResp->res.jsonValue[jsonKeyName];
7192409d0eSEd Tanous     members = nlohmann::json::array();
7292409d0eSEd Tanous     for (const std::string& leaf : pathNames)
7392409d0eSEd Tanous     {
74ae9031f0SWilly Tu         boost::urls::url url = collectionPath;
75ae9031f0SWilly Tu         crow::utility::appendUrlPieces(url, leaf);
761476687dSEd Tanous         nlohmann::json::object_t member;
77ae9031f0SWilly Tu         member["@odata.id"] = std::move(url);
78b2ba3072SPatrick Williams         members.emplace_back(std::move(member));
79116bcc5cSGunnar Mills     }
8070c4d545SLakshmi Yadlapati     asyncResp->res.jsonValue[jsonCountKeyName] = members.size();
8136b5f1edSLakshmi Yadlapati }
8236b5f1edSLakshmi Yadlapati 
8336b5f1edSLakshmi Yadlapati /**
8470c4d545SLakshmi Yadlapati  * @brief Populate the collection members from a GetSubTreePaths search of
8536b5f1edSLakshmi Yadlapati  *        inventory
8636b5f1edSLakshmi Yadlapati  *
8736b5f1edSLakshmi Yadlapati  * @param[i,o] asyncResp  Async response object
8836b5f1edSLakshmi Yadlapati  * @param[i]   collectionPath  Redfish collection path which is used for the
8936b5f1edSLakshmi Yadlapati  *             Members Redfish Path
9036b5f1edSLakshmi Yadlapati  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
9136b5f1edSLakshmi Yadlapati  * @param[in]  subtree     D-Bus base path to constrain search to.
9270c4d545SLakshmi Yadlapati  * @param[in]  jsonKeyName Key name in which the collection members will be
9370c4d545SLakshmi Yadlapati  *             stored.
9436b5f1edSLakshmi Yadlapati  *
9536b5f1edSLakshmi Yadlapati  * @return void
9636b5f1edSLakshmi Yadlapati  */
97bd79bce8SPatrick Williams inline void getCollectionToKey(
98bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9970c4d545SLakshmi Yadlapati     const boost::urls::url& collectionPath,
100bd79bce8SPatrick Williams     std::span<const std::string_view> interfaces, const std::string& subtree,
10170c4d545SLakshmi Yadlapati     const nlohmann::json::json_pointer& jsonKeyName)
10270c4d545SLakshmi Yadlapati {
10370c4d545SLakshmi Yadlapati     BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
104bd79bce8SPatrick Williams     dbus::utility::getSubTreePaths(
105bd79bce8SPatrick Williams         subtree, 0, interfaces,
106bd79bce8SPatrick Williams         std::bind_front(handleCollectionMembers, asyncResp, collectionPath,
10770c4d545SLakshmi Yadlapati                         jsonKeyName));
10870c4d545SLakshmi Yadlapati }
109bd79bce8SPatrick Williams inline void getCollectionMembers(
110bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11136b5f1edSLakshmi Yadlapati     const boost::urls::url& collectionPath,
112bd79bce8SPatrick Williams     std::span<const std::string_view> interfaces, 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