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 197e860f15SJohn 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 407e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app) 41e5aaf047SAppaRao Puli { 427e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 43*432a890cSEd Tanous .privileges({{"Login"}}) 447e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 457e860f15SJohn Edward Broadbent [](const crow::Request&, 467e860f15SJohn 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; 657e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 667e860f15SJohn Edward Broadbent retryAttempts; 67e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 687d1cc387SAppaRao Puli retryTimeoutInterval; 697e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EventFormatTypes"] = 707e860f15SJohn Edward Broadbent supportedEvtFormatTypes; 717e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["RegistryPrefixes"] = 727e860f15SJohn Edward Broadbent supportedRegPrefixes; 737e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ResourceTypes"] = 747e860f15SJohn 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; 837e860f15SJohn Edward Broadbent }); 84e5aaf047SAppaRao Puli 857e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 86*432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 877e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 887e860f15SJohn Edward Broadbent [](const crow::Request& req, 897e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 907e860f15SJohn 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 967e860f15SJohn Edward Broadbent if (!json_util::readJson( 977e860f15SJohn Edward Broadbent req, asyncResp->res, "ServiceEnabled", serviceEnabled, 987e860f15SJohn Edward Broadbent "DeliveryRetryAttempts", retryAttemps, 997e860f15SJohn 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)); 1447e860f15SJohn Edward Broadbent }); 1450b4bdd93SAppaRao Puli } 1460b4bdd93SAppaRao Puli 1477e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app) 1480b4bdd93SAppaRao Puli { 1497e860f15SJohn Edward Broadbent 1507e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 1517e860f15SJohn Edward Broadbent app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/") 152*432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 1537e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1547e860f15SJohn Edward Broadbent [](const crow::Request&, 1557e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1560b4bdd93SAppaRao Puli EventServiceManager::getInstance().sendTestEventLog(); 1578d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 1587e860f15SJohn Edward Broadbent }); 159e5aaf047SAppaRao Puli } 160e5aaf047SAppaRao Puli 1617e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app) 162e5aaf047SAppaRao Puli { 1637e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions") 164*432a890cSEd Tanous .privileges({{"Login"}}) 1657e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1667e860f15SJohn Edward Broadbent [](const crow::Request&, 1677e860f15SJohn 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 1747e860f15SJohn Edward Broadbent nlohmann::json& memberArray = 1757e860f15SJohn 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(); 1807e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members@odata.count"] = 1817e860f15SJohn 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 } 1897e860f15SJohn Edward Broadbent }); 1907e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 191*432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 1927e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1937e860f15SJohn Edward Broadbent [](const crow::Request& req, 1947e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1957e860f15SJohn Edward Broadbent if (EventServiceManager::getInstance() 1967e860f15SJohn 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( 2147e860f15SJohn Edward Broadbent req, asyncResp->res, "Destination", destUrl, "Context", 2157e860f15SJohn Edward Broadbent context, "Protocol", protocol, "SubscriptionType", 2167e860f15SJohn Edward Broadbent subscriptionType, "EventFormatType", eventFormatType2, 2177e860f15SJohn Edward Broadbent "HttpHeaders", headers, "RegistryPrefixes", regPrefixes, 2187e860f15SJohn Edward Broadbent "MessageIds", msgIds, "DeliveryRetryPolicy", 2197e860f15SJohn Edward Broadbent retryPolicy, "MetricReportDefinitions", mrdJsonArray, 2207e860f15SJohn 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 2547e860f15SJohn Edward Broadbent std::string uriProto = 2557e860f15SJohn 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 { 2937e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 2947e860f15SJohn Edward Broadbent *subscriptionType, 2957e860f15SJohn 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(), 3177e860f15SJohn Edward Broadbent *eventFormatType2) == 3187e860f15SJohn Edward Broadbent supportedEvtFormatTypes.end()) 319e5aaf047SAppaRao Puli { 3207e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 3217e860f15SJohn Edward Broadbent *eventFormatType2, 3227e860f15SJohn 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 { 3517e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 3527e860f15SJohn 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 3797e860f15SJohn Edward Broadbent // If no registry prefixes are mentioned, consider all 3807e860f15SJohn 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> 4007e860f15SJohn Edward Broadbent registry = redfish::message_registries:: 4017e860f15SJohn Edward Broadbent getRegistryFromPrefix(it); 402b304bd79SP Dheeraj Srujan Kumar 403b304bd79SP Dheeraj Srujan Kumar if (std::any_of( 404b304bd79SP Dheeraj Srujan Kumar registry.cbegin(), registry.cend(), 4057e860f15SJohn Edward Broadbent [&id](const redfish::message_registries:: 4067e860f15SJohn 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 { 4327e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 4337e860f15SJohn 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; 4507e860f15SJohn Edward Broadbent if (json_util::getValueFromJsonObject( 4517e860f15SJohn Edward Broadbent mrdObj, "@odata.id", mrdUri)) 452144b6318SAppaRao Puli { 4537e860f15SJohn Edward Broadbent subValue->metricReportDefinitions.emplace_back( 4547e860f15SJohn Edward Broadbent mrdUri); 455144b6318SAppaRao Puli } 456144b6318SAppaRao Puli else 457144b6318SAppaRao Puli { 458144b6318SAppaRao Puli messages::propertyValueFormatError( 45971f52d96SEd Tanous asyncResp->res, 4607e860f15SJohn Edward Broadbent mrdObj.dump( 4617e860f15SJohn 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 = 4707e860f15SJohn Edward Broadbent EventServiceManager::getInstance().addSubscription( 4717e860f15SJohn 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); 4817e860f15SJohn Edward Broadbent }); 482e5aaf047SAppaRao Puli } 483e5aaf047SAppaRao Puli 4847e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app) 485e5aaf047SAppaRao Puli { 4869552547cSChicago Duan BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 487*432a890cSEd Tanous .privileges({{"Login"}}) 4887e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 4897e860f15SJohn Edward Broadbent [](const crow::Request&, 4907e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4917e860f15SJohn Edward Broadbent const std::string& param) { 492b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 4937e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 494b52664e2SAppaRao Puli if (subValue == nullptr) 495e5aaf047SAppaRao Puli { 4967e860f15SJohn Edward Broadbent asyncResp->res.result( 4977e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 498e5aaf047SAppaRao Puli return; 499e5aaf047SAppaRao Puli } 5007e860f15SJohn Edward Broadbent const std::string& id = param; 501e5aaf047SAppaRao Puli 5028d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 5037e860f15SJohn Edward Broadbent {"@odata.type", 5047e860f15SJohn 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; 5107e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Destination"] = 5117e860f15SJohn 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; 5167e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EventFormatType"] = 5177e860f15SJohn Edward Broadbent subValue->eventFormatType; 518e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = 519b52664e2SAppaRao Puli subValue->registryPrefixes; 5207e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ResourceTypes"] = 5217e860f15SJohn Edward Broadbent subValue->resourceTypes; 522e56f254cSSunitha Harish 5237e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["MessageIds"] = 5247e860f15SJohn Edward Broadbent subValue->registryMsgIds; 5257e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryPolicy"] = 5267e860f15SJohn 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 } 5337e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["MetricReportDefinitions"] = 5347e860f15SJohn Edward Broadbent mrdJsonArray; 5357e860f15SJohn Edward Broadbent }); 5367e860f15SJohn Edward Broadbent /////redfish/v1/EventService/Subscriptions/ 5377e860f15SJohn Edward Broadbent // ConfigureManager 5389552547cSChicago Duan BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 539*432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 5407e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 5417e860f15SJohn Edward Broadbent [](const crow::Request& req, 5427e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5437e860f15SJohn Edward Broadbent const std::string& param) { 544b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 5457e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 546b52664e2SAppaRao Puli if (subValue == nullptr) 547e5aaf047SAppaRao Puli { 5487e860f15SJohn Edward Broadbent asyncResp->res.result( 5497e860f15SJohn 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 5577e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "Context", 5587e860f15SJohn Edward Broadbent context, "DeliveryRetryPolicy", 5597e860f15SJohn 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 { 5807e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 5817e860f15SJohn 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(); 5907e860f15SJohn Edward Broadbent }); 5919552547cSChicago Duan BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 592*432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 5937e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 5947e860f15SJohn Edward Broadbent [](const crow::Request&, 5957e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5967e860f15SJohn Edward Broadbent const std::string& param) { 5977e860f15SJohn Edward Broadbent if (!EventServiceManager::getInstance().isSubscriptionExist( 5987e860f15SJohn Edward Broadbent param)) 599e5aaf047SAppaRao Puli { 6007e860f15SJohn Edward Broadbent asyncResp->res.result( 6017e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 602e5aaf047SAppaRao Puli return; 603e5aaf047SAppaRao Puli } 6047e860f15SJohn Edward Broadbent EventServiceManager::getInstance().deleteSubscription(param); 6057e860f15SJohn Edward Broadbent }); 606e5aaf047SAppaRao Puli } 607e5aaf047SAppaRao Puli 608e5aaf047SAppaRao Puli } // namespace redfish 609