xref: /openbmc/bmcweb/features/redfish/include/event_service_manager.hpp (revision 0b4bdd93c79779913fcfc3641beb5f7f3966f339)
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