blob: 4b8928683ec9b42a7dc7733f746012887efa63a1 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanous6c068982023-02-07 15:44:38 -08003#pragma once
4
5#include "app.hpp"
6#include "error_messages.hpp"
7#include "http_request.hpp"
8#include "http_response.hpp"
9#include "query.hpp"
Carson Labrado8b2521a2023-02-18 02:33:14 +000010#include "redfish_aggregator.hpp"
Ed Tanous6c068982023-02-07 15:44:38 -080011#include "registries/privilege_registry.hpp"
12
Ed Tanousef4c65b2023-04-24 15:28:50 -070013#include <boost/url/format.hpp>
Ed Tanous6c068982023-02-07 15:44:38 -080014#include <nlohmann/json.hpp>
15
16#include <functional>
17#include <memory>
18
19namespace redfish
20{
21
22inline void handleAggregationServiceHead(
23 App& app, const crow::Request& req,
24 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
25{
26 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
27 {
28 return;
29 }
30 asyncResp->res.addHeader(
31 boost::beast::http::field::link,
32 "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
33}
34
35inline void handleAggregationServiceGet(
36 App& app, const crow::Request& req,
37 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
38{
39 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
40 {
41 return;
42 }
43 asyncResp->res.addHeader(
44 boost::beast::http::field::link,
45 "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
46 nlohmann::json& json = asyncResp->res.jsonValue;
47 json["@odata.id"] = "/redfish/v1/AggregationService";
48 json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService";
49 json["Id"] = "AggregationService";
50 json["Name"] = "Aggregation Service";
51 json["Description"] = "Aggregation Service";
52 json["ServiceEnabled"] = true;
Carson Labrado5315c1b2023-02-18 01:02:18 +000053 json["AggregationSources"]["@odata.id"] =
54 "/redfish/v1/AggregationService/AggregationSources";
Ed Tanous6c068982023-02-07 15:44:38 -080055}
56
Carson Labrado8b2521a2023-02-18 02:33:14 +000057inline void requestRoutesAggregationService(App& app)
Ed Tanous6c068982023-02-07 15:44:38 -080058{
59 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
60 .privileges(redfish::privileges::headAggregationService)
61 .methods(boost::beast::http::verb::head)(
62 std::bind_front(handleAggregationServiceHead, std::ref(app)));
63 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
64 .privileges(redfish::privileges::getAggregationService)
65 .methods(boost::beast::http::verb::get)(
66 std::bind_front(handleAggregationServiceGet, std::ref(app)));
67}
68
Carson Labrado8b2521a2023-02-18 02:33:14 +000069inline void populateAggregationSourceCollection(
70 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous81c4e332023-05-18 10:30:34 -070071 const boost::system::error_code& ec,
Carson Labrado8b2521a2023-02-18 02:33:14 +000072 const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
73{
74 // Something went wrong while querying dbus
75 if (ec)
76 {
77 messages::internalError(asyncResp->res);
78 return;
79 }
80 nlohmann::json::array_t members = nlohmann::json::array();
81 for (const auto& sat : satelliteInfo)
82 {
83 nlohmann::json::object_t member;
Ed Tanousef4c65b2023-04-24 15:28:50 -070084 member["@odata.id"] = boost::urls::format(
85 "/redfish/v1/AggregationService/AggregationSources/{}", sat.first);
Patrick Williamsad539542023-05-12 10:10:08 -050086 members.emplace_back(std::move(member));
Carson Labrado8b2521a2023-02-18 02:33:14 +000087 }
88 asyncResp->res.jsonValue["Members@odata.count"] = members.size();
89 asyncResp->res.jsonValue["Members"] = std::move(members);
90}
91
92inline void handleAggregationSourceCollectionGet(
Carson Labrado5315c1b2023-02-18 01:02:18 +000093 App& app, const crow::Request& req,
94 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
95{
96 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
97 {
98 return;
99 }
100 asyncResp->res.addHeader(
101 boost::beast::http::field::link,
102 "</redfish/v1/JsonSchemas/AggregationSourceCollection/AggregationSourceCollection.json>; rel=describedby");
103 nlohmann::json& json = asyncResp->res.jsonValue;
104 json["@odata.id"] = "/redfish/v1/AggregationService/AggregationSources";
105 json["@odata.type"] =
106 "#AggregationSourceCollection.AggregationSourceCollection";
107 json["Name"] = "Aggregation Source Collection";
Carson Labrado5315c1b2023-02-18 01:02:18 +0000108
Carson Labrado8b2521a2023-02-18 02:33:14 +0000109 // Query D-Bus for satellite configs and add them to the Members array
110 RedfishAggregator::getSatelliteConfigs(
111 std::bind_front(populateAggregationSourceCollection, asyncResp));
Carson Labrado5315c1b2023-02-18 01:02:18 +0000112}
113
Carson Labrado8b2521a2023-02-18 02:33:14 +0000114inline void handleAggregationSourceCollectionHead(
115 App& app, const crow::Request& req,
116 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
117{
118 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119 {
120 return;
121 }
122 asyncResp->res.addHeader(
123 boost::beast::http::field::link,
124 "</redfish/v1/JsonSchemas/AggregationService/AggregationSourceCollection.json>; rel=describedby");
125}
126
127inline void requestRoutesAggregationSourceCollection(App& app)
Carson Labrado5315c1b2023-02-18 01:02:18 +0000128{
129 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
Carson Labrado8b2521a2023-02-18 02:33:14 +0000130 .privileges(redfish::privileges::getAggregationSourceCollection)
131 .methods(boost::beast::http::verb::get)(std::bind_front(
132 handleAggregationSourceCollectionGet, std::ref(app)));
133
134 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
135 .privileges(redfish::privileges::getAggregationSourceCollection)
136 .methods(boost::beast::http::verb::head)(std::bind_front(
137 handleAggregationSourceCollectionHead, std::ref(app)));
138}
139
140inline void populateAggregationSource(
141 const std::string& aggregationSourceId,
142 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous81c4e332023-05-18 10:30:34 -0700143 const boost::system::error_code& ec,
Carson Labrado8b2521a2023-02-18 02:33:14 +0000144 const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
145{
146 asyncResp->res.addHeader(
147 boost::beast::http::field::link,
148 "</redfish/v1/JsonSchemas/AggregationSource/AggregationSource.json>; rel=describedby");
149
150 // Something went wrong while querying dbus
151 if (ec)
152 {
153 messages::internalError(asyncResp->res);
154 return;
155 }
156
157 const auto& sat = satelliteInfo.find(aggregationSourceId);
158 if (sat == satelliteInfo.end())
159 {
160 messages::resourceNotFound(asyncResp->res, "AggregationSource",
161 aggregationSourceId);
162 return;
163 }
164
Ed Tanousef4c65b2023-04-24 15:28:50 -0700165 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
166 "/redfish/v1/AggregationService/AggregationSources/{}",
167 aggregationSourceId);
Carson Labrado8b2521a2023-02-18 02:33:14 +0000168 asyncResp->res.jsonValue["@odata.type"] =
169 "#AggregationSource.v1_3_1.AggregationSource";
170 asyncResp->res.jsonValue["Id"] = aggregationSourceId;
171
172 // TODO: We may want to change this whenever we support aggregating multiple
173 // satellite BMCs. Otherwise all AggregationSource resources will have the
174 // same "Name".
175 // TODO: We should use the "Name" from the satellite config whenever we add
176 // support for including it in the data returned in satelliteInfo.
177 asyncResp->res.jsonValue["Name"] = "Aggregation source";
178 std::string hostName(sat->second.encoded_origin());
179 asyncResp->res.jsonValue["HostName"] = std::move(hostName);
180
181 // The Redfish spec requires Password to be null in responses
182 asyncResp->res.jsonValue["Password"] = nullptr;
183}
184
185inline void handleAggregationSourceGet(
186 App& app, const crow::Request& req,
187 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
188 const std::string& aggregationSourceId)
189{
190 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
191 {
192 return;
193 }
194
195 // Query D-Bus for satellite config corresponding to the specified
196 // AggregationSource
197 RedfishAggregator::getSatelliteConfigs(std::bind_front(
198 populateAggregationSource, aggregationSourceId, asyncResp));
199}
200
201inline void handleAggregationSourceHead(
202 App& app, const crow::Request& req,
203 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
204 const std::string& aggregationSourceId)
205{
206 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
207 {
208 return;
209 }
210 asyncResp->res.addHeader(
211 boost::beast::http::field::link,
212 "</redfish/v1/JsonSchemas/AggregationService/AggregationSource.json>; rel=describedby");
213
214 // Needed to prevent unused variable error
Ed Tanous62598e32023-07-17 17:06:25 -0700215 BMCWEB_LOG_DEBUG("Added link header to response from {}",
216 aggregationSourceId);
Carson Labrado8b2521a2023-02-18 02:33:14 +0000217}
218
219inline void requestRoutesAggregationSource(App& app)
220{
221 BMCWEB_ROUTE(app,
222 "/redfish/v1/AggregationService/AggregationSources/<str>/")
223 .privileges(redfish::privileges::getAggregationSource)
Carson Labrado5315c1b2023-02-18 01:02:18 +0000224 .methods(boost::beast::http::verb::get)(
Carson Labrado8b2521a2023-02-18 02:33:14 +0000225 std::bind_front(handleAggregationSourceGet, std::ref(app)));
Carson Labrado5315c1b2023-02-18 01:02:18 +0000226}
227
Ed Tanous6c068982023-02-07 15:44:38 -0800228} // namespace redfish