blob: d0fa0a66e3b6071172f25b80ddc88f288363714b [file] [log] [blame]
AppaRao Pulie5aaf042020-03-20 01:05:52 +05301/*
2// Copyright (c) 2020 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
AppaRao Pulib52664e2020-04-09 21:36:51 +053017#include "event_service_manager.hpp"
AppaRao Pulie5aaf042020-03-20 01:05:52 +053018
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Ed Tanous601c71a2021-09-08 16:40:12 -070020#include <boost/beast/http/fields.hpp>
Ed Tanouseb1c47d2022-02-09 11:47:27 -080021#include <http/utility.hpp>
22#include <logging.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
25
Patrick Williams1e270c52021-12-04 06:06:56 -060026#include <span>
27
AppaRao Pulie5aaf042020-03-20 01:05:52 +053028namespace redfish
29{
30
AppaRao Puli156d6b02020-04-25 06:04:05 +053031static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
32 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053033static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053034 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053035static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
36 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
37
Sunitha Harishe56f2542020-07-22 02:38:59 -050038#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
39static constexpr const std::array<const char*, 2> supportedResourceTypes = {
40 "IBMConfigFile", "Task"};
41#else
42static constexpr const std::array<const char*, 1> supportedResourceTypes = {
43 "Task"};
44#endif
45
AppaRao Pulie5aaf042020-03-20 01:05:52 +053046static constexpr const uint8_t maxNoOfSubscriptions = 20;
47
John Edward Broadbent7e860f12021-04-08 15:57:16 -070048inline void requestRoutesEventService(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +053049{
John Edward Broadbent7e860f12021-04-08 15:57:16 -070050 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070051 .privileges(redfish::privileges::getEventService)
Ed Tanous002d39b2022-05-31 08:59:27 -070052 .methods(boost::beast::http::verb::get)(
53 [&app](const crow::Request& req,
54 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
55 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
56 {
57 return;
58 }
Ed Tanous14766872022-03-15 10:44:42 -070059
Ed Tanous002d39b2022-05-31 08:59:27 -070060 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
61 asyncResp->res.jsonValue["@odata.type"] =
62 "#EventService.v1_5_0.EventService";
63 asyncResp->res.jsonValue["Id"] = "EventService";
64 asyncResp->res.jsonValue["Name"] = "Event Service";
65 asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
66 "/redfish/v1/EventService/Subscriptions";
67 asyncResp->res
68 .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
69 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
AppaRao Pulie5aaf042020-03-20 01:05:52 +053070
Ed Tanous002d39b2022-05-31 08:59:27 -070071 const persistent_data::EventServiceConfig eventServiceConfig =
72 persistent_data::EventServiceStore::getInstance()
73 .getEventServiceConfig();
zhanghch058d1b46d2021-04-01 11:18:24 +080074
Ed Tanous002d39b2022-05-31 08:59:27 -070075 asyncResp->res.jsonValue["Status"]["State"] =
76 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
77 asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
78 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
79 eventServiceConfig.retryAttempts;
80 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
81 eventServiceConfig.retryTimeoutInterval;
82 asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
83 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
84 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053085
Ed Tanous002d39b2022-05-31 08:59:27 -070086 nlohmann::json supportedSSEFilters = {
87 {"EventFormatType", true}, {"MessageId", true},
88 {"MetricReportDefinition", true}, {"RegistryPrefix", true},
89 {"OriginResource", false}, {"ResourceType", false}};
AppaRao Puli7d1cc382020-05-16 02:42:22 +053090
Ed Tanous002d39b2022-05-31 08:59:27 -070091 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
92 supportedSSEFilters;
George Liu0fda0f12021-11-16 10:06:17 +080093 });
Ayushi Smriti07941a82020-05-21 15:55:34 +053094
John Edward Broadbent7e860f12021-04-08 15:57:16 -070095 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070096 .privileges(redfish::privileges::patchEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -070097 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -070098 [&app](const crow::Request& req,
99 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700100 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
101 {
102 return;
103 }
104 std::optional<bool> serviceEnabled;
105 std::optional<uint32_t> retryAttemps;
106 std::optional<uint32_t> retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530107
Ed Tanous002d39b2022-05-31 08:59:27 -0700108 if (!json_util::readJsonPatch(
109 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
110 "DeliveryRetryAttempts", retryAttemps,
111 "DeliveryRetryIntervalSeconds", retryInterval))
112 {
113 return;
114 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530115
Ed Tanous002d39b2022-05-31 08:59:27 -0700116 persistent_data::EventServiceConfig eventServiceConfig =
117 persistent_data::EventServiceStore::getInstance()
118 .getEventServiceConfig();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700119
Ed Tanous002d39b2022-05-31 08:59:27 -0700120 if (serviceEnabled)
121 {
122 eventServiceConfig.enabled = *serviceEnabled;
123 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500124
Ed Tanous002d39b2022-05-31 08:59:27 -0700125 if (retryAttemps)
126 {
127 // Supported range [1-3]
128 if ((*retryAttemps < 1) || (*retryAttemps > 3))
129 {
130 messages::queryParameterOutOfRange(
131 asyncResp->res, std::to_string(*retryAttemps),
132 "DeliveryRetryAttempts", "[1-3]");
133 }
134 else
135 {
136 eventServiceConfig.retryAttempts = *retryAttemps;
137 }
138 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530139
Ed Tanous002d39b2022-05-31 08:59:27 -0700140 if (retryInterval)
141 {
142 // Supported range [30 - 180]
143 if ((*retryInterval < 30) || (*retryInterval > 180))
144 {
145 messages::queryParameterOutOfRange(
146 asyncResp->res, std::to_string(*retryInterval),
147 "DeliveryRetryIntervalSeconds", "[30-180]");
148 }
149 else
150 {
151 eventServiceConfig.retryTimeoutInterval = *retryInterval;
152 }
153 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700154
Ed Tanous002d39b2022-05-31 08:59:27 -0700155 EventServiceManager::getInstance().setEventServiceConfig(
156 eventServiceConfig);
157 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700158}
159
160inline void requestRoutesSubmitTestEvent(App& app)
161{
162
163 BMCWEB_ROUTE(
164 app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
Ed Tanoused398212021-06-09 17:05:54 -0700165 .privileges(redfish::privileges::postEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700166 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700167 [&app](const crow::Request& req,
168 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700169 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
170 {
171 return;
172 }
173 if (!EventServiceManager::getInstance().sendTestEventLog())
174 {
175 messages::serviceDisabled(asyncResp->res,
176 "/redfish/v1/EventService/");
177 return;
178 }
179 asyncResp->res.result(boost::beast::http::status::no_content);
180 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700181}
182
183inline void requestRoutesEventDestinationCollection(App& app)
184{
Gayathri Leburu1ebe3e42022-02-09 10:45:19 +0000185 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Ed Tanoused398212021-06-09 17:05:54 -0700186 .privileges(redfish::privileges::getEventDestinationCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700187 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700188 [&app](const crow::Request& req,
189 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700190 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
191 {
192 return;
193 }
194 asyncResp->res.jsonValue["@odata.type"] =
195 "#EventDestinationCollection.EventDestinationCollection";
196 asyncResp->res.jsonValue["@odata.id"] =
197 "/redfish/v1/EventService/Subscriptions";
198 asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700199
Ed Tanous002d39b2022-05-31 08:59:27 -0700200 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700201
Ed Tanous002d39b2022-05-31 08:59:27 -0700202 std::vector<std::string> subscripIds =
203 EventServiceManager::getInstance().getAllIDs();
204 memberArray = nlohmann::json::array();
205 asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700206
Ed Tanous002d39b2022-05-31 08:59:27 -0700207 for (const std::string& id : subscripIds)
208 {
209 nlohmann::json::object_t member;
210 member["@odata.id"] =
211 "/redfish/v1/EventService/Subscriptions/" + id;
212 memberArray.push_back(std::move(member));
213 }
214 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700215 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500216 .privileges(redfish::privileges::postEventDestinationCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700217 .methods(boost::beast::http::verb::post)(
218 [&app](const crow::Request& req,
219 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
220 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
221 {
222 return;
223 }
224 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
225 maxNoOfSubscriptions)
226 {
227 messages::eventSubscriptionLimitExceeded(asyncResp->res);
228 return;
229 }
230 std::string destUrl;
231 std::string protocol;
232 std::optional<std::string> context;
233 std::optional<std::string> subscriptionType;
234 std::optional<std::string> eventFormatType2;
235 std::optional<std::string> retryPolicy;
236 std::optional<std::vector<std::string>> msgIds;
237 std::optional<std::vector<std::string>> regPrefixes;
238 std::optional<std::vector<std::string>> resTypes;
239 std::optional<std::vector<nlohmann::json>> headers;
240 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800241
Ed Tanous002d39b2022-05-31 08:59:27 -0700242 if (!json_util::readJsonPatch(
243 req, asyncResp->res, "Destination", destUrl, "Context", context,
244 "Protocol", protocol, "SubscriptionType", subscriptionType,
245 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
246 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
247 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
248 mrdJsonArray, "ResourceTypes", resTypes))
249 {
250 return;
251 }
252
253 if (regPrefixes && msgIds)
254 {
255 if (!regPrefixes->empty() && !msgIds->empty())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800256 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700257 messages::propertyValueConflict(asyncResp->res, "MessageIds",
258 "RegistryPrefixes");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800259 return;
260 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700261 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800262
Ed Tanous002d39b2022-05-31 08:59:27 -0700263 std::string host;
264 std::string urlProto;
265 uint16_t port = 0;
266 std::string path;
267
268 if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, port,
269 path))
270 {
271 BMCWEB_LOG_WARNING
272 << "Failed to validate and split destination url";
273 messages::propertyValueFormatError(asyncResp->res, destUrl,
274 "Destination");
275 return;
276 }
277
278 if (path.empty())
279 {
280 path = "/";
281 }
282 std::shared_ptr<Subscription> subValue =
283 std::make_shared<Subscription>(host, port, path, urlProto);
284
285 subValue->destinationUrl = destUrl;
286
287 if (subscriptionType)
288 {
289 if (*subscriptionType != "RedfishEvent")
Ed Tanousfffb8c12022-02-07 23:53:03 -0800290 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700291 messages::propertyValueNotInList(
292 asyncResp->res, *subscriptionType, "SubscriptionType");
293 return;
294 }
295 subValue->subscriptionType = *subscriptionType;
296 }
297 else
298 {
299 subValue->subscriptionType = "RedfishEvent"; // Default
300 }
301
302 if (protocol != "Redfish")
303 {
304 messages::propertyValueNotInList(asyncResp->res, protocol,
305 "Protocol");
306 return;
307 }
308 subValue->protocol = protocol;
309
310 if (eventFormatType2)
311 {
312 if (std::find(supportedEvtFormatTypes.begin(),
313 supportedEvtFormatTypes.end(),
314 *eventFormatType2) == supportedEvtFormatTypes.end())
315 {
316 messages::propertyValueNotInList(
317 asyncResp->res, *eventFormatType2, "EventFormatType");
318 return;
319 }
320 subValue->eventFormatType = *eventFormatType2;
321 }
322 else
323 {
324 // If not specified, use default "Event"
325 subValue->eventFormatType = "Event";
326 }
327
328 if (context)
329 {
330 subValue->customText = *context;
331 }
332
333 if (headers)
334 {
335 for (const nlohmann::json& headerChunk : *headers)
336 {
337 for (const auto& item : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700338 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700339 const std::string* value =
340 item.value().get_ptr<const std::string*>();
341 if (value == nullptr)
342 {
343 messages::propertyValueFormatError(
344 asyncResp->res, item.value().dump(2, 1),
345 "HttpHeaders/" + item.key());
346 return;
347 }
348 subValue->httpHeaders.set(item.key(), *value);
349 }
350 }
351 }
352
353 if (regPrefixes)
354 {
355 for (const std::string& it : *regPrefixes)
356 {
357 if (std::find(supportedRegPrefixes.begin(),
358 supportedRegPrefixes.end(),
359 it) == supportedRegPrefixes.end())
360 {
361 messages::propertyValueNotInList(asyncResp->res, it,
362 "RegistryPrefixes");
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530363 return;
364 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800365 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700366 subValue->registryPrefixes = *regPrefixes;
367 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530368
Ed Tanous002d39b2022-05-31 08:59:27 -0700369 if (resTypes)
370 {
371 for (const std::string& it : *resTypes)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800372 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700373 if (std::find(supportedResourceTypes.begin(),
374 supportedResourceTypes.end(),
375 it) == supportedResourceTypes.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700376 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700377 messages::propertyValueNotInList(asyncResp->res, it,
378 "ResourceTypes");
AppaRao Puli144b6312020-08-03 22:23:12 +0530379 return;
380 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700381 }
382 subValue->resourceTypes = *resTypes;
383 }
384
385 if (msgIds)
386 {
387 std::vector<std::string> registryPrefix;
388
389 // If no registry prefixes are mentioned, consider all
390 // supported prefixes
391 if (subValue->registryPrefixes.empty())
392 {
393 registryPrefix.assign(supportedRegPrefixes.begin(),
394 supportedRegPrefixes.end());
Ed Tanousfffb8c12022-02-07 23:53:03 -0800395 }
396 else
397 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700398 registryPrefix = subValue->registryPrefixes;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800399 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530400
Ed Tanous002d39b2022-05-31 08:59:27 -0700401 for (const std::string& id : *msgIds)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800402 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700403 bool validId = false;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800404
Ed Tanous002d39b2022-05-31 08:59:27 -0700405 // Check for Message ID in each of the selected Registry
406 for (const std::string& it : registryPrefix)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700407 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700408 const std::span<const redfish::registries::MessageEntry>
409 registry =
410 redfish::registries::getRegistryFromPrefix(it);
411
412 if (std::any_of(
413 registry.begin(), registry.end(),
414 [&id](const redfish::registries::MessageEntry&
415 messageEntry) {
416 return id == messageEntry.first;
417 }))
418 {
419 validId = true;
420 break;
421 }
422 }
423
424 if (!validId)
425 {
426 messages::propertyValueNotInList(asyncResp->res, id,
427 "MessageIds");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800428 return;
429 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800430 }
431
Ed Tanous002d39b2022-05-31 08:59:27 -0700432 subValue->registryMsgIds = *msgIds;
433 }
434
435 if (retryPolicy)
436 {
437 if (std::find(supportedRetryPolicies.begin(),
438 supportedRetryPolicies.end(),
439 *retryPolicy) == supportedRetryPolicies.end())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800440 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700441 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
442 "DeliveryRetryPolicy");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800443 return;
444 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700445 subValue->retryPolicy = *retryPolicy;
446 }
447 else
448 {
449 // Default "TerminateAfterRetries"
450 subValue->retryPolicy = "TerminateAfterRetries";
451 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800452
Ed Tanous002d39b2022-05-31 08:59:27 -0700453 if (mrdJsonArray)
454 {
455 for (nlohmann::json& mrdObj : *mrdJsonArray)
456 {
457 std::string mrdUri;
458
459 if (!json_util::readJson(mrdObj, asyncResp->res, "@odata.id",
460 mrdUri))
461
462 {
463 return;
464 }
465 subValue->metricReportDefinitions.emplace_back(mrdUri);
466 }
467 }
468
469 std::string id =
470 EventServiceManager::getInstance().addSubscription(subValue);
471 if (id.empty())
472 {
473 messages::internalError(asyncResp->res);
474 return;
475 }
476
477 messages::created(asyncResp->res);
478 asyncResp->res.addHeader(
479 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
Ed Tanousfffb8c12022-02-07 23:53:03 -0800480 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700481}
482
483inline void requestRoutesEventDestination(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530484{
Ravi Teja9d41aec2021-07-23 01:57:01 -0500485 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700486 .privileges(redfish::privileges::getEventDestination)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700487 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700488 [&app](const crow::Request& req,
489 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
490 const std::string& param) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700491 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
492 {
493 return;
494 }
495 std::shared_ptr<Subscription> subValue =
496 EventServiceManager::getInstance().getSubscription(param);
497 if (subValue == nullptr)
498 {
499 asyncResp->res.result(boost::beast::http::status::not_found);
500 return;
501 }
502 const std::string& id = param;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530503
Ed Tanous002d39b2022-05-31 08:59:27 -0700504 asyncResp->res.jsonValue["@odata.type"] =
505 "#EventDestination.v1_7_0.EventDestination";
506 asyncResp->res.jsonValue["Protocol"] = "Redfish";
507 asyncResp->res.jsonValue["@odata.id"] =
508 "/redfish/v1/EventService/Subscriptions/" + id;
509 asyncResp->res.jsonValue["Id"] = id;
510 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
511 asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
512 asyncResp->res.jsonValue["Context"] = subValue->customText;
513 asyncResp->res.jsonValue["SubscriptionType"] =
514 subValue->subscriptionType;
515 asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
516 asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
517 asyncResp->res.jsonValue["RegistryPrefixes"] =
518 subValue->registryPrefixes;
519 asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
zhanghch058d1b46d2021-04-01 11:18:24 +0800520
Ed Tanous002d39b2022-05-31 08:59:27 -0700521 asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
522 asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530523
Ed Tanous002d39b2022-05-31 08:59:27 -0700524 nlohmann::json::array_t mrdJsonArray;
525 for (const auto& mdrUri : subValue->metricReportDefinitions)
526 {
527 nlohmann::json::object_t mdr;
528 mdr["@odata.id"] = mdrUri;
529 mrdJsonArray.emplace_back(std::move(mdr));
530 }
531 asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
532 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500533 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700534 // The below privilege is wrong, it should be ConfigureManager OR
535 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500536 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700537 //.privileges(redfish::privileges::patchEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700538 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700539 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700540 [&app](const crow::Request& req,
541 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
542 const std::string& param) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700543 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
544 {
545 return;
546 }
547 std::shared_ptr<Subscription> subValue =
548 EventServiceManager::getInstance().getSubscription(param);
549 if (subValue == nullptr)
550 {
551 asyncResp->res.result(boost::beast::http::status::not_found);
552 return;
553 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530554
Ed Tanous002d39b2022-05-31 08:59:27 -0700555 std::optional<std::string> context;
556 std::optional<std::string> retryPolicy;
557 std::optional<std::vector<nlohmann::json>> headers;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500558
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
560 "DeliveryRetryPolicy", retryPolicy,
561 "HttpHeaders", headers))
562 {
563 return;
564 }
AppaRao Puli144b6312020-08-03 22:23:12 +0530565
Ed Tanous002d39b2022-05-31 08:59:27 -0700566 if (context)
567 {
568 subValue->customText = *context;
569 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530570
Ed Tanous002d39b2022-05-31 08:59:27 -0700571 if (headers)
572 {
573 boost::beast::http::fields fields;
574 for (const nlohmann::json& headerChunk : *headers)
575 {
576 for (auto& it : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700577 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700578 const std::string* value =
579 it.value().get_ptr<const std::string*>();
580 if (value == nullptr)
Ed Tanous601c71a2021-09-08 16:40:12 -0700581 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700582 messages::propertyValueFormatError(
583 asyncResp->res, it.value().dump(2, ' ', true),
584 "HttpHeaders/" + it.key());
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700585 return;
586 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700587 fields.set(it.key(), *value);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700588 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700589 }
590 subValue->httpHeaders = fields;
591 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530592
Ed Tanous002d39b2022-05-31 08:59:27 -0700593 if (retryPolicy)
594 {
595 if (std::find(supportedRetryPolicies.begin(),
596 supportedRetryPolicies.end(),
597 *retryPolicy) == supportedRetryPolicies.end())
598 {
599 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
600 "DeliveryRetryPolicy");
601 return;
602 }
603 subValue->retryPolicy = *retryPolicy;
604 subValue->updateRetryPolicy();
605 }
606
607 EventServiceManager::getInstance().updateSubscriptionData();
608 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500609 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700610 // The below privilege is wrong, it should be ConfigureManager OR
611 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500612 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700613 //.privileges(redfish::privileges::deleteEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700614 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700615 .methods(boost::beast::http::verb::delete_)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700616 [&app](const crow::Request& req,
617 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
618 const std::string& param) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700619 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
620 {
621 return;
622 }
623 if (!EventServiceManager::getInstance().isSubscriptionExist(param))
624 {
625 asyncResp->res.result(boost::beast::http::status::not_found);
626 return;
627 }
628 EventServiceManager::getInstance().deleteSubscription(param);
629 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700630}
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530631
632} // namespace redfish