xref: /openbmc/bmcweb/features/redfish/lib/aggregation_service.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
36c068982SEd Tanous #pragma once
46c068982SEd Tanous 
56c068982SEd Tanous #include "app.hpp"
66c068982SEd Tanous #include "error_messages.hpp"
76c068982SEd Tanous #include "http_request.hpp"
86c068982SEd Tanous #include "http_response.hpp"
96c068982SEd Tanous #include "query.hpp"
108b2521a5SCarson Labrado #include "redfish_aggregator.hpp"
116c068982SEd Tanous #include "registries/privilege_registry.hpp"
126c068982SEd Tanous 
13ef4c65b7SEd Tanous #include <boost/url/format.hpp>
146c068982SEd Tanous #include <nlohmann/json.hpp>
156c068982SEd Tanous 
166c068982SEd Tanous #include <functional>
176c068982SEd Tanous #include <memory>
186c068982SEd Tanous 
196c068982SEd Tanous namespace redfish
206c068982SEd Tanous {
216c068982SEd Tanous 
226c068982SEd Tanous inline void handleAggregationServiceHead(
236c068982SEd Tanous     App& app, const crow::Request& req,
246c068982SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
256c068982SEd Tanous {
266c068982SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
276c068982SEd Tanous     {
286c068982SEd Tanous         return;
296c068982SEd Tanous     }
306c068982SEd Tanous     asyncResp->res.addHeader(
316c068982SEd Tanous         boost::beast::http::field::link,
326c068982SEd Tanous         "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
336c068982SEd Tanous }
346c068982SEd Tanous 
356c068982SEd Tanous inline void handleAggregationServiceGet(
366c068982SEd Tanous     App& app, const crow::Request& req,
376c068982SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
386c068982SEd Tanous {
396c068982SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
406c068982SEd Tanous     {
416c068982SEd Tanous         return;
426c068982SEd Tanous     }
436c068982SEd Tanous     asyncResp->res.addHeader(
446c068982SEd Tanous         boost::beast::http::field::link,
456c068982SEd Tanous         "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
466c068982SEd Tanous     nlohmann::json& json = asyncResp->res.jsonValue;
476c068982SEd Tanous     json["@odata.id"] = "/redfish/v1/AggregationService";
486c068982SEd Tanous     json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService";
496c068982SEd Tanous     json["Id"] = "AggregationService";
506c068982SEd Tanous     json["Name"] = "Aggregation Service";
516c068982SEd Tanous     json["Description"] = "Aggregation Service";
526c068982SEd Tanous     json["ServiceEnabled"] = true;
535315c1b1SCarson Labrado     json["AggregationSources"]["@odata.id"] =
545315c1b1SCarson Labrado         "/redfish/v1/AggregationService/AggregationSources";
556c068982SEd Tanous }
566c068982SEd Tanous 
578b2521a5SCarson Labrado inline void requestRoutesAggregationService(App& app)
586c068982SEd Tanous {
596c068982SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
606c068982SEd Tanous         .privileges(redfish::privileges::headAggregationService)
616c068982SEd Tanous         .methods(boost::beast::http::verb::head)(
626c068982SEd Tanous             std::bind_front(handleAggregationServiceHead, std::ref(app)));
636c068982SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
646c068982SEd Tanous         .privileges(redfish::privileges::getAggregationService)
656c068982SEd Tanous         .methods(boost::beast::http::verb::get)(
666c068982SEd Tanous             std::bind_front(handleAggregationServiceGet, std::ref(app)));
676c068982SEd Tanous }
686c068982SEd Tanous 
698b2521a5SCarson Labrado inline void populateAggregationSourceCollection(
708b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7181c4e330SEd Tanous     const boost::system::error_code& ec,
728b2521a5SCarson Labrado     const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
738b2521a5SCarson Labrado {
748b2521a5SCarson Labrado     // Something went wrong while querying dbus
758b2521a5SCarson Labrado     if (ec)
768b2521a5SCarson Labrado     {
778b2521a5SCarson Labrado         messages::internalError(asyncResp->res);
788b2521a5SCarson Labrado         return;
798b2521a5SCarson Labrado     }
808b2521a5SCarson Labrado     nlohmann::json::array_t members = nlohmann::json::array();
818b2521a5SCarson Labrado     for (const auto& sat : satelliteInfo)
828b2521a5SCarson Labrado     {
838b2521a5SCarson Labrado         nlohmann::json::object_t member;
84ef4c65b7SEd Tanous         member["@odata.id"] = boost::urls::format(
85ef4c65b7SEd Tanous             "/redfish/v1/AggregationService/AggregationSources/{}", sat.first);
86ad539545SPatrick Williams         members.emplace_back(std::move(member));
878b2521a5SCarson Labrado     }
888b2521a5SCarson Labrado     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
898b2521a5SCarson Labrado     asyncResp->res.jsonValue["Members"] = std::move(members);
908b2521a5SCarson Labrado }
918b2521a5SCarson Labrado 
928b2521a5SCarson Labrado inline void handleAggregationSourceCollectionGet(
935315c1b1SCarson Labrado     App& app, const crow::Request& req,
945315c1b1SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
955315c1b1SCarson Labrado {
965315c1b1SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
975315c1b1SCarson Labrado     {
985315c1b1SCarson Labrado         return;
995315c1b1SCarson Labrado     }
1005315c1b1SCarson Labrado     asyncResp->res.addHeader(
1015315c1b1SCarson Labrado         boost::beast::http::field::link,
1025315c1b1SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationSourceCollection/AggregationSourceCollection.json>; rel=describedby");
1035315c1b1SCarson Labrado     nlohmann::json& json = asyncResp->res.jsonValue;
1045315c1b1SCarson Labrado     json["@odata.id"] = "/redfish/v1/AggregationService/AggregationSources";
1055315c1b1SCarson Labrado     json["@odata.type"] =
1065315c1b1SCarson Labrado         "#AggregationSourceCollection.AggregationSourceCollection";
1075315c1b1SCarson Labrado     json["Name"] = "Aggregation Source Collection";
1085315c1b1SCarson Labrado 
1098b2521a5SCarson Labrado     // Query D-Bus for satellite configs and add them to the Members array
1108b2521a5SCarson Labrado     RedfishAggregator::getSatelliteConfigs(
1118b2521a5SCarson Labrado         std::bind_front(populateAggregationSourceCollection, asyncResp));
1125315c1b1SCarson Labrado }
1135315c1b1SCarson Labrado 
1148b2521a5SCarson Labrado inline void handleAggregationSourceCollectionHead(
1158b2521a5SCarson Labrado     App& app, const crow::Request& req,
1168b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1178b2521a5SCarson Labrado {
1188b2521a5SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1198b2521a5SCarson Labrado     {
1208b2521a5SCarson Labrado         return;
1218b2521a5SCarson Labrado     }
1228b2521a5SCarson Labrado     asyncResp->res.addHeader(
1238b2521a5SCarson Labrado         boost::beast::http::field::link,
1248b2521a5SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationService/AggregationSourceCollection.json>; rel=describedby");
1258b2521a5SCarson Labrado }
1268b2521a5SCarson Labrado 
1278b2521a5SCarson Labrado inline void requestRoutesAggregationSourceCollection(App& app)
1285315c1b1SCarson Labrado {
1295315c1b1SCarson Labrado     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
1308b2521a5SCarson Labrado         .privileges(redfish::privileges::getAggregationSourceCollection)
1318b2521a5SCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
1328b2521a5SCarson Labrado             handleAggregationSourceCollectionGet, std::ref(app)));
1338b2521a5SCarson Labrado 
1348b2521a5SCarson Labrado     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
1358b2521a5SCarson Labrado         .privileges(redfish::privileges::getAggregationSourceCollection)
1368b2521a5SCarson Labrado         .methods(boost::beast::http::verb::head)(std::bind_front(
1378b2521a5SCarson Labrado             handleAggregationSourceCollectionHead, std::ref(app)));
1388b2521a5SCarson Labrado }
1398b2521a5SCarson Labrado 
1408b2521a5SCarson Labrado inline void populateAggregationSource(
1418b2521a5SCarson Labrado     const std::string& aggregationSourceId,
1428b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
14381c4e330SEd Tanous     const boost::system::error_code& ec,
1448b2521a5SCarson Labrado     const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
1458b2521a5SCarson Labrado {
1468b2521a5SCarson Labrado     asyncResp->res.addHeader(
1478b2521a5SCarson Labrado         boost::beast::http::field::link,
1488b2521a5SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationSource/AggregationSource.json>; rel=describedby");
1498b2521a5SCarson Labrado 
1508b2521a5SCarson Labrado     // Something went wrong while querying dbus
1518b2521a5SCarson Labrado     if (ec)
1528b2521a5SCarson Labrado     {
1538b2521a5SCarson Labrado         messages::internalError(asyncResp->res);
1548b2521a5SCarson Labrado         return;
1558b2521a5SCarson Labrado     }
1568b2521a5SCarson Labrado 
1578b2521a5SCarson Labrado     const auto& sat = satelliteInfo.find(aggregationSourceId);
1588b2521a5SCarson Labrado     if (sat == satelliteInfo.end())
1598b2521a5SCarson Labrado     {
1608b2521a5SCarson Labrado         messages::resourceNotFound(asyncResp->res, "AggregationSource",
1618b2521a5SCarson Labrado                                    aggregationSourceId);
1628b2521a5SCarson Labrado         return;
1638b2521a5SCarson Labrado     }
1648b2521a5SCarson Labrado 
165ef4c65b7SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
166ef4c65b7SEd Tanous         "/redfish/v1/AggregationService/AggregationSources/{}",
167ef4c65b7SEd Tanous         aggregationSourceId);
1688b2521a5SCarson Labrado     asyncResp->res.jsonValue["@odata.type"] =
1698b2521a5SCarson Labrado         "#AggregationSource.v1_3_1.AggregationSource";
1708b2521a5SCarson Labrado     asyncResp->res.jsonValue["Id"] = aggregationSourceId;
1718b2521a5SCarson Labrado 
1728b2521a5SCarson Labrado     // TODO: We may want to change this whenever we support aggregating multiple
1738b2521a5SCarson Labrado     // satellite BMCs.  Otherwise all AggregationSource resources will have the
1748b2521a5SCarson Labrado     // same "Name".
1758b2521a5SCarson Labrado     // TODO: We should use the "Name" from the satellite config whenever we add
1768b2521a5SCarson Labrado     // support for including it in the data returned in satelliteInfo.
1778b2521a5SCarson Labrado     asyncResp->res.jsonValue["Name"] = "Aggregation source";
1788b2521a5SCarson Labrado     std::string hostName(sat->second.encoded_origin());
1798b2521a5SCarson Labrado     asyncResp->res.jsonValue["HostName"] = std::move(hostName);
1808b2521a5SCarson Labrado 
1818b2521a5SCarson Labrado     // The Redfish spec requires Password to be null in responses
1828b2521a5SCarson Labrado     asyncResp->res.jsonValue["Password"] = nullptr;
1838b2521a5SCarson Labrado }
1848b2521a5SCarson Labrado 
1858b2521a5SCarson Labrado inline void handleAggregationSourceGet(
1868b2521a5SCarson Labrado     App& app, const crow::Request& req,
1878b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1888b2521a5SCarson Labrado     const std::string& aggregationSourceId)
1898b2521a5SCarson Labrado {
1908b2521a5SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1918b2521a5SCarson Labrado     {
1928b2521a5SCarson Labrado         return;
1938b2521a5SCarson Labrado     }
1948b2521a5SCarson Labrado 
1958b2521a5SCarson Labrado     // Query D-Bus for satellite config corresponding to the specified
1968b2521a5SCarson Labrado     // AggregationSource
1978b2521a5SCarson Labrado     RedfishAggregator::getSatelliteConfigs(std::bind_front(
1988b2521a5SCarson Labrado         populateAggregationSource, aggregationSourceId, asyncResp));
1998b2521a5SCarson Labrado }
2008b2521a5SCarson Labrado 
2018b2521a5SCarson Labrado inline void handleAggregationSourceHead(
2028b2521a5SCarson Labrado     App& app, const crow::Request& req,
2038b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2048b2521a5SCarson Labrado     const std::string& aggregationSourceId)
2058b2521a5SCarson Labrado {
2068b2521a5SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2078b2521a5SCarson Labrado     {
2088b2521a5SCarson Labrado         return;
2098b2521a5SCarson Labrado     }
2108b2521a5SCarson Labrado     asyncResp->res.addHeader(
2118b2521a5SCarson Labrado         boost::beast::http::field::link,
2128b2521a5SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationService/AggregationSource.json>; rel=describedby");
2138b2521a5SCarson Labrado 
2148b2521a5SCarson Labrado     // Needed to prevent unused variable error
21562598e31SEd Tanous     BMCWEB_LOG_DEBUG("Added link header to response from {}",
21662598e31SEd Tanous                      aggregationSourceId);
2178b2521a5SCarson Labrado }
2188b2521a5SCarson Labrado 
2198b2521a5SCarson Labrado inline void requestRoutesAggregationSource(App& app)
2208b2521a5SCarson Labrado {
2218b2521a5SCarson Labrado     BMCWEB_ROUTE(app,
2228b2521a5SCarson Labrado                  "/redfish/v1/AggregationService/AggregationSources/<str>/")
2238b2521a5SCarson Labrado         .privileges(redfish::privileges::getAggregationSource)
2245315c1b1SCarson Labrado         .methods(boost::beast::http::verb::get)(
2258b2521a5SCarson Labrado             std::bind_front(handleAggregationSourceGet, std::ref(app)));
2265315c1b1SCarson Labrado }
2275315c1b1SCarson Labrado 
2286c068982SEd Tanous } // namespace redfish
229