1b52664e2SAppaRao Puli /* 2b52664e2SAppaRao Puli // Copyright (c) 2020 Intel Corporation 3b52664e2SAppaRao Puli // 4b52664e2SAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License"); 5b52664e2SAppaRao Puli // you may not use this file except in compliance with the License. 6b52664e2SAppaRao Puli // You may obtain a copy of the License at 7b52664e2SAppaRao Puli // 8b52664e2SAppaRao Puli // http://www.apache.org/licenses/LICENSE-2.0 9b52664e2SAppaRao Puli // 10b52664e2SAppaRao Puli // Unless required by applicable law or agreed to in writing, software 11b52664e2SAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS, 12b52664e2SAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b52664e2SAppaRao Puli // See the License for the specific language governing permissions and 14b52664e2SAppaRao Puli // limitations under the License. 15b52664e2SAppaRao Puli */ 16b52664e2SAppaRao Puli #pragma once 17b52664e2SAppaRao Puli #include "node.hpp" 18b52664e2SAppaRao Puli 19b52664e2SAppaRao Puli #include <boost/container/flat_map.hpp> 20b52664e2SAppaRao Puli #include <cstdlib> 21b52664e2SAppaRao Puli #include <ctime> 22b52664e2SAppaRao Puli #include <error_messages.hpp> 23b52664e2SAppaRao Puli #include <http_client.hpp> 24b52664e2SAppaRao Puli #include <memory> 25b52664e2SAppaRao Puli #include <utils/json_utils.hpp> 26b52664e2SAppaRao Puli #include <variant> 27b52664e2SAppaRao Puli 28b52664e2SAppaRao Puli namespace redfish 29b52664e2SAppaRao Puli { 30b52664e2SAppaRao Puli class Subscription 31b52664e2SAppaRao Puli { 32b52664e2SAppaRao Puli public: 33b52664e2SAppaRao Puli std::string id; 34b52664e2SAppaRao Puli std::string destinationUrl; 35b52664e2SAppaRao Puli std::string protocol; 36b52664e2SAppaRao Puli std::string retryPolicy; 37b52664e2SAppaRao Puli std::string customText; 38b52664e2SAppaRao Puli std::string eventFormatType; 39b52664e2SAppaRao Puli std::string subscriptionType; 40b52664e2SAppaRao Puli std::vector<std::string> registryMsgIds; 41b52664e2SAppaRao Puli std::vector<std::string> registryPrefixes; 42b52664e2SAppaRao Puli std::vector<nlohmann::json> httpHeaders; // key-value pair 43b52664e2SAppaRao Puli 44b52664e2SAppaRao Puli Subscription(const Subscription&) = delete; 45b52664e2SAppaRao Puli Subscription& operator=(const Subscription&) = delete; 46b52664e2SAppaRao Puli Subscription(Subscription&&) = delete; 47b52664e2SAppaRao Puli Subscription& operator=(Subscription&&) = delete; 48b52664e2SAppaRao Puli 49b52664e2SAppaRao Puli Subscription(const std::string& inHost, const std::string& inPort, 50b52664e2SAppaRao Puli const std::string& inPath, const std::string& inUriProto) : 51*0b4bdd93SAppaRao Puli eventSeqNum(1), 52*0b4bdd93SAppaRao Puli host(inHost), port(inPort), path(inPath), uriProto(inUriProto) 53b52664e2SAppaRao Puli { 54b52664e2SAppaRao Puli conn = std::make_shared<crow::HttpClient>( 552a5689a7SAppaRao Puli crow::connections::systemBus->get_io_context(), host, port, path); 56b52664e2SAppaRao Puli } 57b52664e2SAppaRao Puli ~Subscription() 58b52664e2SAppaRao Puli { 59b52664e2SAppaRao Puli } 60b52664e2SAppaRao Puli 61b52664e2SAppaRao Puli void sendEvent(const std::string& msg) 62b52664e2SAppaRao Puli { 63b52664e2SAppaRao Puli std::vector<std::pair<std::string, std::string>> reqHeaders; 64b52664e2SAppaRao Puli for (const auto& header : httpHeaders) 65b52664e2SAppaRao Puli { 66b52664e2SAppaRao Puli for (const auto& item : header.items()) 67b52664e2SAppaRao Puli { 68b52664e2SAppaRao Puli std::string key = item.key(); 69b52664e2SAppaRao Puli std::string val = item.value(); 70b52664e2SAppaRao Puli reqHeaders.emplace_back(std::pair(key, val)); 71b52664e2SAppaRao Puli } 72b52664e2SAppaRao Puli } 73b52664e2SAppaRao Puli conn->setHeaders(reqHeaders); 742a5689a7SAppaRao Puli conn->sendData(msg); 75b52664e2SAppaRao Puli } 76b52664e2SAppaRao Puli 77*0b4bdd93SAppaRao Puli void sendTestEventLog() 78*0b4bdd93SAppaRao Puli { 79*0b4bdd93SAppaRao Puli nlohmann::json logEntryArray; 80*0b4bdd93SAppaRao Puli logEntryArray.push_back({}); 81*0b4bdd93SAppaRao Puli nlohmann::json& logEntryJson = logEntryArray.back(); 82*0b4bdd93SAppaRao Puli 83*0b4bdd93SAppaRao Puli logEntryJson = {{"EventId", "TestID"}, 84*0b4bdd93SAppaRao Puli {"EventType", "Event"}, 85*0b4bdd93SAppaRao Puli {"Severity", "OK"}, 86*0b4bdd93SAppaRao Puli {"Message", "Generated test event"}, 87*0b4bdd93SAppaRao Puli {"MessageId", "OpenBMC.0.1.TestEventLog"}, 88*0b4bdd93SAppaRao Puli {"MessageArgs", nlohmann::json::array()}, 89*0b4bdd93SAppaRao Puli {"EventTimestamp", crow::utility::dateTimeNow()}, 90*0b4bdd93SAppaRao Puli {"Context", customText}}; 91*0b4bdd93SAppaRao Puli 92*0b4bdd93SAppaRao Puli nlohmann::json msg = {{"@odata.type", "#Event.v1_4_0.Event"}, 93*0b4bdd93SAppaRao Puli {"Id", std::to_string(eventSeqNum)}, 94*0b4bdd93SAppaRao Puli {"Name", "Event Log"}, 95*0b4bdd93SAppaRao Puli {"Events", logEntryArray}}; 96*0b4bdd93SAppaRao Puli 97*0b4bdd93SAppaRao Puli this->sendEvent(msg.dump()); 98*0b4bdd93SAppaRao Puli this->eventSeqNum++; 99*0b4bdd93SAppaRao Puli } 100*0b4bdd93SAppaRao Puli 101b52664e2SAppaRao Puli private: 102*0b4bdd93SAppaRao Puli uint64_t eventSeqNum; 103b52664e2SAppaRao Puli std::string host; 104b52664e2SAppaRao Puli std::string port; 105b52664e2SAppaRao Puli std::string path; 106b52664e2SAppaRao Puli std::string uriProto; 107b52664e2SAppaRao Puli std::shared_ptr<crow::HttpClient> conn; 108b52664e2SAppaRao Puli }; 109b52664e2SAppaRao Puli 110b52664e2SAppaRao Puli class EventServiceManager 111b52664e2SAppaRao Puli { 112b52664e2SAppaRao Puli private: 113b52664e2SAppaRao Puli EventServiceManager(const EventServiceManager&) = delete; 114b52664e2SAppaRao Puli EventServiceManager& operator=(const EventServiceManager&) = delete; 115b52664e2SAppaRao Puli EventServiceManager(EventServiceManager&&) = delete; 116b52664e2SAppaRao Puli EventServiceManager& operator=(EventServiceManager&&) = delete; 117b52664e2SAppaRao Puli 118b52664e2SAppaRao Puli EventServiceManager() 119b52664e2SAppaRao Puli { 120b52664e2SAppaRao Puli // TODO: Read the persistent data from store and populate. 121b52664e2SAppaRao Puli // Populating with default. 122b52664e2SAppaRao Puli enabled = true; 123b52664e2SAppaRao Puli retryAttempts = 3; 124b52664e2SAppaRao Puli retryTimeoutInterval = 30; // seconds 125b52664e2SAppaRao Puli } 126b52664e2SAppaRao Puli 127b52664e2SAppaRao Puli boost::container::flat_map<std::string, std::shared_ptr<Subscription>> 128b52664e2SAppaRao Puli subscriptionsMap; 129b52664e2SAppaRao Puli 130b52664e2SAppaRao Puli public: 131b52664e2SAppaRao Puli bool enabled; 132b52664e2SAppaRao Puli uint32_t retryAttempts; 133b52664e2SAppaRao Puli uint32_t retryTimeoutInterval; 134b52664e2SAppaRao Puli 135b52664e2SAppaRao Puli static EventServiceManager& getInstance() 136b52664e2SAppaRao Puli { 137b52664e2SAppaRao Puli static EventServiceManager handler; 138b52664e2SAppaRao Puli return handler; 139b52664e2SAppaRao Puli } 140b52664e2SAppaRao Puli 141b52664e2SAppaRao Puli void updateSubscriptionData() 142b52664e2SAppaRao Puli { 143b52664e2SAppaRao Puli // Persist the config and subscription data. 144b52664e2SAppaRao Puli // TODO: subscriptionsMap & configData need to be 145b52664e2SAppaRao Puli // written to Persist store. 146b52664e2SAppaRao Puli return; 147b52664e2SAppaRao Puli } 148b52664e2SAppaRao Puli 149b52664e2SAppaRao Puli std::shared_ptr<Subscription> getSubscription(const std::string& id) 150b52664e2SAppaRao Puli { 151b52664e2SAppaRao Puli auto obj = subscriptionsMap.find(id); 152b52664e2SAppaRao Puli if (obj == subscriptionsMap.end()) 153b52664e2SAppaRao Puli { 154b52664e2SAppaRao Puli BMCWEB_LOG_ERROR << "No subscription exist with ID:" << id; 155b52664e2SAppaRao Puli return nullptr; 156b52664e2SAppaRao Puli } 157b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = obj->second; 158b52664e2SAppaRao Puli return subValue; 159b52664e2SAppaRao Puli } 160b52664e2SAppaRao Puli 161b52664e2SAppaRao Puli std::string addSubscription(const std::shared_ptr<Subscription> subValue) 162b52664e2SAppaRao Puli { 163b52664e2SAppaRao Puli std::srand(static_cast<uint32_t>(std::time(0))); 164b52664e2SAppaRao Puli std::string id; 165b52664e2SAppaRao Puli 166b52664e2SAppaRao Puli int retry = 3; 167b52664e2SAppaRao Puli while (retry) 168b52664e2SAppaRao Puli { 169b52664e2SAppaRao Puli id = std::to_string(std::rand()); 170b52664e2SAppaRao Puli auto inserted = subscriptionsMap.insert(std::pair(id, subValue)); 171b52664e2SAppaRao Puli if (inserted.second) 172b52664e2SAppaRao Puli { 173b52664e2SAppaRao Puli break; 174b52664e2SAppaRao Puli } 175b52664e2SAppaRao Puli --retry; 176b52664e2SAppaRao Puli }; 177b52664e2SAppaRao Puli 178b52664e2SAppaRao Puli if (retry <= 0) 179b52664e2SAppaRao Puli { 180b52664e2SAppaRao Puli BMCWEB_LOG_ERROR << "Failed to generate random number"; 181b52664e2SAppaRao Puli return std::string(""); 182b52664e2SAppaRao Puli } 183b52664e2SAppaRao Puli 184b52664e2SAppaRao Puli updateSubscriptionData(); 185b52664e2SAppaRao Puli return id; 186b52664e2SAppaRao Puli } 187b52664e2SAppaRao Puli 188b52664e2SAppaRao Puli bool isSubscriptionExist(const std::string& id) 189b52664e2SAppaRao Puli { 190b52664e2SAppaRao Puli auto obj = subscriptionsMap.find(id); 191b52664e2SAppaRao Puli if (obj == subscriptionsMap.end()) 192b52664e2SAppaRao Puli { 193b52664e2SAppaRao Puli return false; 194b52664e2SAppaRao Puli } 195b52664e2SAppaRao Puli return true; 196b52664e2SAppaRao Puli } 197b52664e2SAppaRao Puli 198b52664e2SAppaRao Puli void deleteSubscription(const std::string& id) 199b52664e2SAppaRao Puli { 200b52664e2SAppaRao Puli auto obj = subscriptionsMap.find(id); 201b52664e2SAppaRao Puli if (obj != subscriptionsMap.end()) 202b52664e2SAppaRao Puli { 203b52664e2SAppaRao Puli subscriptionsMap.erase(obj); 204b52664e2SAppaRao Puli updateSubscriptionData(); 205b52664e2SAppaRao Puli } 206b52664e2SAppaRao Puli } 207b52664e2SAppaRao Puli 208b52664e2SAppaRao Puli size_t getNumberOfSubscriptions() 209b52664e2SAppaRao Puli { 210b52664e2SAppaRao Puli return subscriptionsMap.size(); 211b52664e2SAppaRao Puli } 212b52664e2SAppaRao Puli 213b52664e2SAppaRao Puli std::vector<std::string> getAllIDs() 214b52664e2SAppaRao Puli { 215b52664e2SAppaRao Puli std::vector<std::string> idList; 216b52664e2SAppaRao Puli for (const auto& it : subscriptionsMap) 217b52664e2SAppaRao Puli { 218b52664e2SAppaRao Puli idList.emplace_back(it.first); 219b52664e2SAppaRao Puli } 220b52664e2SAppaRao Puli return idList; 221b52664e2SAppaRao Puli } 222b52664e2SAppaRao Puli 223b52664e2SAppaRao Puli bool isDestinationExist(const std::string& destUrl) 224b52664e2SAppaRao Puli { 225b52664e2SAppaRao Puli for (const auto& it : subscriptionsMap) 226b52664e2SAppaRao Puli { 227b52664e2SAppaRao Puli std::shared_ptr<Subscription> entry = it.second; 228b52664e2SAppaRao Puli if (entry->destinationUrl == destUrl) 229b52664e2SAppaRao Puli { 230b52664e2SAppaRao Puli BMCWEB_LOG_ERROR << "Destination exist already" << destUrl; 231b52664e2SAppaRao Puli return true; 232b52664e2SAppaRao Puli } 233b52664e2SAppaRao Puli } 234b52664e2SAppaRao Puli return false; 235b52664e2SAppaRao Puli } 236*0b4bdd93SAppaRao Puli 237*0b4bdd93SAppaRao Puli void sendTestEventLog() 238*0b4bdd93SAppaRao Puli { 239*0b4bdd93SAppaRao Puli for (const auto& it : this->subscriptionsMap) 240*0b4bdd93SAppaRao Puli { 241*0b4bdd93SAppaRao Puli std::shared_ptr<Subscription> entry = it.second; 242*0b4bdd93SAppaRao Puli entry->sendTestEventLog(); 243*0b4bdd93SAppaRao Puli } 244*0b4bdd93SAppaRao Puli } 245b52664e2SAppaRao Puli }; 246b52664e2SAppaRao Puli 247b52664e2SAppaRao Puli } // namespace redfish 248