xref: /openbmc/phosphor-modbus/common/events.cpp (revision 7184805ae4ede906935133e3e0f8ee2468bc781b)
1 #include "events.hpp"
2 
3 #include <phosphor-logging/commit.hpp>
4 #include <phosphor-logging/lg2.hpp>
5 #include <sdbusplus/async.hpp>
6 #include <xyz/openbmc_project/Sensor/Threshold/event.hpp>
7 #include <xyz/openbmc_project/Sensor/event.hpp>
8 #include <xyz/openbmc_project/State/Fan/event.hpp>
9 #include <xyz/openbmc_project/State/Filter/event.hpp>
10 #include <xyz/openbmc_project/State/Leak/Detector/event.hpp>
11 #include <xyz/openbmc_project/State/Power/event.hpp>
12 #include <xyz/openbmc_project/State/Pump/event.hpp>
13 #include <xyz/openbmc_project/State/SMC/event.hpp>
14 
15 namespace phosphor::modbus::events
16 {
17 
18 PHOSPHOR_LOG2_USING;
19 
20 const std::unordered_map<EventLevel, std::string> eventLevelToName = {
21     {EventLevel::critical, "Critical"},
22     {EventLevel::warning, "Warning"},
23 };
24 
generateSensorReadingEvent(sdbusplus::message::object_path objectPath,EventLevel level,double value,SensorValueIntf::Unit unit,bool asserted)25 auto Events::generateSensorReadingEvent(
26     sdbusplus::message::object_path objectPath, EventLevel level, double value,
27     SensorValueIntf::Unit unit, bool asserted) -> sdbusplus::async::task<>
28 {
29     namespace error_intf =
30         sdbusplus::error::xyz::openbmc_project::sensor::Threshold;
31     namespace event_intf =
32         sdbusplus::event::xyz::openbmc_project::sensor::Threshold;
33 
34     auto eventName =
35         objectPath.str + ".threshold." + eventLevelToName.at(level);
36     auto pendingEvent = pendingEvents.find(eventName);
37 
38     if (asserted)
39     {
40         if (pendingEvent == pendingEvents.end())
41         {
42             sdbusplus::message::object_path eventPath{};
43             if (level == EventLevel::critical)
44             {
45                 eventPath = co_await lg2::commit(
46                     ctx, error_intf::ReadingCritical("SENSOR_NAME", objectPath,
47                                                      "READING_VALUE", value,
48                                                      "UNITS", unit));
49             }
50             else
51             {
52                 eventPath = co_await lg2::commit(
53                     ctx, error_intf::ReadingWarning("SENSOR_NAME", objectPath,
54                                                     "READING_VALUE", value,
55                                                     "UNITS", unit));
56             }
57 
58             pendingEvents.emplace(eventName, eventPath);
59         }
60     }
61     else
62     {
63         if (pendingEvent != pendingEvents.end())
64         {
65             co_await lg2::resolve(ctx, pendingEvent->second);
66 
67             co_await lg2::commit(ctx,
68                                  event_intf::SensorReadingNormalRange(
69                                      "SENSOR_NAME", objectPath, "READING_VALUE",
70                                      value, "UNITS", unit));
71 
72             pendingEvents.erase(eventName);
73         }
74     }
75 
76     debug("Sensor reading event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
77           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
78 }
79 
generateSensorFailureEvent(sdbusplus::message::object_path objectPath,bool asserted)80 auto Events::generateSensorFailureEvent(
81     sdbusplus::message::object_path objectPath, bool asserted)
82     -> sdbusplus::async::task<>
83 {
84     namespace error_intf = sdbusplus::error::xyz::openbmc_project::Sensor;
85     namespace event_intf = sdbusplus::event::xyz::openbmc_project::Sensor;
86 
87     auto eventName = objectPath.str + ".SensorFailure";
88     auto pendingEvent = pendingEvents.find(eventName);
89 
90     if (asserted)
91     {
92         if (pendingEvent == pendingEvents.end())
93         {
94             auto eventPath = co_await lg2::commit(
95                 ctx, error_intf::SensorFailure("SENSOR_NAME", objectPath));
96             pendingEvents.emplace(eventName, eventPath);
97         }
98     }
99     else
100     {
101         if (pendingEvent != pendingEvents.end())
102         {
103             co_await lg2::resolve(ctx, pendingEvent->second);
104 
105             co_await lg2::commit(
106                 ctx, event_intf::SensorRestored("SENSOR_NAME", objectPath));
107             pendingEvents.erase(eventName);
108         }
109     }
110 
111     debug("Sensor failure event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
112           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
113 }
114 
generateControllerFailureEvent(sdbusplus::message::object_path objectPath,std::string additionalInfo,bool asserted)115 auto Events::generateControllerFailureEvent(
116     sdbusplus::message::object_path objectPath, std::string additionalInfo,
117     bool asserted) -> sdbusplus::async::task<>
118 {
119     namespace error_intf = sdbusplus::error::xyz::openbmc_project::state::SMC;
120     namespace event_intf = sdbusplus::event::xyz::openbmc_project::state::SMC;
121 
122     auto eventName = objectPath.str + ".ControllerFailure." + additionalInfo;
123     auto pendingEvent = pendingEvents.find(eventName);
124 
125     if (asserted)
126     {
127         if (pendingEvent == pendingEvents.end())
128         {
129             auto eventPath = co_await lg2::commit(
130                 ctx, error_intf::SMCFailed("IDENTIFIER", objectPath,
131                                            "FAILURE_TYPE", additionalInfo));
132             pendingEvents.emplace(eventName, eventPath);
133         }
134     }
135     else
136     {
137         if (pendingEvent != pendingEvents.end())
138         {
139             co_await lg2::resolve(ctx, pendingEvent->second);
140 
141             co_await lg2::commit(
142                 ctx, event_intf::SMCRestored("IDENTIFIER", objectPath));
143 
144             pendingEvents.erase(eventName);
145         }
146     }
147 
148     debug("Controller failure event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
149           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
150 }
151 
generatePowerFaultEvent(sdbusplus::message::object_path objectPath,std::string additionalInfo,bool asserted)152 auto Events::generatePowerFaultEvent(sdbusplus::message::object_path objectPath,
153                                      std::string additionalInfo, bool asserted)
154     -> sdbusplus::async::task<>
155 {
156     namespace error_intf = sdbusplus::error::xyz::openbmc_project::state::Power;
157     namespace event_intf = sdbusplus::event::xyz::openbmc_project::state::Power;
158 
159     auto eventName = objectPath.str + ".PowerFailure." + additionalInfo;
160     auto pendingEvent = pendingEvents.find(eventName);
161 
162     if (asserted)
163     {
164         if (pendingEvent == pendingEvents.end())
165         {
166             auto eventPath = co_await lg2::commit(
167                 ctx,
168                 error_intf::PowerRailFault("POWER_RAIL", objectPath,
169                                            "FAILURE_DATA", additionalInfo));
170             pendingEvents.emplace(eventName, eventPath);
171         }
172     }
173     else
174     {
175         if (pendingEvent != pendingEvents.end())
176         {
177             co_await lg2::resolve(ctx, pendingEvent->second);
178 
179             co_await lg2::commit(ctx, event_intf::PowerRailFaultRecovered(
180                                           "POWER_RAIL", objectPath));
181 
182             pendingEvents.erase(eventName);
183         }
184     }
185 
186     debug("Power fault event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
187           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
188 }
189 
generateFilterFailureEvent(sdbusplus::message::object_path objectPath,bool asserted)190 auto Events::generateFilterFailureEvent(
191     sdbusplus::message::object_path objectPath, bool asserted)
192     -> sdbusplus::async::task<>
193 {
194     namespace error_intf =
195         sdbusplus::error::xyz::openbmc_project::state::Filter;
196     namespace event_intf =
197         sdbusplus::event::xyz::openbmc_project::state::Filter;
198 
199     auto eventName = objectPath.str + ".FilterFailure";
200     auto pendingEvent = pendingEvents.find(eventName);
201 
202     if (asserted)
203     {
204         if (pendingEvent == pendingEvents.end())
205         {
206             auto eventPath = co_await lg2::commit(
207                 ctx,
208                 error_intf::FilterRequiresService("FILTER_NAME", objectPath));
209             pendingEvents.emplace(eventName, eventPath);
210         }
211     }
212     else
213     {
214         if (pendingEvent != pendingEvents.end())
215         {
216             co_await lg2::resolve(ctx, pendingEvent->second);
217 
218             co_await lg2::commit(
219                 ctx, event_intf::FilterRestored("FILTER_NAME", objectPath));
220 
221             pendingEvents.erase(eventName);
222         }
223     }
224 
225     debug("Filter failure event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
226           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
227 }
228 
generatePumpFailureEvent(sdbusplus::message::object_path objectPath,bool asserted)229 auto Events::generatePumpFailureEvent(
230     sdbusplus::message::object_path objectPath, bool asserted)
231     -> sdbusplus::async::task<>
232 {
233     namespace error_intf = sdbusplus::error::xyz::openbmc_project::state::Pump;
234     namespace event_intf = sdbusplus::event::xyz::openbmc_project::state::Pump;
235 
236     auto eventName = objectPath.str + ".PumpFailure";
237     auto pendingEvent = pendingEvents.find(eventName);
238 
239     if (asserted)
240     {
241         if (pendingEvent == pendingEvents.end())
242         {
243             auto eventPath = co_await lg2::commit(
244                 ctx, error_intf::PumpFailed("PUMP_NAME", objectPath));
245             pendingEvents.emplace(eventName, eventPath);
246         }
247     }
248     else
249     {
250         if (pendingEvent != pendingEvents.end())
251         {
252             co_await lg2::resolve(ctx, pendingEvent->second);
253 
254             co_await lg2::commit(
255                 ctx, event_intf::PumpRestored("PUMP_NAME", objectPath));
256 
257             pendingEvents.erase(eventName);
258         }
259     }
260 
261     debug("Pump failure event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
262           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
263 }
264 
generateFanFailureEvent(sdbusplus::message::object_path objectPath,bool asserted)265 auto Events::generateFanFailureEvent(sdbusplus::message::object_path objectPath,
266                                      bool asserted) -> sdbusplus::async::task<>
267 {
268     namespace error_intf = sdbusplus::error::xyz::openbmc_project::state::Fan;
269     namespace event_intf = sdbusplus::event::xyz::openbmc_project::state::Fan;
270 
271     auto eventName = objectPath.str + ".FanFailure";
272     auto pendingEvent = pendingEvents.find(eventName);
273 
274     if (asserted)
275     {
276         if (pendingEvent == pendingEvents.end())
277         {
278             auto eventPath = co_await lg2::commit(
279                 ctx, error_intf::FanFailed("FAN_NAME", objectPath));
280             pendingEvents.emplace(eventName, eventPath);
281         }
282     }
283     else
284     {
285         if (pendingEvent != pendingEvents.end())
286         {
287             co_await lg2::resolve(ctx, pendingEvent->second);
288 
289             co_await lg2::commit(
290                 ctx, event_intf::FanRestored("FAN_NAME", objectPath));
291 
292             pendingEvents.erase(eventName);
293         }
294     }
295 
296     debug("Fan failure event for {EVENT_NAME} is {STATUS}", "EVENT_NAME",
297           eventName, "STATUS", (asserted ? "asserted" : "deasserted"));
298 }
299 
generateLeakDetectedEvent(sdbusplus::message::object_path objectPath,EventLevel level,bool asserted)300 auto Events::generateLeakDetectedEvent(
301     sdbusplus::message::object_path objectPath, EventLevel level, bool asserted)
302     -> sdbusplus::async::task<>
303 {
304     auto eventName = objectPath.str + ".Leak." + eventLevelToName.at(level);
305 
306     if (!asserted)
307     {
308         auto pendingEvent = pendingEvents.find(eventName);
309         if (pendingEvent != pendingEvents.end())
310         {
311             co_await lg2::resolve(ctx, pendingEvent->second);
312 
313             using DetectorNormal = sdbusplus::event::xyz::openbmc_project::
314                 state::leak::Detector::LeakDetectedNormal;
315             co_await lg2::commit(ctx,
316                                  DetectorNormal("DETECTOR_NAME", objectPath));
317 
318             pendingEvents.erase(eventName);
319         }
320         co_return;
321     }
322 
323     namespace error_intf =
324         sdbusplus::error::xyz::openbmc_project::state::leak::Detector;
325     sdbusplus::message::object_path eventPath{};
326 
327     if (level == EventLevel::critical)
328     {
329         eventPath = co_await lg2::commit(
330             ctx, error_intf::LeakDetectedCritical("DETECTOR_NAME", objectPath));
331         error("Critical leak detected for {PATH}", "PATH", objectPath);
332     }
333     else
334     {
335         eventPath = co_await lg2::commit(
336             ctx, error_intf::LeakDetectedWarning("DETECTOR_NAME", objectPath));
337         warning("Warning leak detected for {PATH}", "PATH", objectPath);
338     }
339     pendingEvents[eventName] = eventPath;
340 }
341 
342 } // namespace phosphor::modbus::events
343