blob: 04ca735070542b7fb9800b20e412b41cd8bf3293 [file] [log] [blame]
AppaRao Pulie5aaf042020-03-20 01:05:52 +05301/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2020 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
AppaRao Pulie5aaf042020-03-20 01:05:52 +053015*/
16#pragma once
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080017#include "app.hpp"
AppaRao Pulib52664e2020-04-09 21:36:51 +053018#include "event_service_manager.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070019#include "generated/enums/event_service.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "http/utility.hpp"
21#include "logging.hpp"
22#include "query.hpp"
Alexander Hansend109e2b2024-11-18 14:38:06 +010023#include "registries.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "registries/privilege_registry.hpp"
Alexander Hansend109e2b2024-11-18 14:38:06 +010025#include "registries_selector.hpp"
Chicago Duan3d307082020-11-26 14:12:12 +080026#include "snmp_trap_event_clients.hpp"
Alexander Hansend109e2b2024-11-18 14:38:06 +010027#include "utils/json_utils.hpp"
AppaRao Pulie5aaf042020-03-20 01:05:52 +053028
Ed Tanous601c71a2021-09-08 16:40:12 -070029#include <boost/beast/http/fields.hpp>
Chicago Duan3d307082020-11-26 14:12:12 +080030#include <boost/system/error_code.hpp>
Ed Tanousa716aa72023-08-01 11:35:53 -070031#include <boost/url/parse.hpp>
Chicago Duan3d307082020-11-26 14:12:12 +080032#include <sdbusplus/unpack_properties.hpp>
33#include <utils/dbus_utils.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070034
Chicago Duan3d307082020-11-26 14:12:12 +080035#include <charconv>
36#include <memory>
Myung Bae5064a252024-10-04 09:34:25 -070037#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070038#include <ranges>
Patrick Williams1e270c52021-12-04 06:06:56 -060039#include <span>
Chicago Duan3d307082020-11-26 14:12:12 +080040#include <string>
Ed Tanousa14c9112024-09-04 10:46:47 -070041#include <vector>
Patrick Williams1e270c52021-12-04 06:06:56 -060042
AppaRao Pulie5aaf042020-03-20 01:05:52 +053043namespace redfish
44{
45
AppaRao Puli156d6b02020-04-25 06:04:05 +053046static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
47 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053048static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053049 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053050static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
51 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
52
Sunitha Harishe56f2542020-07-22 02:38:59 -050053static constexpr const std::array<const char*, 1> supportedResourceTypes = {
54 "Task"};
Sunitha Harishe56f2542020-07-22 02:38:59 -050055
John Edward Broadbent7e860f12021-04-08 15:57:16 -070056inline void requestRoutesEventService(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +053057{
John Edward Broadbent7e860f12021-04-08 15:57:16 -070058 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070059 .privileges(redfish::privileges::getEventService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -040060 .methods(
61 boost::beast::http::verb::
62 get)([&app](
63 const crow::Request& req,
64 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
65 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
66 {
67 return;
68 }
Ed Tanous14766872022-03-15 10:44:42 -070069
Patrick Williamsbd79bce2024-08-16 15:22:20 -040070 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
71 asyncResp->res.jsonValue["@odata.type"] =
72 "#EventService.v1_5_0.EventService";
73 asyncResp->res.jsonValue["Id"] = "EventService";
74 asyncResp->res.jsonValue["Name"] = "Event Service";
75 asyncResp->res.jsonValue["ServerSentEventUri"] =
76 "/redfish/v1/EventService/SSE";
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000077
Patrick Williamsbd79bce2024-08-16 15:22:20 -040078 asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
79 "/redfish/v1/EventService/Subscriptions";
80 asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"]
81 ["target"] =
82 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
AppaRao Pulie5aaf042020-03-20 01:05:52 +053083
Patrick Williamsbd79bce2024-08-16 15:22:20 -040084 const persistent_data::EventServiceConfig eventServiceConfig =
85 persistent_data::EventServiceStore::getInstance()
86 .getEventServiceConfig();
zhanghch058d1b46d2021-04-01 11:18:24 +080087
Patrick Williamsbd79bce2024-08-16 15:22:20 -040088 asyncResp->res.jsonValue["Status"]["State"] =
89 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
90 asyncResp->res.jsonValue["ServiceEnabled"] =
91 eventServiceConfig.enabled;
92 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
93 eventServiceConfig.retryAttempts;
94 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
95 eventServiceConfig.retryTimeoutInterval;
96 asyncResp->res.jsonValue["EventFormatTypes"] =
97 supportedEvtFormatTypes;
98 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
99 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530100
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400101 nlohmann::json::object_t supportedSSEFilters;
102 supportedSSEFilters["EventFormatType"] = true;
103 supportedSSEFilters["MessageId"] = true;
104 supportedSSEFilters["MetricReportDefinition"] = true;
105 supportedSSEFilters["RegistryPrefix"] = true;
106 supportedSSEFilters["OriginResource"] = false;
107 supportedSSEFilters["ResourceType"] = false;
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530108
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400109 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
110 std::move(supportedSSEFilters);
111 });
Ayushi Smriti07941a82020-05-21 15:55:34 +0530112
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700113 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -0700114 .privileges(redfish::privileges::patchEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700115 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700116 [&app](const crow::Request& req,
117 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400118 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119 {
120 return;
121 }
122 std::optional<bool> serviceEnabled;
123 std::optional<uint32_t> retryAttemps;
124 std::optional<uint32_t> retryInterval;
Myung Baeafc474a2024-10-09 00:53:29 -0700125 if (!json_util::readJsonPatch( //
126 req, asyncResp->res, //
127 "DeliveryRetryAttempts", retryAttemps, //
128 "DeliveryRetryIntervalSeconds", retryInterval, //
129 "ServiceEnabled", serviceEnabled //
130 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400131 {
132 return;
133 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530134
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400135 persistent_data::EventServiceConfig eventServiceConfig =
136 persistent_data::EventServiceStore::getInstance()
137 .getEventServiceConfig();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700138
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400139 if (serviceEnabled)
140 {
141 eventServiceConfig.enabled = *serviceEnabled;
142 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500143
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400144 if (retryAttemps)
145 {
146 // Supported range [1-3]
147 if ((*retryAttemps < 1) || (*retryAttemps > 3))
148 {
149 messages::queryParameterOutOfRange(
150 asyncResp->res, std::to_string(*retryAttemps),
151 "DeliveryRetryAttempts", "[1-3]");
152 }
153 else
154 {
155 eventServiceConfig.retryAttempts = *retryAttemps;
156 }
157 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530158
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400159 if (retryInterval)
160 {
161 // Supported range [5 - 180]
162 if ((*retryInterval < 5) || (*retryInterval > 180))
163 {
164 messages::queryParameterOutOfRange(
165 asyncResp->res, std::to_string(*retryInterval),
166 "DeliveryRetryIntervalSeconds", "[5-180]");
167 }
168 else
169 {
170 eventServiceConfig.retryTimeoutInterval =
171 *retryInterval;
172 }
173 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700174
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400175 EventServiceManager::getInstance().setEventServiceConfig(
176 eventServiceConfig);
177 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700178}
179
180inline void requestRoutesSubmitTestEvent(App& app)
181{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700182 BMCWEB_ROUTE(
183 app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
Ed Tanoused398212021-06-09 17:05:54 -0700184 .privileges(redfish::privileges::postEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700185 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700186 [&app](const crow::Request& req,
187 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400188 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
189 {
190 return;
191 }
192 if (!EventServiceManager::getInstance().sendTestEventLog())
193 {
194 messages::serviceDisabled(asyncResp->res,
195 "/redfish/v1/EventService/");
196 return;
197 }
198 asyncResp->res.result(boost::beast::http::status::no_content);
199 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700200}
201
Chicago Duan3d307082020-11-26 14:12:12 +0800202inline void doSubscriptionCollection(
Ed Tanouse81de512023-06-27 17:07:00 -0700203 const boost::system::error_code& ec,
Chicago Duan3d307082020-11-26 14:12:12 +0800204 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
205 const dbus::utility::ManagedObjectType& resp)
206{
207 if (ec)
208 {
Ed Tanous13061012023-07-25 11:12:19 -0700209 if (ec.value() == EBADR || ec.value() == EHOSTUNREACH)
Chicago Duan3d307082020-11-26 14:12:12 +0800210 {
211 // This is an optional process so just return if it isn't there
212 return;
213 }
214
Ed Tanous62598e32023-07-17 17:06:25 -0700215 BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec);
Chicago Duan3d307082020-11-26 14:12:12 +0800216 messages::internalError(asyncResp->res);
217 return;
218 }
219 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
220 for (const auto& objpath : resp)
221 {
222 sdbusplus::message::object_path path(objpath.first);
223 const std::string snmpId = path.filename();
224 if (snmpId.empty())
225 {
Ed Tanous62598e32023-07-17 17:06:25 -0700226 BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
Chicago Duan3d307082020-11-26 14:12:12 +0800227 messages::internalError(asyncResp->res);
228 return;
229 }
230
231 getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
232 }
233}
234
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700235inline void requestRoutesEventDestinationCollection(App& app)
236{
Gayathri Leburu1ebe3e42022-02-09 10:45:19 +0000237 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Ed Tanoused398212021-06-09 17:05:54 -0700238 .privileges(redfish::privileges::getEventDestinationCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700239 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700240 [&app](const crow::Request& req,
241 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400242 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
243 {
244 return;
245 }
246 asyncResp->res.jsonValue["@odata.type"] =
247 "#EventDestinationCollection.EventDestinationCollection";
248 asyncResp->res.jsonValue["@odata.id"] =
249 "/redfish/v1/EventService/Subscriptions";
250 asyncResp->res.jsonValue["Name"] =
251 "Event Destination Collections";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700252
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400253 nlohmann::json& memberArray =
254 asyncResp->res.jsonValue["Members"];
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700255
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400256 std::vector<std::string> subscripIds =
257 EventServiceManager::getInstance().getAllIDs();
258 memberArray = nlohmann::json::array();
259 asyncResp->res.jsonValue["Members@odata.count"] =
260 subscripIds.size();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700261
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400262 for (const std::string& id : subscripIds)
263 {
264 nlohmann::json::object_t member;
265 member["@odata.id"] = boost::urls::format(
266 "/redfish/v1/EventService/Subscriptions/{}" + id);
267 memberArray.emplace_back(std::move(member));
268 }
269 crow::connections::systemBus->async_method_call(
270 [asyncResp](const boost::system::error_code& ec,
271 const dbus::utility::ManagedObjectType& resp) {
272 doSubscriptionCollection(ec, asyncResp, resp);
273 },
274 "xyz.openbmc_project.Network.SNMP",
275 "/xyz/openbmc_project/network/snmp/manager",
276 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
277 });
Chicago Duan3d307082020-11-26 14:12:12 +0800278
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700279 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500280 .privileges(redfish::privileges::postEventDestinationCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400281 .methods(
282 boost::beast::http::verb::
283 post)([&app](
284 const crow::Request& req,
285 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
286 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
287 {
288 return;
289 }
290 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
291 maxNoOfSubscriptions)
292 {
293 messages::eventSubscriptionLimitExceeded(asyncResp->res);
294 return;
295 }
296 std::string destUrl;
297 std::string protocol;
298 std::optional<bool> verifyCertificate;
299 std::optional<std::string> context;
300 std::optional<std::string> subscriptionType;
301 std::optional<std::string> eventFormatType2;
302 std::optional<std::string> retryPolicy;
Myung Bae5064a252024-10-04 09:34:25 -0700303 std::optional<bool> sendHeartbeat;
304 std::optional<uint64_t> hbIntervalMinutes;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400305 std::optional<std::vector<std::string>> msgIds;
306 std::optional<std::vector<std::string>> regPrefixes;
Ed Tanousa14c9112024-09-04 10:46:47 -0700307 std::optional<std::vector<std::string>> originResources;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400308 std::optional<std::vector<std::string>> resTypes;
309 std::optional<std::vector<nlohmann::json::object_t>> headers;
310 std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800311
Myung Baeafc474a2024-10-09 00:53:29 -0700312 if (!json_util::readJsonPatch( //
313 req, asyncResp->res, //
314 "Context", context, //
315 "DeliveryRetryPolicy", retryPolicy, //
316 "Destination", destUrl, //
317 "EventFormatType", eventFormatType2, //
Myung Bae5064a252024-10-04 09:34:25 -0700318 "HeartbeatIntervalMinutes", hbIntervalMinutes, //
Myung Baeafc474a2024-10-09 00:53:29 -0700319 "HttpHeaders", headers, //
320 "MessageIds", msgIds, //
321 "MetricReportDefinitions", mrdJsonArray, //
322 "OriginResources", originResources, //
323 "Protocol", protocol, //
324 "RegistryPrefixes", regPrefixes, //
325 "ResourceTypes", resTypes, //
Myung Bae5064a252024-10-04 09:34:25 -0700326 "SendHeartbeat", sendHeartbeat, //
Myung Baeafc474a2024-10-09 00:53:29 -0700327 "SubscriptionType", subscriptionType, //
328 "VerifyCertificate", verifyCertificate //
329 ))
Ed Tanousfffb8c12022-02-07 23:53:03 -0800330 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700331 return;
332 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700333 // clang-format on
Chicago Duan3d307082020-11-26 14:12:12 +0800334
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400335 // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
336 static constexpr const uint16_t maxDestinationSize = 2000;
337 if (destUrl.size() > maxDestinationSize)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800338 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400339 messages::stringValueTooLong(asyncResp->res, "Destination",
340 maxDestinationSize);
Ed Tanous002d39b2022-05-31 08:59:27 -0700341 return;
342 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700343
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400344 if (regPrefixes && msgIds)
Ed Tanous002d39b2022-05-31 08:59:27 -0700345 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400346 if (!regPrefixes->empty() && !msgIds->empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700347 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400348 messages::propertyValueConflict(
349 asyncResp->res, "MessageIds", "RegistryPrefixes");
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530350 return;
351 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800352 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530353
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400354 boost::system::result<boost::urls::url> url =
355 boost::urls::parse_absolute_uri(destUrl);
356 if (!url)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800357 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400358 BMCWEB_LOG_WARNING(
359 "Failed to validate and split destination url");
360 messages::propertyValueFormatError(asyncResp->res, destUrl,
361 "Destination");
362 return;
363 }
364 url->normalize();
George Liub07942e2024-11-01 09:59:40 +0800365
366 // port_number returns zero if it is not a valid representable port
367 if (url->has_port() && url->port_number() == 0)
368 {
369 BMCWEB_LOG_WARNING("{} is an invalid port in destination url",
370 url->port());
371 messages::propertyValueFormatError(asyncResp->res, destUrl,
372 "Destination");
373 return;
374 }
375
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400376 crow::utility::setProtocolDefaults(*url, protocol);
377 crow::utility::setPortDefaults(*url);
378
379 if (url->path().empty())
380 {
381 url->set_path("/");
382 }
383
384 if (url->has_userinfo())
385 {
386 messages::propertyValueFormatError(asyncResp->res, destUrl,
387 "Destination");
388 return;
389 }
390
391 if (protocol == "SNMPv2c")
392 {
393 if (context)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700394 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400395 messages::propertyValueConflict(asyncResp->res, "Context",
396 "Protocol");
AppaRao Puli144b6312020-08-03 22:23:12 +0530397 return;
398 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400399 if (eventFormatType2)
400 {
401 messages::propertyValueConflict(
402 asyncResp->res, "EventFormatType", "Protocol");
403 return;
404 }
405 if (retryPolicy)
406 {
407 messages::propertyValueConflict(asyncResp->res,
408 "RetryPolicy", "Protocol");
409 return;
410 }
Myung Bae5064a252024-10-04 09:34:25 -0700411 if (sendHeartbeat)
412 {
413 messages::propertyValueConflict(
414 asyncResp->res, "SendHeartbeat", "Protocol");
415 return;
416 }
417 if (hbIntervalMinutes)
418 {
419 messages::propertyValueConflict(
420 asyncResp->res, "HeartbeatIntervalMinutes", "Protocol");
421 return;
422 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400423 if (msgIds)
424 {
425 messages::propertyValueConflict(asyncResp->res,
426 "MessageIds", "Protocol");
427 return;
428 }
429 if (regPrefixes)
430 {
431 messages::propertyValueConflict(
432 asyncResp->res, "RegistryPrefixes", "Protocol");
433 return;
434 }
435 if (resTypes)
436 {
437 messages::propertyValueConflict(
438 asyncResp->res, "ResourceTypes", "Protocol");
439 return;
440 }
441 if (headers)
442 {
443 messages::propertyValueConflict(asyncResp->res,
444 "HttpHeaders", "Protocol");
445 return;
446 }
447 if (mrdJsonArray)
448 {
449 messages::propertyValueConflict(
450 asyncResp->res, "MetricReportDefinitions", "Protocol");
451 return;
452 }
453 if (url->scheme() != "snmp")
454 {
455 messages::propertyValueConflict(asyncResp->res,
456 "Destination", "Protocol");
457 return;
458 }
459
460 addSnmpTrapClient(asyncResp, url->host_address(),
461 url->port_number());
462 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700463 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700464
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400465 std::shared_ptr<Subscription> subValue =
Myung Bae21a94d52024-10-14 15:02:57 -0700466 std::make_shared<Subscription>(
Myung Bae5fe4ef32024-10-19 09:56:02 -0400467 std::make_shared<persistent_data::UserSubscription>(), *url,
468 app.ioContext());
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400469
470 if (subscriptionType)
Ed Tanous002d39b2022-05-31 08:59:27 -0700471 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400472 if (*subscriptionType != "RedfishEvent")
473 {
474 messages::propertyValueNotInList(
475 asyncResp->res, *subscriptionType, "SubscriptionType");
476 return;
477 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400478 subValue->userSub->subscriptionType = *subscriptionType;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800479 }
480 else
481 {
Ed Tanous4b712a22023-08-02 12:56:52 -0700482 // Default
Myung Bae5fe4ef32024-10-19 09:56:02 -0400483 subValue->userSub->subscriptionType = "RedfishEvent";
Ed Tanousfffb8c12022-02-07 23:53:03 -0800484 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530485
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400486 if (protocol != "Redfish")
Ed Tanousfffb8c12022-02-07 23:53:03 -0800487 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400488 messages::propertyValueNotInList(asyncResp->res, protocol,
489 "Protocol");
490 return;
491 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400492 subValue->userSub->protocol = protocol;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800493
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400494 if (verifyCertificate)
495 {
Myung Bae5fe4ef32024-10-19 09:56:02 -0400496 subValue->userSub->verifyCertificate = *verifyCertificate;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400497 }
498
499 if (eventFormatType2)
500 {
501 if (std::ranges::find(supportedEvtFormatTypes,
502 *eventFormatType2) ==
503 supportedEvtFormatTypes.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700504 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400505 messages::propertyValueNotInList(
506 asyncResp->res, *eventFormatType2, "EventFormatType");
507 return;
508 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400509 subValue->userSub->eventFormatType = *eventFormatType2;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400510 }
511 else
512 {
513 // If not specified, use default "Event"
Myung Bae5fe4ef32024-10-19 09:56:02 -0400514 subValue->userSub->eventFormatType = "Event";
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400515 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700516
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400517 if (context)
518 {
519 // This value is selected arbitrarily.
520 constexpr const size_t maxContextSize = 256;
521 if (context->size() > maxContextSize)
522 {
523 messages::stringValueTooLong(asyncResp->res, "Context",
524 maxContextSize);
525 return;
526 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400527 subValue->userSub->customText = *context;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400528 }
529
530 if (headers)
531 {
532 size_t cumulativeLen = 0;
533
534 for (const nlohmann::json::object_t& headerChunk : *headers)
535 {
536 for (const auto& item : headerChunk)
Ed Tanous002d39b2022-05-31 08:59:27 -0700537 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400538 const std::string* value =
539 item.second.get_ptr<const std::string*>();
540 if (value == nullptr)
541 {
542 messages::propertyValueFormatError(
543 asyncResp->res, item.second,
544 "HttpHeaders/" + item.first);
545 return;
546 }
547 // Adding a new json value is the size of the key, +
548 // the size of the value + 2 * 2 quotes for each, +
549 // the colon and space between. example:
550 // "key": "value"
551 cumulativeLen += item.first.size() + value->size() + 6;
552 // This value is selected to mirror http_connection.hpp
553 constexpr const uint16_t maxHeaderSizeED = 8096;
554 if (cumulativeLen > maxHeaderSizeED)
555 {
556 messages::arraySizeTooLong(
557 asyncResp->res, "HttpHeaders", maxHeaderSizeED);
558 return;
559 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400560 subValue->userSub->httpHeaders.set(item.first, *value);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400561 }
562 }
563 }
564
565 if (regPrefixes)
566 {
567 for (const std::string& it : *regPrefixes)
568 {
569 if (std::ranges::find(supportedRegPrefixes, it) ==
570 supportedRegPrefixes.end())
571 {
572 messages::propertyValueNotInList(asyncResp->res, it,
573 "RegistryPrefixes");
574 return;
575 }
576 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400577 subValue->userSub->registryPrefixes = *regPrefixes;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400578 }
579
Ed Tanousa14c9112024-09-04 10:46:47 -0700580 if (originResources)
581 {
Myung Bae5fe4ef32024-10-19 09:56:02 -0400582 subValue->userSub->originResources = *originResources;
Ed Tanousa14c9112024-09-04 10:46:47 -0700583 }
584
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400585 if (resTypes)
586 {
587 for (const std::string& it : *resTypes)
588 {
589 if (std::ranges::find(supportedResourceTypes, it) ==
590 supportedResourceTypes.end())
591 {
592 messages::propertyValueNotInList(asyncResp->res, it,
593 "ResourceTypes");
594 return;
595 }
596 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400597 subValue->userSub->resourceTypes = *resTypes;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400598 }
599
600 if (msgIds)
601 {
602 std::vector<std::string> registryPrefix;
603
604 // If no registry prefixes are mentioned, consider all
605 // supported prefixes
Myung Bae5fe4ef32024-10-19 09:56:02 -0400606 if (subValue->userSub->registryPrefixes.empty())
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400607 {
608 registryPrefix.assign(supportedRegPrefixes.begin(),
609 supportedRegPrefixes.end());
610 }
611 else
612 {
Myung Bae5fe4ef32024-10-19 09:56:02 -0400613 registryPrefix = subValue->userSub->registryPrefixes;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400614 }
615
616 for (const std::string& id : *msgIds)
617 {
618 bool validId = false;
619
620 // Check for Message ID in each of the selected Registry
621 for (const std::string& it : registryPrefix)
622 {
623 const std::span<const redfish::registries::MessageEntry>
624 registry =
625 redfish::registries::getRegistryFromPrefix(it);
626
627 if (std::ranges::any_of(
628 registry,
629 [&id](const redfish::registries::MessageEntry&
630 messageEntry) {
631 return id == messageEntry.first;
632 }))
633 {
634 validId = true;
635 break;
636 }
637 }
638
639 if (!validId)
640 {
641 messages::propertyValueNotInList(asyncResp->res, id,
642 "MessageIds");
643 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700644 }
645 }
646
Myung Bae5fe4ef32024-10-19 09:56:02 -0400647 subValue->userSub->registryMsgIds = *msgIds;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400648 }
649
650 if (retryPolicy)
651 {
652 if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
653 supportedRetryPolicies.end())
Ed Tanous002d39b2022-05-31 08:59:27 -0700654 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400655 messages::propertyValueNotInList(
656 asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800657 return;
658 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400659 subValue->userSub->retryPolicy = *retryPolicy;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400660 }
661 else
662 {
663 // Default "TerminateAfterRetries"
Myung Bae5fe4ef32024-10-19 09:56:02 -0400664 subValue->userSub->retryPolicy = "TerminateAfterRetries";
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400665 }
Myung Bae5064a252024-10-04 09:34:25 -0700666 if (sendHeartbeat)
667 {
668 subValue->userSub->sendHeartbeat = *sendHeartbeat;
669 }
670 if (hbIntervalMinutes)
671 {
672 if (*hbIntervalMinutes < 1 || *hbIntervalMinutes > 65535)
673 {
674 messages::propertyValueOutOfRange(
675 asyncResp->res, *hbIntervalMinutes,
676 "HeartbeatIntervalMinutes");
677 return;
678 }
679 subValue->userSub->hbIntervalMinutes = *hbIntervalMinutes;
680 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400681
682 if (mrdJsonArray)
683 {
684 for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
685 {
686 std::string mrdUri;
687
688 if (!json_util::readJsonObject(mrdObj, asyncResp->res,
689 "@odata.id", mrdUri))
690
691 {
692 return;
693 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400694 subValue->userSub->metricReportDefinitions.emplace_back(
Ed Tanous4b712a22023-08-02 12:56:52 -0700695 mrdUri);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400696 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800697 }
698
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400699 std::string id =
700 EventServiceManager::getInstance().addPushSubscription(
701 subValue);
702 if (id.empty())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800703 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400704 messages::internalError(asyncResp->res);
Ed Tanousfffb8c12022-02-07 23:53:03 -0800705 return;
706 }
707
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400708 messages::created(asyncResp->res);
709 asyncResp->res.addHeader(
710 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
711 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700712}
713
714inline void requestRoutesEventDestination(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530715{
Ravi Teja9d41aec2021-07-23 01:57:01 -0500716 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700717 .privileges(redfish::privileges::getEventDestination)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700718 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700719 [&app](const crow::Request& req,
720 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
721 const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400722 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
723 {
724 return;
725 }
Chicago Duan3d307082020-11-26 14:12:12 +0800726
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400727 if (param.starts_with("snmp"))
728 {
729 getSnmpTrapClient(asyncResp, param);
730 return;
731 }
Chicago Duan3d307082020-11-26 14:12:12 +0800732
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400733 std::shared_ptr<Subscription> subValue =
734 EventServiceManager::getInstance().getSubscription(param);
735 if (subValue == nullptr)
736 {
737 asyncResp->res.result(
738 boost::beast::http::status::not_found);
739 return;
740 }
741 const std::string& id = param;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530742
Ed Tanous4b712a22023-08-02 12:56:52 -0700743 const persistent_data::UserSubscription& userSub =
Myung Bae5fe4ef32024-10-19 09:56:02 -0400744 *subValue->userSub;
zhanghch058d1b46d2021-04-01 11:18:24 +0800745
Ed Tanous4b712a22023-08-02 12:56:52 -0700746 nlohmann::json& jVal = asyncResp->res.jsonValue;
747 jVal["@odata.type"] =
748 "#EventDestination.v1_14_1.EventDestination";
749 jVal["Protocol"] =
750 event_destination::EventDestinationProtocol::Redfish;
751 jVal["@odata.id"] = boost::urls::format(
752 "/redfish/v1/EventService/Subscriptions/{}", id);
753 jVal["Id"] = id;
754 jVal["Name"] = "Event Destination " + id;
755 jVal["Destination"] = userSub.destinationUrl;
756 jVal["Context"] = userSub.customText;
757 jVal["SubscriptionType"] = userSub.subscriptionType;
758 jVal["HttpHeaders"] = nlohmann::json::array();
759 jVal["EventFormatType"] = userSub.eventFormatType;
760 jVal["RegistryPrefixes"] = userSub.registryPrefixes;
761 jVal["ResourceTypes"] = userSub.resourceTypes;
762
763 jVal["MessageIds"] = userSub.registryMsgIds;
764 jVal["DeliveryRetryPolicy"] = userSub.retryPolicy;
Myung Bae5064a252024-10-04 09:34:25 -0700765 jVal["SendHeartbeat"] = userSub.sendHeartbeat;
766 jVal["HeartbeatIntervalMinutes"] = userSub.hbIntervalMinutes;
Ed Tanous4b712a22023-08-02 12:56:52 -0700767 jVal["VerifyCertificate"] = userSub.verifyCertificate;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530768
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400769 nlohmann::json::array_t mrdJsonArray;
Ed Tanous4b712a22023-08-02 12:56:52 -0700770 for (const auto& mdrUri : userSub.metricReportDefinitions)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400771 {
772 nlohmann::json::object_t mdr;
773 mdr["@odata.id"] = mdrUri;
774 mrdJsonArray.emplace_back(std::move(mdr));
775 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700776 jVal["MetricReportDefinitions"] = mrdJsonArray;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400777 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500778 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700779 // The below privilege is wrong, it should be ConfigureManager OR
780 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500781 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700782 //.privileges(redfish::privileges::patchEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700783 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700784 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700785 [&app](const crow::Request& req,
786 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
787 const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400788 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700789 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400790 return;
791 }
792 std::shared_ptr<Subscription> subValue =
793 EventServiceManager::getInstance().getSubscription(param);
794 if (subValue == nullptr)
795 {
796 asyncResp->res.result(
797 boost::beast::http::status::not_found);
798 return;
799 }
800
801 std::optional<std::string> context;
802 std::optional<std::string> retryPolicy;
Myung Bae5064a252024-10-04 09:34:25 -0700803 std::optional<bool> sendHeartbeat;
804 std::optional<uint64_t> hbIntervalMinutes;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400805 std::optional<bool> verifyCertificate;
806 std::optional<std::vector<nlohmann::json::object_t>> headers;
807
Myung Baeafc474a2024-10-09 00:53:29 -0700808 if (!json_util::readJsonPatch( //
809 req, asyncResp->res, //
810 "Context", context, //
811 "DeliveryRetryPolicy", retryPolicy, //
Myung Bae5064a252024-10-04 09:34:25 -0700812 "HeartbeatIntervalMinutes", hbIntervalMinutes, //
Myung Baeafc474a2024-10-09 00:53:29 -0700813 "HttpHeaders", headers, //
Myung Bae5064a252024-10-04 09:34:25 -0700814 "SendHeartbeat", sendHeartbeat, //
Myung Baeafc474a2024-10-09 00:53:29 -0700815 "VerifyCertificate", verifyCertificate //
816 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400817 {
818 return;
819 }
820
821 if (context)
822 {
Myung Bae5fe4ef32024-10-19 09:56:02 -0400823 subValue->userSub->customText = *context;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400824 }
825
826 if (headers)
827 {
828 boost::beast::http::fields fields;
829 for (const nlohmann::json::object_t& headerChunk : *headers)
Ed Tanous601c71a2021-09-08 16:40:12 -0700830 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400831 for (const auto& it : headerChunk)
832 {
833 const std::string* value =
834 it.second.get_ptr<const std::string*>();
835 if (value == nullptr)
836 {
837 messages::propertyValueFormatError(
838 asyncResp->res, it.second,
839 "HttpHeaders/" + it.first);
840 return;
841 }
842 fields.set(it.first, *value);
843 }
844 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400845 subValue->userSub->httpHeaders = std::move(fields);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400846 }
847
848 if (retryPolicy)
849 {
850 if (std::ranges::find(supportedRetryPolicies,
851 *retryPolicy) ==
852 supportedRetryPolicies.end())
853 {
854 messages::propertyValueNotInList(asyncResp->res,
855 *retryPolicy,
856 "DeliveryRetryPolicy");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700857 return;
858 }
Myung Bae5fe4ef32024-10-19 09:56:02 -0400859 subValue->userSub->retryPolicy = *retryPolicy;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700860 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530861
Myung Bae5064a252024-10-04 09:34:25 -0700862 if (sendHeartbeat)
863 {
864 subValue->userSub->sendHeartbeat = *sendHeartbeat;
865 }
866 if (hbIntervalMinutes)
867 {
868 if (*hbIntervalMinutes < 1 || *hbIntervalMinutes > 65535)
869 {
870 messages::propertyValueOutOfRange(
871 asyncResp->res, *hbIntervalMinutes,
872 "HeartbeatIntervalMinutes");
873 return;
874 }
875 subValue->userSub->hbIntervalMinutes = *hbIntervalMinutes;
876 }
877
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400878 if (verifyCertificate)
879 {
Myung Bae5fe4ef32024-10-19 09:56:02 -0400880 subValue->userSub->verifyCertificate = *verifyCertificate;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400881 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700882
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400883 EventServiceManager::getInstance().updateSubscriptionData();
884 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500885 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700886 // The below privilege is wrong, it should be ConfigureManager OR
887 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500888 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700889 //.privileges(redfish::privileges::deleteEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700890 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700891 .methods(boost::beast::http::verb::delete_)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700892 [&app](const crow::Request& req,
893 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
894 const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400895 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
896 {
897 return;
898 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700899 EventServiceManager& event = EventServiceManager::getInstance();
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400900 if (param.starts_with("snmp"))
901 {
902 deleteSnmpTrapClient(asyncResp, param);
Ed Tanous4b712a22023-08-02 12:56:52 -0700903 event.deleteSubscription(param);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400904 return;
905 }
Chicago Duan3d307082020-11-26 14:12:12 +0800906
Ed Tanous4b712a22023-08-02 12:56:52 -0700907 if (!event.deleteSubscription(param))
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400908 {
Ed Tanous4b712a22023-08-02 12:56:52 -0700909 messages::resourceNotFound(asyncResp->res,
910 "EventDestination", param);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400911 return;
912 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700913 messages::success(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400914 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700915}
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530916
917} // namespace redfish