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