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