xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 7e860f1550c8686eec42f7a75bc5f2ef51e756ad)
1e5aaf047SAppaRao Puli /*
2e5aaf047SAppaRao Puli // Copyright (c) 2020 Intel Corporation
3e5aaf047SAppaRao Puli //
4e5aaf047SAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License");
5e5aaf047SAppaRao Puli // you may not use this file except in compliance with the License.
6e5aaf047SAppaRao Puli // You may obtain a copy of the License at
7e5aaf047SAppaRao Puli //
8e5aaf047SAppaRao Puli //      http://www.apache.org/licenses/LICENSE-2.0
9e5aaf047SAppaRao Puli //
10e5aaf047SAppaRao Puli // Unless required by applicable law or agreed to in writing, software
11e5aaf047SAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS,
12e5aaf047SAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e5aaf047SAppaRao Puli // See the License for the specific language governing permissions and
14e5aaf047SAppaRao Puli // limitations under the License.
15e5aaf047SAppaRao Puli */
16e5aaf047SAppaRao Puli #pragma once
17b52664e2SAppaRao Puli #include "event_service_manager.hpp"
18e5aaf047SAppaRao Puli 
19*7e860f15SJohn Edward Broadbent #include <app.hpp>
20e5aaf047SAppaRao Puli namespace redfish
21e5aaf047SAppaRao Puli {
22e5aaf047SAppaRao Puli 
23156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
24156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
25e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
26b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
27e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
28e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
29e5aaf047SAppaRao Puli 
30e56f254cSSunitha Harish #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
31e56f254cSSunitha Harish static constexpr const std::array<const char*, 2> supportedResourceTypes = {
32e56f254cSSunitha Harish     "IBMConfigFile", "Task"};
33e56f254cSSunitha Harish #else
34e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
35e56f254cSSunitha Harish     "Task"};
36e56f254cSSunitha Harish #endif
37e56f254cSSunitha Harish 
38e5aaf047SAppaRao Puli static constexpr const uint8_t maxNoOfSubscriptions = 20;
39e5aaf047SAppaRao Puli 
40*7e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
41e5aaf047SAppaRao Puli {
42*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
43*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
44*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
45*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
46*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
478d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
48e5aaf047SAppaRao Puli                     {"@odata.type", "#EventService.v1_5_0.EventService"},
49e5aaf047SAppaRao Puli                     {"Id", "EventService"},
50e5aaf047SAppaRao Puli                     {"Name", "Event Service"},
51e5aaf047SAppaRao Puli                     {"Subscriptions",
52e5aaf047SAppaRao Puli                      {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
530b4bdd93SAppaRao Puli                     {"Actions",
540b4bdd93SAppaRao Puli                      {{"#EventService.SubmitTestEvent",
550b4bdd93SAppaRao Puli                        {{"target", "/redfish/v1/EventService/Actions/"
560b4bdd93SAppaRao Puli                                    "EventService.SubmitTestEvent"}}}}},
57e5aaf047SAppaRao Puli                     {"@odata.id", "/redfish/v1/EventService"}};
58e5aaf047SAppaRao Puli 
597d1cc387SAppaRao Puli                 const auto& [enabled, retryAttempts, retryTimeoutInterval] =
607d1cc387SAppaRao Puli                     EventServiceManager::getInstance().getEventServiceConfig();
617d1cc387SAppaRao Puli 
627d1cc387SAppaRao Puli                 asyncResp->res.jsonValue["Status"]["State"] =
637d1cc387SAppaRao Puli                     (enabled ? "Enabled" : "Disabled");
647d1cc387SAppaRao Puli                 asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
65*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
66*7e860f15SJohn Edward Broadbent                     retryAttempts;
67e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
687d1cc387SAppaRao Puli                     retryTimeoutInterval;
69*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["EventFormatTypes"] =
70*7e860f15SJohn Edward Broadbent                     supportedEvtFormatTypes;
71*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["RegistryPrefixes"] =
72*7e860f15SJohn Edward Broadbent                     supportedRegPrefixes;
73*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["ResourceTypes"] =
74*7e860f15SJohn Edward Broadbent                     supportedResourceTypes;
7507941a88SAyushi Smriti 
7607941a88SAyushi Smriti                 nlohmann::json supportedSSEFilters = {
7707941a88SAyushi Smriti                     {"EventFormatType", true},        {"MessageId", true},
7807941a88SAyushi Smriti                     {"MetricReportDefinition", true}, {"RegistryPrefix", true},
7907941a88SAyushi Smriti                     {"OriginResource", false},        {"ResourceType", false}};
8007941a88SAyushi Smriti 
8107941a88SAyushi Smriti                 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
8207941a88SAyushi Smriti                     supportedSSEFilters;
83*7e860f15SJohn Edward Broadbent             });
84e5aaf047SAppaRao Puli 
85*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
86*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
87*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
88*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
89*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
90*7e860f15SJohn Edward Broadbent 
91e5aaf047SAppaRao Puli             {
92e5aaf047SAppaRao Puli                 std::optional<bool> serviceEnabled;
93e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryAttemps;
94e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryInterval;
95e5aaf047SAppaRao Puli 
96*7e860f15SJohn Edward Broadbent                 if (!json_util::readJson(
97*7e860f15SJohn Edward Broadbent                         req, asyncResp->res, "ServiceEnabled", serviceEnabled,
98*7e860f15SJohn Edward Broadbent                         "DeliveryRetryAttempts", retryAttemps,
99*7e860f15SJohn Edward Broadbent                         "DeliveryRetryIntervalSeconds", retryInterval))
100e5aaf047SAppaRao Puli                 {
101e5aaf047SAppaRao Puli                     return;
102e5aaf047SAppaRao Puli                 }
103e5aaf047SAppaRao Puli 
1047d1cc387SAppaRao Puli                 auto [enabled, retryCount, retryTimeoutInterval] =
1057d1cc387SAppaRao Puli                     EventServiceManager::getInstance().getEventServiceConfig();
1067d1cc387SAppaRao Puli 
107e5aaf047SAppaRao Puli                 if (serviceEnabled)
108e5aaf047SAppaRao Puli                 {
1097d1cc387SAppaRao Puli                     enabled = *serviceEnabled;
110e5aaf047SAppaRao Puli                 }
111e5aaf047SAppaRao Puli 
112e5aaf047SAppaRao Puli                 if (retryAttemps)
113e5aaf047SAppaRao Puli                 {
114e5aaf047SAppaRao Puli                     // Supported range [1-3]
115e5aaf047SAppaRao Puli                     if ((*retryAttemps < 1) || (*retryAttemps > 3))
116e5aaf047SAppaRao Puli                     {
117e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
118e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryAttemps),
119e5aaf047SAppaRao Puli                             "DeliveryRetryAttempts", "[1-3]");
120e5aaf047SAppaRao Puli                     }
121e5aaf047SAppaRao Puli                     else
122e5aaf047SAppaRao Puli                     {
1237d1cc387SAppaRao Puli                         retryCount = *retryAttemps;
124e5aaf047SAppaRao Puli                     }
125e5aaf047SAppaRao Puli                 }
126e5aaf047SAppaRao Puli 
127e5aaf047SAppaRao Puli                 if (retryInterval)
128e5aaf047SAppaRao Puli                 {
129e5aaf047SAppaRao Puli                     // Supported range [30 - 180]
130e5aaf047SAppaRao Puli                     if ((*retryInterval < 30) || (*retryInterval > 180))
131e5aaf047SAppaRao Puli                     {
132e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
133e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryInterval),
134e5aaf047SAppaRao Puli                             "DeliveryRetryIntervalSeconds", "[30-180]");
135e5aaf047SAppaRao Puli                     }
136e5aaf047SAppaRao Puli                     else
137e5aaf047SAppaRao Puli                     {
1387d1cc387SAppaRao Puli                         retryTimeoutInterval = *retryInterval;
139e5aaf047SAppaRao Puli                     }
140e5aaf047SAppaRao Puli                 }
141e5aaf047SAppaRao Puli 
1427d1cc387SAppaRao Puli                 EventServiceManager::getInstance().setEventServiceConfig(
1437d1cc387SAppaRao Puli                     std::make_tuple(enabled, retryCount, retryTimeoutInterval));
144*7e860f15SJohn Edward Broadbent             });
1450b4bdd93SAppaRao Puli }
1460b4bdd93SAppaRao Puli 
147*7e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1480b4bdd93SAppaRao Puli {
149*7e860f15SJohn Edward Broadbent 
150*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
151*7e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
152*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
153*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
154*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
155*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1560b4bdd93SAppaRao Puli                 EventServiceManager::getInstance().sendTestEventLog();
1578d1b46d7Szhanghch05                 asyncResp->res.result(boost::beast::http::status::no_content);
158*7e860f15SJohn Edward Broadbent             });
159e5aaf047SAppaRao Puli }
160e5aaf047SAppaRao Puli 
161*7e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
162e5aaf047SAppaRao Puli {
163*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions")
164*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
165*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
166*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
167*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1688d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
169e5aaf047SAppaRao Puli                     {"@odata.type",
170e5aaf047SAppaRao Puli                      "#EventDestinationCollection.EventDestinationCollection"},
171e5aaf047SAppaRao Puli                     {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
172e5aaf047SAppaRao Puli                     {"Name", "Event Destination Collections"}};
173e5aaf047SAppaRao Puli 
174*7e860f15SJohn Edward Broadbent                 nlohmann::json& memberArray =
175*7e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Members"];
176e5aaf047SAppaRao Puli 
177b52664e2SAppaRao Puli                 std::vector<std::string> subscripIds =
178b52664e2SAppaRao Puli                     EventServiceManager::getInstance().getAllIDs();
179b52664e2SAppaRao Puli                 memberArray = nlohmann::json::array();
180*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Members@odata.count"] =
181*7e860f15SJohn Edward Broadbent                     subscripIds.size();
182b52664e2SAppaRao Puli 
183b52664e2SAppaRao Puli                 for (const std::string& id : subscripIds)
184e5aaf047SAppaRao Puli                 {
185e5aaf047SAppaRao Puli                     memberArray.push_back(
186e5aaf047SAppaRao Puli                         {{"@odata.id",
187b52664e2SAppaRao Puli                           "/redfish/v1/EventService/Subscriptions/" + id}});
188e5aaf047SAppaRao Puli                 }
189*7e860f15SJohn Edward Broadbent             });
190*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
191*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
192*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
193*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
194*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
195*7e860f15SJohn Edward Broadbent                 if (EventServiceManager::getInstance()
196*7e860f15SJohn Edward Broadbent                         .getNumberOfSubscriptions() >= maxNoOfSubscriptions)
197e5aaf047SAppaRao Puli                 {
198e5aaf047SAppaRao Puli                     messages::eventSubscriptionLimitExceeded(asyncResp->res);
199e5aaf047SAppaRao Puli                     return;
200e5aaf047SAppaRao Puli                 }
201e5aaf047SAppaRao Puli                 std::string destUrl;
202e5aaf047SAppaRao Puli                 std::string protocol;
203e5aaf047SAppaRao Puli                 std::optional<std::string> context;
204e5aaf047SAppaRao Puli                 std::optional<std::string> subscriptionType;
20523a21a1cSEd Tanous                 std::optional<std::string> eventFormatType2;
206e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
207e5aaf047SAppaRao Puli                 std::optional<std::vector<std::string>> msgIds;
208e5aaf047SAppaRao Puli                 std::optional<std::vector<std::string>> regPrefixes;
209e56f254cSSunitha Harish                 std::optional<std::vector<std::string>> resTypes;
210e5aaf047SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> headers;
211144b6318SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
212e5aaf047SAppaRao Puli 
213e5aaf047SAppaRao Puli                 if (!json_util::readJson(
214*7e860f15SJohn Edward Broadbent                         req, asyncResp->res, "Destination", destUrl, "Context",
215*7e860f15SJohn Edward Broadbent                         context, "Protocol", protocol, "SubscriptionType",
216*7e860f15SJohn Edward Broadbent                         subscriptionType, "EventFormatType", eventFormatType2,
217*7e860f15SJohn Edward Broadbent                         "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
218*7e860f15SJohn Edward Broadbent                         "MessageIds", msgIds, "DeliveryRetryPolicy",
219*7e860f15SJohn Edward Broadbent                         retryPolicy, "MetricReportDefinitions", mrdJsonArray,
220*7e860f15SJohn Edward Broadbent                         "ResourceTypes", resTypes))
221e5aaf047SAppaRao Puli                 {
222e5aaf047SAppaRao Puli                     return;
223e5aaf047SAppaRao Puli                 }
224e5aaf047SAppaRao Puli 
225dd28ba82SAppaRao Puli                 if (regPrefixes && msgIds)
226dd28ba82SAppaRao Puli                 {
227dd28ba82SAppaRao Puli                     if (regPrefixes->size() && msgIds->size())
228dd28ba82SAppaRao Puli                     {
229dd28ba82SAppaRao Puli                         messages::mutualExclusiveProperties(
230dd28ba82SAppaRao Puli                             asyncResp->res, "RegistryPrefixes", "MessageIds");
231dd28ba82SAppaRao Puli                         return;
232dd28ba82SAppaRao Puli                     }
233dd28ba82SAppaRao Puli                 }
234dd28ba82SAppaRao Puli 
235e5aaf047SAppaRao Puli                 // Validate the URL using regex expression
236b52664e2SAppaRao Puli                 // Format: <protocol>://<host>:<port>/<uri>
237b52664e2SAppaRao Puli                 // protocol: http/https
238b52664e2SAppaRao Puli                 // host: Exclude ' ', ':', '#', '?'
2394e0453b1SGunnar Mills                 // port: Empty or numeric value with ':' separator.
240b52664e2SAppaRao Puli                 // uri: Start with '/' and Exclude '#', ' '
241b52664e2SAppaRao Puli                 //      Can include query params(ex: '/event?test=1')
242b52664e2SAppaRao Puli                 // TODO: Need to validate hostname extensively(as per rfc)
243b52664e2SAppaRao Puli                 const std::regex urlRegex(
244b52664e2SAppaRao Puli                     "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
245b52664e2SAppaRao Puli                     "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
246b52664e2SAppaRao Puli                 std::cmatch match;
247b52664e2SAppaRao Puli                 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
248e5aaf047SAppaRao Puli                 {
249e5aaf047SAppaRao Puli                     messages::propertyValueFormatError(asyncResp->res, destUrl,
250e5aaf047SAppaRao Puli                                                        "Destination");
251e5aaf047SAppaRao Puli                     return;
252e5aaf047SAppaRao Puli                 }
253b52664e2SAppaRao Puli 
254*7e860f15SJohn Edward Broadbent                 std::string uriProto =
255*7e860f15SJohn Edward Broadbent                     std::string(match[1].first, match[1].second);
256b52664e2SAppaRao Puli                 if (uriProto == "http")
257b52664e2SAppaRao Puli                 {
258b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
259b52664e2SAppaRao Puli                     messages::propertyValueFormatError(asyncResp->res, destUrl,
260b52664e2SAppaRao Puli                                                        "Destination");
261b52664e2SAppaRao Puli                     return;
262b52664e2SAppaRao Puli #endif
263b52664e2SAppaRao Puli                 }
264b52664e2SAppaRao Puli 
265b52664e2SAppaRao Puli                 std::string host = std::string(match[2].first, match[2].second);
266b52664e2SAppaRao Puli                 std::string port = std::string(match[3].first, match[3].second);
267b52664e2SAppaRao Puli                 std::string path = std::string(match[4].first, match[4].second);
268b52664e2SAppaRao Puli                 if (port.empty())
269b52664e2SAppaRao Puli                 {
270b52664e2SAppaRao Puli                     if (uriProto == "http")
271b52664e2SAppaRao Puli                     {
272b52664e2SAppaRao Puli                         port = "80";
273b52664e2SAppaRao Puli                     }
274b52664e2SAppaRao Puli                     else
275b52664e2SAppaRao Puli                     {
276b52664e2SAppaRao Puli                         port = "443";
277b52664e2SAppaRao Puli                     }
278b52664e2SAppaRao Puli                 }
279b52664e2SAppaRao Puli                 if (path.empty())
280b52664e2SAppaRao Puli                 {
281b52664e2SAppaRao Puli                     path = "/";
282b52664e2SAppaRao Puli                 }
283b52664e2SAppaRao Puli 
284b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
285b52664e2SAppaRao Puli                     std::make_shared<Subscription>(host, port, path, uriProto);
286b52664e2SAppaRao Puli 
287b52664e2SAppaRao Puli                 subValue->destinationUrl = destUrl;
288e5aaf047SAppaRao Puli 
289e5aaf047SAppaRao Puli                 if (subscriptionType)
290e5aaf047SAppaRao Puli                 {
291e5aaf047SAppaRao Puli                     if (*subscriptionType != "RedfishEvent")
292e5aaf047SAppaRao Puli                     {
293*7e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
294*7e860f15SJohn Edward Broadbent                                                          *subscriptionType,
295*7e860f15SJohn Edward Broadbent                                                          "SubscriptionType");
296e5aaf047SAppaRao Puli                         return;
297e5aaf047SAppaRao Puli                     }
298b52664e2SAppaRao Puli                     subValue->subscriptionType = *subscriptionType;
299e5aaf047SAppaRao Puli                 }
300e5aaf047SAppaRao Puli                 else
301e5aaf047SAppaRao Puli                 {
302b52664e2SAppaRao Puli                     subValue->subscriptionType = "RedfishEvent"; // Default
303e5aaf047SAppaRao Puli                 }
304e5aaf047SAppaRao Puli 
305e5aaf047SAppaRao Puli                 if (protocol != "Redfish")
306e5aaf047SAppaRao Puli                 {
307e5aaf047SAppaRao Puli                     messages::propertyValueNotInList(asyncResp->res, protocol,
308e5aaf047SAppaRao Puli                                                      "Protocol");
309e5aaf047SAppaRao Puli                     return;
310e5aaf047SAppaRao Puli                 }
311b52664e2SAppaRao Puli                 subValue->protocol = protocol;
312e5aaf047SAppaRao Puli 
31323a21a1cSEd Tanous                 if (eventFormatType2)
314e5aaf047SAppaRao Puli                 {
315e5aaf047SAppaRao Puli                     if (std::find(supportedEvtFormatTypes.begin(),
316e5aaf047SAppaRao Puli                                   supportedEvtFormatTypes.end(),
317*7e860f15SJohn Edward Broadbent                                   *eventFormatType2) ==
318*7e860f15SJohn Edward Broadbent                         supportedEvtFormatTypes.end())
319e5aaf047SAppaRao Puli                     {
320*7e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
321*7e860f15SJohn Edward Broadbent                                                          *eventFormatType2,
322*7e860f15SJohn Edward Broadbent                                                          "EventFormatType");
323e5aaf047SAppaRao Puli                         return;
324e5aaf047SAppaRao Puli                     }
32523a21a1cSEd Tanous                     subValue->eventFormatType = *eventFormatType2;
326e5aaf047SAppaRao Puli                 }
327e5aaf047SAppaRao Puli                 else
328e5aaf047SAppaRao Puli                 {
329e5aaf047SAppaRao Puli                     // If not specified, use default "Event"
33023a21a1cSEd Tanous                     subValue->eventFormatType = "Event";
331e5aaf047SAppaRao Puli                 }
332e5aaf047SAppaRao Puli 
333e5aaf047SAppaRao Puli                 if (context)
334e5aaf047SAppaRao Puli                 {
335b52664e2SAppaRao Puli                     subValue->customText = *context;
336e5aaf047SAppaRao Puli                 }
337e5aaf047SAppaRao Puli 
338e5aaf047SAppaRao Puli                 if (headers)
339e5aaf047SAppaRao Puli                 {
340b52664e2SAppaRao Puli                     subValue->httpHeaders = *headers;
341e5aaf047SAppaRao Puli                 }
342e5aaf047SAppaRao Puli 
343e5aaf047SAppaRao Puli                 if (regPrefixes)
344e5aaf047SAppaRao Puli                 {
345e5aaf047SAppaRao Puli                     for (const std::string& it : *regPrefixes)
346e5aaf047SAppaRao Puli                     {
347e5aaf047SAppaRao Puli                         if (std::find(supportedRegPrefixes.begin(),
348e5aaf047SAppaRao Puli                                       supportedRegPrefixes.end(),
349e5aaf047SAppaRao Puli                                       it) == supportedRegPrefixes.end())
350e5aaf047SAppaRao Puli                         {
351*7e860f15SJohn Edward Broadbent                             messages::propertyValueNotInList(
352*7e860f15SJohn Edward Broadbent                                 asyncResp->res, it, "RegistryPrefixes");
353e5aaf047SAppaRao Puli                             return;
354e5aaf047SAppaRao Puli                         }
355e5aaf047SAppaRao Puli                     }
356b52664e2SAppaRao Puli                     subValue->registryPrefixes = *regPrefixes;
357e5aaf047SAppaRao Puli                 }
358e5aaf047SAppaRao Puli 
359e56f254cSSunitha Harish                 if (resTypes)
360e56f254cSSunitha Harish                 {
361e56f254cSSunitha Harish                     for (const std::string& it : *resTypes)
362e56f254cSSunitha Harish                     {
363e56f254cSSunitha Harish                         if (std::find(supportedResourceTypes.begin(),
364e56f254cSSunitha Harish                                       supportedResourceTypes.end(),
365e56f254cSSunitha Harish                                       it) == supportedResourceTypes.end())
366e56f254cSSunitha Harish                         {
367e56f254cSSunitha Harish                             messages::propertyValueNotInList(asyncResp->res, it,
368e56f254cSSunitha Harish                                                              "ResourceTypes");
369e56f254cSSunitha Harish                             return;
370e56f254cSSunitha Harish                         }
371e56f254cSSunitha Harish                     }
372e56f254cSSunitha Harish                     subValue->resourceTypes = *resTypes;
373e56f254cSSunitha Harish                 }
374e56f254cSSunitha Harish 
375e5aaf047SAppaRao Puli                 if (msgIds)
376e5aaf047SAppaRao Puli                 {
377b304bd79SP Dheeraj Srujan Kumar                     std::vector<std::string> registryPrefix;
378b304bd79SP Dheeraj Srujan Kumar 
379*7e860f15SJohn Edward Broadbent                     // If no registry prefixes are mentioned, consider all
380*7e860f15SJohn Edward Broadbent                     // supported prefixes
381b304bd79SP Dheeraj Srujan Kumar                     if (subValue->registryPrefixes.empty())
382b304bd79SP Dheeraj Srujan Kumar                     {
383b304bd79SP Dheeraj Srujan Kumar                         registryPrefix.assign(supportedRegPrefixes.begin(),
384b304bd79SP Dheeraj Srujan Kumar                                               supportedRegPrefixes.end());
385b304bd79SP Dheeraj Srujan Kumar                     }
386b304bd79SP Dheeraj Srujan Kumar                     else
387b304bd79SP Dheeraj Srujan Kumar                     {
388b304bd79SP Dheeraj Srujan Kumar                         registryPrefix = subValue->registryPrefixes;
389b304bd79SP Dheeraj Srujan Kumar                     }
390b304bd79SP Dheeraj Srujan Kumar 
391b304bd79SP Dheeraj Srujan Kumar                     for (const std::string& id : *msgIds)
392b304bd79SP Dheeraj Srujan Kumar                     {
393b304bd79SP Dheeraj Srujan Kumar                         bool validId = false;
394b304bd79SP Dheeraj Srujan Kumar 
395b304bd79SP Dheeraj Srujan Kumar                         // Check for Message ID in each of the selected Registry
396b304bd79SP Dheeraj Srujan Kumar                         for (const std::string& it : registryPrefix)
397b304bd79SP Dheeraj Srujan Kumar                         {
398b304bd79SP Dheeraj Srujan Kumar                             const boost::beast::span<
399b304bd79SP Dheeraj Srujan Kumar                                 const redfish::message_registries::MessageEntry>
400*7e860f15SJohn Edward Broadbent                                 registry = redfish::message_registries::
401*7e860f15SJohn Edward Broadbent                                     getRegistryFromPrefix(it);
402b304bd79SP Dheeraj Srujan Kumar 
403b304bd79SP Dheeraj Srujan Kumar                             if (std::any_of(
404b304bd79SP Dheeraj Srujan Kumar                                     registry.cbegin(), registry.cend(),
405*7e860f15SJohn Edward Broadbent                                     [&id](const redfish::message_registries::
406*7e860f15SJohn Edward Broadbent                                               MessageEntry& messageEntry) {
407b304bd79SP Dheeraj Srujan Kumar                                         return !id.compare(messageEntry.first);
408b304bd79SP Dheeraj Srujan Kumar                                     }))
409b304bd79SP Dheeraj Srujan Kumar                             {
410b304bd79SP Dheeraj Srujan Kumar                                 validId = true;
411b304bd79SP Dheeraj Srujan Kumar                                 break;
412b304bd79SP Dheeraj Srujan Kumar                             }
413b304bd79SP Dheeraj Srujan Kumar                         }
414b304bd79SP Dheeraj Srujan Kumar 
415b304bd79SP Dheeraj Srujan Kumar                         if (!validId)
416b304bd79SP Dheeraj Srujan Kumar                         {
417b304bd79SP Dheeraj Srujan Kumar                             messages::propertyValueNotInList(asyncResp->res, id,
418b304bd79SP Dheeraj Srujan Kumar                                                              "MessageIds");
419b304bd79SP Dheeraj Srujan Kumar                             return;
420b304bd79SP Dheeraj Srujan Kumar                         }
421b304bd79SP Dheeraj Srujan Kumar                     }
422b304bd79SP Dheeraj Srujan Kumar 
423b52664e2SAppaRao Puli                     subValue->registryMsgIds = *msgIds;
424e5aaf047SAppaRao Puli                 }
425e5aaf047SAppaRao Puli 
426e5aaf047SAppaRao Puli                 if (retryPolicy)
427e5aaf047SAppaRao Puli                 {
428e5aaf047SAppaRao Puli                     if (std::find(supportedRetryPolicies.begin(),
429e5aaf047SAppaRao Puli                                   supportedRetryPolicies.end(),
430e5aaf047SAppaRao Puli                                   *retryPolicy) == supportedRetryPolicies.end())
431e5aaf047SAppaRao Puli                     {
432*7e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
433*7e860f15SJohn Edward Broadbent                                                          *retryPolicy,
434e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
435e5aaf047SAppaRao Puli                         return;
436e5aaf047SAppaRao Puli                     }
437b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
438e5aaf047SAppaRao Puli                 }
439e5aaf047SAppaRao Puli                 else
440e5aaf047SAppaRao Puli                 {
441e5aaf047SAppaRao Puli                     // Default "TerminateAfterRetries"
442b52664e2SAppaRao Puli                     subValue->retryPolicy = "TerminateAfterRetries";
443e5aaf047SAppaRao Puli                 }
444e5aaf047SAppaRao Puli 
445144b6318SAppaRao Puli                 if (mrdJsonArray)
446156d6b00SAppaRao Puli                 {
447144b6318SAppaRao Puli                     for (nlohmann::json& mrdObj : *mrdJsonArray)
448144b6318SAppaRao Puli                     {
449144b6318SAppaRao Puli                         std::string mrdUri;
450*7e860f15SJohn Edward Broadbent                         if (json_util::getValueFromJsonObject(
451*7e860f15SJohn Edward Broadbent                                 mrdObj, "@odata.id", mrdUri))
452144b6318SAppaRao Puli                         {
453*7e860f15SJohn Edward Broadbent                             subValue->metricReportDefinitions.emplace_back(
454*7e860f15SJohn Edward Broadbent                                 mrdUri);
455144b6318SAppaRao Puli                         }
456144b6318SAppaRao Puli                         else
457144b6318SAppaRao Puli                         {
458144b6318SAppaRao Puli                             messages::propertyValueFormatError(
45971f52d96SEd Tanous                                 asyncResp->res,
460*7e860f15SJohn Edward Broadbent                                 mrdObj.dump(
461*7e860f15SJohn Edward Broadbent                                     2, ' ', true,
46271f52d96SEd Tanous                                     nlohmann::json::error_handler_t::replace),
463144b6318SAppaRao Puli                                 "MetricReportDefinitions");
464144b6318SAppaRao Puli                             return;
465144b6318SAppaRao Puli                         }
466144b6318SAppaRao Puli                     }
467156d6b00SAppaRao Puli                 }
468156d6b00SAppaRao Puli 
469b52664e2SAppaRao Puli                 std::string id =
470*7e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().addSubscription(
471*7e860f15SJohn Edward Broadbent                         subValue);
472b52664e2SAppaRao Puli                 if (id.empty())
473e5aaf047SAppaRao Puli                 {
474e5aaf047SAppaRao Puli                     messages::internalError(asyncResp->res);
475e5aaf047SAppaRao Puli                     return;
476e5aaf047SAppaRao Puli                 }
477e5aaf047SAppaRao Puli 
478e5aaf047SAppaRao Puli                 messages::created(asyncResp->res);
479e5aaf047SAppaRao Puli                 asyncResp->res.addHeader(
480e5aaf047SAppaRao Puli                     "Location", "/redfish/v1/EventService/Subscriptions/" + id);
481*7e860f15SJohn Edward Broadbent             });
482e5aaf047SAppaRao Puli }
483e5aaf047SAppaRao Puli 
484*7e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
485e5aaf047SAppaRao Puli {
486*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
487*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
488*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
489*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
490*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
491*7e860f15SJohn Edward Broadbent                const std::string& param) {
492b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
493*7e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
494b52664e2SAppaRao Puli                 if (subValue == nullptr)
495e5aaf047SAppaRao Puli                 {
496*7e860f15SJohn Edward Broadbent                     asyncResp->res.result(
497*7e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
498e5aaf047SAppaRao Puli                     return;
499e5aaf047SAppaRao Puli                 }
500*7e860f15SJohn Edward Broadbent                 const std::string& id = param;
501e5aaf047SAppaRao Puli 
5028d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
503*7e860f15SJohn Edward Broadbent                     {"@odata.type",
504*7e860f15SJohn Edward Broadbent                      "#EventDestination.v1_7_0.EventDestination"},
505e5aaf047SAppaRao Puli                     {"Protocol", "Redfish"}};
506e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["@odata.id"] =
507e5aaf047SAppaRao Puli                     "/redfish/v1/EventService/Subscriptions/" + id;
508e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Id"] = id;
509e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
510*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Destination"] =
511*7e860f15SJohn Edward Broadbent                     subValue->destinationUrl;
512b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["Context"] = subValue->customText;
513e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["SubscriptionType"] =
514b52664e2SAppaRao Puli                     subValue->subscriptionType;
515b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
516*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["EventFormatType"] =
517*7e860f15SJohn Edward Broadbent                     subValue->eventFormatType;
518e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["RegistryPrefixes"] =
519b52664e2SAppaRao Puli                     subValue->registryPrefixes;
520*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["ResourceTypes"] =
521*7e860f15SJohn Edward Broadbent                     subValue->resourceTypes;
522e56f254cSSunitha Harish 
523*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["MessageIds"] =
524*7e860f15SJohn Edward Broadbent                     subValue->registryMsgIds;
525*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
526*7e860f15SJohn Edward Broadbent                     subValue->retryPolicy;
527144b6318SAppaRao Puli 
528144b6318SAppaRao Puli                 std::vector<nlohmann::json> mrdJsonArray;
529144b6318SAppaRao Puli                 for (const auto& mdrUri : subValue->metricReportDefinitions)
530144b6318SAppaRao Puli                 {
531144b6318SAppaRao Puli                     mrdJsonArray.push_back({{"@odata.id", mdrUri}});
532144b6318SAppaRao Puli                 }
533*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["MetricReportDefinitions"] =
534*7e860f15SJohn Edward Broadbent                     mrdJsonArray;
535*7e860f15SJohn Edward Broadbent             });
536*7e860f15SJohn Edward Broadbent     /////redfish/v1/EventService/Subscriptions/
537*7e860f15SJohn Edward Broadbent     // ConfigureManager
538*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
539*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
540*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
541*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
542*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
543*7e860f15SJohn Edward Broadbent                const std::string& param) {
544b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
545*7e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
546b52664e2SAppaRao Puli                 if (subValue == nullptr)
547e5aaf047SAppaRao Puli                 {
548*7e860f15SJohn Edward Broadbent                     asyncResp->res.result(
549*7e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
550e5aaf047SAppaRao Puli                     return;
551e5aaf047SAppaRao Puli                 }
552e5aaf047SAppaRao Puli 
553e5aaf047SAppaRao Puli                 std::optional<std::string> context;
554e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
555e5aaf047SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> headers;
556e5aaf047SAppaRao Puli 
557*7e860f15SJohn Edward Broadbent                 if (!json_util::readJson(req, asyncResp->res, "Context",
558*7e860f15SJohn Edward Broadbent                                          context, "DeliveryRetryPolicy",
559*7e860f15SJohn Edward Broadbent                                          retryPolicy, "HttpHeaders", headers))
560e5aaf047SAppaRao Puli                 {
561e5aaf047SAppaRao Puli                     return;
562e5aaf047SAppaRao Puli                 }
563e5aaf047SAppaRao Puli 
564e5aaf047SAppaRao Puli                 if (context)
565e5aaf047SAppaRao Puli                 {
566b52664e2SAppaRao Puli                     subValue->customText = *context;
567e5aaf047SAppaRao Puli                 }
568e5aaf047SAppaRao Puli 
569e5aaf047SAppaRao Puli                 if (headers)
570e5aaf047SAppaRao Puli                 {
571b52664e2SAppaRao Puli                     subValue->httpHeaders = *headers;
572e5aaf047SAppaRao Puli                 }
573e5aaf047SAppaRao Puli 
574e5aaf047SAppaRao Puli                 if (retryPolicy)
575e5aaf047SAppaRao Puli                 {
576e5aaf047SAppaRao Puli                     if (std::find(supportedRetryPolicies.begin(),
577e5aaf047SAppaRao Puli                                   supportedRetryPolicies.end(),
578e5aaf047SAppaRao Puli                                   *retryPolicy) == supportedRetryPolicies.end())
579e5aaf047SAppaRao Puli                     {
580*7e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
581*7e860f15SJohn Edward Broadbent                                                          *retryPolicy,
582e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
583e5aaf047SAppaRao Puli                         return;
584e5aaf047SAppaRao Puli                     }
585b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
586fe44eb0bSAyushi Smriti                     subValue->updateRetryPolicy();
587e5aaf047SAppaRao Puli                 }
588e5aaf047SAppaRao Puli 
589b52664e2SAppaRao Puli                 EventServiceManager::getInstance().updateSubscriptionData();
590*7e860f15SJohn Edward Broadbent             });
591*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
592*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
593*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
594*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
595*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
596*7e860f15SJohn Edward Broadbent                const std::string& param) {
597*7e860f15SJohn Edward Broadbent                 if (!EventServiceManager::getInstance().isSubscriptionExist(
598*7e860f15SJohn Edward Broadbent                         param))
599e5aaf047SAppaRao Puli                 {
600*7e860f15SJohn Edward Broadbent                     asyncResp->res.result(
601*7e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
602e5aaf047SAppaRao Puli                     return;
603e5aaf047SAppaRao Puli                 }
604*7e860f15SJohn Edward Broadbent                 EventServiceManager::getInstance().deleteSubscription(param);
605*7e860f15SJohn Edward Broadbent             });
606e5aaf047SAppaRao Puli }
607e5aaf047SAppaRao Puli 
608e5aaf047SAppaRao Puli } // namespace redfish
609