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