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