16c068982SEd Tanous #pragma once 26c068982SEd Tanous 36c068982SEd Tanous #include "app.hpp" 46c068982SEd Tanous #include "error_messages.hpp" 56c068982SEd Tanous #include "http_request.hpp" 66c068982SEd Tanous #include "http_response.hpp" 76c068982SEd Tanous #include "query.hpp" 8*8b2521a5SCarson Labrado #include "redfish_aggregator.hpp" 96c068982SEd Tanous #include "registries/privilege_registry.hpp" 106c068982SEd Tanous 116c068982SEd Tanous #include <nlohmann/json.hpp> 126c068982SEd Tanous 136c068982SEd Tanous #include <functional> 146c068982SEd Tanous #include <memory> 156c068982SEd Tanous 166c068982SEd Tanous namespace redfish 176c068982SEd Tanous { 186c068982SEd Tanous 196c068982SEd Tanous inline void handleAggregationServiceHead( 206c068982SEd Tanous App& app, const crow::Request& req, 216c068982SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 226c068982SEd Tanous { 236c068982SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 246c068982SEd Tanous { 256c068982SEd Tanous return; 266c068982SEd Tanous } 276c068982SEd Tanous asyncResp->res.addHeader( 286c068982SEd Tanous boost::beast::http::field::link, 296c068982SEd Tanous "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby"); 306c068982SEd Tanous } 316c068982SEd Tanous 326c068982SEd Tanous inline void handleAggregationServiceGet( 336c068982SEd Tanous App& app, const crow::Request& req, 346c068982SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 356c068982SEd Tanous { 366c068982SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 376c068982SEd Tanous { 386c068982SEd Tanous return; 396c068982SEd Tanous } 406c068982SEd Tanous asyncResp->res.addHeader( 416c068982SEd Tanous boost::beast::http::field::link, 426c068982SEd Tanous "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby"); 436c068982SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 446c068982SEd Tanous json["@odata.id"] = "/redfish/v1/AggregationService"; 456c068982SEd Tanous json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService"; 466c068982SEd Tanous json["Id"] = "AggregationService"; 476c068982SEd Tanous json["Name"] = "Aggregation Service"; 486c068982SEd Tanous json["Description"] = "Aggregation Service"; 496c068982SEd Tanous json["ServiceEnabled"] = true; 505315c1b1SCarson Labrado json["AggregationSources"]["@odata.id"] = 515315c1b1SCarson Labrado "/redfish/v1/AggregationService/AggregationSources"; 526c068982SEd Tanous } 536c068982SEd Tanous 54*8b2521a5SCarson Labrado inline void requestRoutesAggregationService(App& app) 556c068982SEd Tanous { 566c068982SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/") 576c068982SEd Tanous .privileges(redfish::privileges::headAggregationService) 586c068982SEd Tanous .methods(boost::beast::http::verb::head)( 596c068982SEd Tanous std::bind_front(handleAggregationServiceHead, std::ref(app))); 606c068982SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/") 616c068982SEd Tanous .privileges(redfish::privileges::getAggregationService) 626c068982SEd Tanous .methods(boost::beast::http::verb::get)( 636c068982SEd Tanous std::bind_front(handleAggregationServiceGet, std::ref(app))); 646c068982SEd Tanous } 656c068982SEd Tanous 66*8b2521a5SCarson Labrado inline void populateAggregationSourceCollection( 67*8b2521a5SCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 68*8b2521a5SCarson Labrado const boost::system::error_code ec, 69*8b2521a5SCarson Labrado const std::unordered_map<std::string, boost::urls::url>& satelliteInfo) 70*8b2521a5SCarson Labrado { 71*8b2521a5SCarson Labrado // Something went wrong while querying dbus 72*8b2521a5SCarson Labrado if (ec) 73*8b2521a5SCarson Labrado { 74*8b2521a5SCarson Labrado messages::internalError(asyncResp->res); 75*8b2521a5SCarson Labrado return; 76*8b2521a5SCarson Labrado } 77*8b2521a5SCarson Labrado nlohmann::json::array_t members = nlohmann::json::array(); 78*8b2521a5SCarson Labrado for (const auto& sat : satelliteInfo) 79*8b2521a5SCarson Labrado { 80*8b2521a5SCarson Labrado nlohmann::json::object_t member; 81*8b2521a5SCarson Labrado member["@odata.id"] = 82*8b2521a5SCarson Labrado crow::utility::urlFromPieces("redfish", "v1", "AggregationService", 83*8b2521a5SCarson Labrado "AggregationSources", sat.first); 84*8b2521a5SCarson Labrado members.push_back(std::move(member)); 85*8b2521a5SCarson Labrado } 86*8b2521a5SCarson Labrado asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 87*8b2521a5SCarson Labrado asyncResp->res.jsonValue["Members"] = std::move(members); 88*8b2521a5SCarson Labrado } 89*8b2521a5SCarson Labrado 90*8b2521a5SCarson Labrado inline void handleAggregationSourceCollectionGet( 915315c1b1SCarson Labrado App& app, const crow::Request& req, 925315c1b1SCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 935315c1b1SCarson Labrado { 945315c1b1SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 955315c1b1SCarson Labrado { 965315c1b1SCarson Labrado return; 975315c1b1SCarson Labrado } 985315c1b1SCarson Labrado asyncResp->res.addHeader( 995315c1b1SCarson Labrado boost::beast::http::field::link, 1005315c1b1SCarson Labrado "</redfish/v1/JsonSchemas/AggregationSourceCollection/AggregationSourceCollection.json>; rel=describedby"); 1015315c1b1SCarson Labrado nlohmann::json& json = asyncResp->res.jsonValue; 1025315c1b1SCarson Labrado json["@odata.id"] = "/redfish/v1/AggregationService/AggregationSources"; 1035315c1b1SCarson Labrado json["@odata.type"] = 1045315c1b1SCarson Labrado "#AggregationSourceCollection.AggregationSourceCollection"; 1055315c1b1SCarson Labrado json["Name"] = "Aggregation Source Collection"; 1065315c1b1SCarson Labrado 107*8b2521a5SCarson Labrado // Query D-Bus for satellite configs and add them to the Members array 108*8b2521a5SCarson Labrado RedfishAggregator::getSatelliteConfigs( 109*8b2521a5SCarson Labrado std::bind_front(populateAggregationSourceCollection, asyncResp)); 1105315c1b1SCarson Labrado } 1115315c1b1SCarson Labrado 112*8b2521a5SCarson Labrado inline void handleAggregationSourceCollectionHead( 113*8b2521a5SCarson Labrado App& app, const crow::Request& req, 114*8b2521a5SCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 115*8b2521a5SCarson Labrado { 116*8b2521a5SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 117*8b2521a5SCarson Labrado { 118*8b2521a5SCarson Labrado return; 119*8b2521a5SCarson Labrado } 120*8b2521a5SCarson Labrado asyncResp->res.addHeader( 121*8b2521a5SCarson Labrado boost::beast::http::field::link, 122*8b2521a5SCarson Labrado "</redfish/v1/JsonSchemas/AggregationService/AggregationSourceCollection.json>; rel=describedby"); 123*8b2521a5SCarson Labrado } 124*8b2521a5SCarson Labrado 125*8b2521a5SCarson Labrado inline void requestRoutesAggregationSourceCollection(App& app) 1265315c1b1SCarson Labrado { 1275315c1b1SCarson Labrado BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/") 128*8b2521a5SCarson Labrado .privileges(redfish::privileges::getAggregationSourceCollection) 129*8b2521a5SCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 130*8b2521a5SCarson Labrado handleAggregationSourceCollectionGet, std::ref(app))); 131*8b2521a5SCarson Labrado 132*8b2521a5SCarson Labrado BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/") 133*8b2521a5SCarson Labrado .privileges(redfish::privileges::getAggregationSourceCollection) 134*8b2521a5SCarson Labrado .methods(boost::beast::http::verb::head)(std::bind_front( 135*8b2521a5SCarson Labrado handleAggregationSourceCollectionHead, std::ref(app))); 136*8b2521a5SCarson Labrado } 137*8b2521a5SCarson Labrado 138*8b2521a5SCarson Labrado inline void populateAggregationSource( 139*8b2521a5SCarson Labrado const std::string& aggregationSourceId, 140*8b2521a5SCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 141*8b2521a5SCarson Labrado const boost::system::error_code ec, 142*8b2521a5SCarson Labrado const std::unordered_map<std::string, boost::urls::url>& satelliteInfo) 143*8b2521a5SCarson Labrado { 144*8b2521a5SCarson Labrado asyncResp->res.addHeader( 145*8b2521a5SCarson Labrado boost::beast::http::field::link, 146*8b2521a5SCarson Labrado "</redfish/v1/JsonSchemas/AggregationSource/AggregationSource.json>; rel=describedby"); 147*8b2521a5SCarson Labrado 148*8b2521a5SCarson Labrado // Something went wrong while querying dbus 149*8b2521a5SCarson Labrado if (ec) 150*8b2521a5SCarson Labrado { 151*8b2521a5SCarson Labrado messages::internalError(asyncResp->res); 152*8b2521a5SCarson Labrado return; 153*8b2521a5SCarson Labrado } 154*8b2521a5SCarson Labrado 155*8b2521a5SCarson Labrado const auto& sat = satelliteInfo.find(aggregationSourceId); 156*8b2521a5SCarson Labrado if (sat == satelliteInfo.end()) 157*8b2521a5SCarson Labrado { 158*8b2521a5SCarson Labrado messages::resourceNotFound(asyncResp->res, "AggregationSource", 159*8b2521a5SCarson Labrado aggregationSourceId); 160*8b2521a5SCarson Labrado return; 161*8b2521a5SCarson Labrado } 162*8b2521a5SCarson Labrado 163*8b2521a5SCarson Labrado asyncResp->res.jsonValue["@odata.id"] = 164*8b2521a5SCarson Labrado crow::utility::urlFromPieces("redfish", "v1", "AggregationService", 165*8b2521a5SCarson Labrado "AggregationSources", aggregationSourceId); 166*8b2521a5SCarson Labrado asyncResp->res.jsonValue["@odata.type"] = 167*8b2521a5SCarson Labrado "#AggregationSource.v1_3_1.AggregationSource"; 168*8b2521a5SCarson Labrado asyncResp->res.jsonValue["Id"] = aggregationSourceId; 169*8b2521a5SCarson Labrado 170*8b2521a5SCarson Labrado // TODO: We may want to change this whenever we support aggregating multiple 171*8b2521a5SCarson Labrado // satellite BMCs. Otherwise all AggregationSource resources will have the 172*8b2521a5SCarson Labrado // same "Name". 173*8b2521a5SCarson Labrado // TODO: We should use the "Name" from the satellite config whenever we add 174*8b2521a5SCarson Labrado // support for including it in the data returned in satelliteInfo. 175*8b2521a5SCarson Labrado asyncResp->res.jsonValue["Name"] = "Aggregation source"; 176*8b2521a5SCarson Labrado std::string hostName(sat->second.encoded_origin()); 177*8b2521a5SCarson Labrado asyncResp->res.jsonValue["HostName"] = std::move(hostName); 178*8b2521a5SCarson Labrado 179*8b2521a5SCarson Labrado // The Redfish spec requires Password to be null in responses 180*8b2521a5SCarson Labrado asyncResp->res.jsonValue["Password"] = nullptr; 181*8b2521a5SCarson Labrado } 182*8b2521a5SCarson Labrado 183*8b2521a5SCarson Labrado inline void handleAggregationSourceGet( 184*8b2521a5SCarson Labrado App& app, const crow::Request& req, 185*8b2521a5SCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 186*8b2521a5SCarson Labrado const std::string& aggregationSourceId) 187*8b2521a5SCarson Labrado { 188*8b2521a5SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 189*8b2521a5SCarson Labrado { 190*8b2521a5SCarson Labrado return; 191*8b2521a5SCarson Labrado } 192*8b2521a5SCarson Labrado 193*8b2521a5SCarson Labrado // Query D-Bus for satellite config corresponding to the specified 194*8b2521a5SCarson Labrado // AggregationSource 195*8b2521a5SCarson Labrado RedfishAggregator::getSatelliteConfigs(std::bind_front( 196*8b2521a5SCarson Labrado populateAggregationSource, aggregationSourceId, asyncResp)); 197*8b2521a5SCarson Labrado } 198*8b2521a5SCarson Labrado 199*8b2521a5SCarson Labrado inline void handleAggregationSourceHead( 200*8b2521a5SCarson Labrado App& app, const crow::Request& req, 201*8b2521a5SCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 202*8b2521a5SCarson Labrado const std::string& aggregationSourceId) 203*8b2521a5SCarson Labrado { 204*8b2521a5SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 205*8b2521a5SCarson Labrado { 206*8b2521a5SCarson Labrado return; 207*8b2521a5SCarson Labrado } 208*8b2521a5SCarson Labrado asyncResp->res.addHeader( 209*8b2521a5SCarson Labrado boost::beast::http::field::link, 210*8b2521a5SCarson Labrado "</redfish/v1/JsonSchemas/AggregationService/AggregationSource.json>; rel=describedby"); 211*8b2521a5SCarson Labrado 212*8b2521a5SCarson Labrado // Needed to prevent unused variable error 213*8b2521a5SCarson Labrado BMCWEB_LOG_DEBUG << "Added link header to response from " 214*8b2521a5SCarson Labrado << aggregationSourceId; 215*8b2521a5SCarson Labrado } 216*8b2521a5SCarson Labrado 217*8b2521a5SCarson Labrado inline void requestRoutesAggregationSource(App& app) 218*8b2521a5SCarson Labrado { 219*8b2521a5SCarson Labrado BMCWEB_ROUTE(app, 220*8b2521a5SCarson Labrado "/redfish/v1/AggregationService/AggregationSources/<str>/") 221*8b2521a5SCarson Labrado .privileges(redfish::privileges::getAggregationSource) 2225315c1b1SCarson Labrado .methods(boost::beast::http::verb::get)( 223*8b2521a5SCarson Labrado std::bind_front(handleAggregationSourceGet, std::ref(app))); 2245315c1b1SCarson Labrado } 2255315c1b1SCarson Labrado 2266c068982SEd Tanous } // namespace redfish 227