blob: 35b30ec95f2cff3c654b2c952de4981a8ff1a13d [file] [log] [blame]
Patrick Venture91ac8d32018-11-01 17:03:22 -07001#include "fru-fault-monitor.hpp"
2
3#include "elog-errors.hpp"
Patrick Venture91ac8d32018-11-01 17:03:22 -07004
5#include <phosphor-logging/elog.hpp>
6#include <sdbusplus/exception.hpp>
George Liu4b062012020-10-13 15:26:58 +08007#include <xyz/openbmc_project/Led/Fru/Monitor/error.hpp>
8#include <xyz/openbmc_project/Led/Mapper/error.hpp>
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -05009
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050010namespace phosphor
11{
12namespace led
13{
14namespace fru
15{
16namespace fault
17{
18namespace monitor
19{
20
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050021using namespace phosphor::logging;
22
Patrick Venture91ac8d32018-11-01 17:03:22 -070023constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
24constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
25constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
26constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager";
27constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/";
28constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
29constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry";
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050030
Patrick Venture91ac8d32018-11-01 17:03:22 -070031using AssociationList =
32 std::vector<std::tuple<std::string, std::string, std::string>>;
Patrick Williamsa41d2822020-05-13 17:57:23 -050033using Attributes = std::variant<bool, AssociationList>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050034using PropertyName = std::string;
Matt Spinlerb2f253b2018-06-13 09:54:13 -050035using PropertyMap = std::map<PropertyName, Attributes>;
36using InterfaceName = std::string;
37using InterfaceMap = std::map<InterfaceName, PropertyMap>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050038
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050039using Service = std::string;
40using Path = std::string;
41using Interface = std::string;
42using Interfaces = std::vector<Interface>;
43using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
44
Patrick Venture91ac8d32018-11-01 17:03:22 -070045using MethodErr =
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050046 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::MethodError;
47using ObjectNotFoundErr =
48 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::ObjectNotFoundError;
Patrick Venture91ac8d32018-11-01 17:03:22 -070049using InventoryPathErr = sdbusplus::xyz::openbmc_project::Led::Fru::Monitor::
50 Error::InventoryPathError;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050051
Patrick Venture91ac8d32018-11-01 17:03:22 -070052std::string getService(sdbusplus::bus::bus& bus, const std::string& path)
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050053{
Patrick Venture91ac8d32018-11-01 17:03:22 -070054 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050055 MAPPER_IFACE, "GetObject");
56 mapper.append(path.c_str(), std::vector<std::string>({OBJMGR_IFACE}));
57 auto mapperResponseMsg = bus.call(mapper);
58 if (mapperResponseMsg.is_method_error())
59 {
60 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -070061 elog<MethodErr>(MethodError::METHOD_NAME("GetObject"),
62 MethodError::PATH(path.c_str()),
63 MethodError::INTERFACE(OBJMGR_IFACE));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050064 }
65
66 std::map<std::string, std::vector<std::string>> mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -070067 try
68 {
69 mapperResponseMsg.read(mapperResponse);
70 }
71 catch (const sdbusplus::exception::SdBusError& e)
72 {
Patrick Venture91ac8d32018-11-01 17:03:22 -070073 log<level::ERR>(
74 "Failed to parse getService mapper response",
75 entry("ERROR=%s", e.what()),
76 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
William A. Kennington III151122a2018-05-15 12:00:32 -070077 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -070078 elog<ObjectNotFoundErr>(ObjectNotFoundError::METHOD_NAME("GetObject"),
79 ObjectNotFoundError::PATH(path.c_str()),
80 ObjectNotFoundError::INTERFACE(OBJMGR_IFACE));
William A. Kennington III151122a2018-05-15 12:00:32 -070081 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050082 if (mapperResponse.empty())
83 {
84 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -070085 elog<ObjectNotFoundErr>(ObjectNotFoundError::METHOD_NAME("GetObject"),
86 ObjectNotFoundError::PATH(path.c_str()),
87 ObjectNotFoundError::INTERFACE(OBJMGR_IFACE));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050088 }
89
90 return mapperResponse.cbegin()->first;
91}
92
Patrick Venture91ac8d32018-11-01 17:03:22 -070093void action(sdbusplus::bus::bus& bus, const std::string& path, bool assert)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050094{
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050095 std::string service;
96 try
97 {
Matt Spinlere77b8342018-09-12 10:41:53 -050098 std::string groups{LED_GROUPS};
99 groups.pop_back();
100 service = getService(bus, groups);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500101 }
102 catch (MethodErr& e)
103 {
104 commit<MethodErr>();
105 return;
106 }
107 catch (ObjectNotFoundErr& e)
108 {
109 commit<ObjectNotFoundErr>();
110 return;
111 }
112
113 auto pos = path.rfind("/");
114 if (pos == std::string::npos)
115 {
116 using namespace xyz::openbmc_project::Led::Fru::Monitor;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700117 report<InventoryPathErr>(InventoryPathError::PATH(path.c_str()));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500118 return;
119 }
120 auto unit = path.substr(pos + 1);
121
Patrick Venture91ac8d32018-11-01 17:03:22 -0700122 std::string ledPath = LED_GROUPS + unit + '_' + LED_FAULT;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500123
Patrick Venture91ac8d32018-11-01 17:03:22 -0700124 auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
125 "org.freedesktop.DBus.Properties", "Set");
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500126 method.append("xyz.openbmc_project.Led.Group");
127 method.append("Asserted");
128
Patrick Williamsa41d2822020-05-13 17:57:23 -0500129 method.append(std::variant<bool>(assert));
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500130
131 try
132 {
133 bus.call_noreply(method);
134 }
135 catch (const sdbusplus::exception::SdBusError& e)
136 {
137 // Log an info message, system may not have all the LED Groups defined
138 log<level::INFO>("Failed to Assert LED Group",
139 entry("ERROR=%s", e.what()));
140 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500141
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500142 return;
143}
144
Patrick Williams3eedbe42017-05-31 17:27:05 -0500145void Add::created(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500146{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500147 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500148
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500149 sdbusplus::message::object_path objectPath;
150 InterfaceMap interfaces;
William A. Kennington III151122a2018-05-15 12:00:32 -0700151 try
152 {
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500153 msg.read(objectPath, interfaces);
William A. Kennington III151122a2018-05-15 12:00:32 -0700154 }
155 catch (const sdbusplus::exception::SdBusError& e)
156 {
157 log<level::ERR>("Failed to parse created message",
158 entry("ERROR=%s", e.what()),
159 entry("REPLY_SIG=%s", msg.get_signature()));
160 return;
161 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500162
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500163 std::size_t found = objectPath.str.find(ELOG_ENTRY);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500164 if (found == std::string::npos)
165 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700166 // Not a new error entry skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500167 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500168 }
Andrew Geisslera6e48922019-11-06 08:43:54 -0600169 auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500170 if (iter == interfaces.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500171 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500172 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500173 }
174
Patrick Venture91ac8d32018-11-01 17:03:22 -0700175 // Nothing else shows when a specific error log
176 // has been created. Do it here.
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500177 std::string message{objectPath.str + " created"};
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500178 log<level::INFO>(message.c_str());
179
Andrew Geisslera6e48922019-11-06 08:43:54 -0600180 auto attr = iter->second.find("Associations");
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500181 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500182 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500183 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500184 }
185
Patrick Williams5ebebef2020-05-13 11:47:27 -0500186 auto& assocs = std::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500187 if (assocs.empty())
188 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700189 // No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500190 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500191 }
192
193 for (const auto& item : assocs)
194 {
195 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
196 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500197 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500198 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500199 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500200 }
201 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500202
Patrick Williams3eedbe42017-05-31 17:27:05 -0500203 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500204}
205
Matt Spinler91122922018-09-24 11:31:44 -0500206void getLoggingSubTree(sdbusplus::bus::bus& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500207{
208 auto depth = 0;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700209 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
210 MAPPER_IFACE, "GetSubTree");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500211 mapperCall.append("/");
212 mapperCall.append(depth);
213 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
214
William A. Kennington III151122a2018-05-15 12:00:32 -0700215 try
216 {
Matt Spinler91122922018-09-24 11:31:44 -0500217 auto mapperResponseMsg = bus.call(mapperCall);
218 if (mapperResponseMsg.is_method_error())
219 {
220 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700221 report<MethodErr>(MethodError::METHOD_NAME("GetSubTree"),
222 MethodError::PATH(MAPPER_OBJ_PATH),
223 MethodError::INTERFACE(OBJMGR_IFACE));
Matt Spinler91122922018-09-24 11:31:44 -0500224 return;
225 }
226
227 try
228 {
229 mapperResponseMsg.read(subtree);
230 }
231 catch (const sdbusplus::exception::SdBusError& e)
232 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700233 log<level::ERR>(
234 "Failed to parse existing callouts subtree message",
235 entry("ERROR=%s", e.what()),
236 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
Matt Spinler91122922018-09-24 11:31:44 -0500237 }
William A. Kennington III151122a2018-05-15 12:00:32 -0700238 }
239 catch (const sdbusplus::exception::SdBusError& e)
240 {
Matt Spinler91122922018-09-24 11:31:44 -0500241 // Just means no log entries at the moment
William A. Kennington III151122a2018-05-15 12:00:32 -0700242 }
Matt Spinler91122922018-09-24 11:31:44 -0500243}
244
245void Add::processExistingCallouts(sdbusplus::bus::bus& bus)
246{
Patrick Venture91ac8d32018-11-01 17:03:22 -0700247 MapperResponseType mapperResponse;
Matt Spinler91122922018-09-24 11:31:44 -0500248
249 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500250 if (mapperResponse.empty())
251 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700252 // No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500253 return;
254 }
255
256 for (const auto& elem : mapperResponse)
257 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700258 auto method = bus.new_method_call(
259 elem.second.begin()->first.c_str(), elem.first.c_str(),
260 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslera6e48922019-11-06 08:43:54 -0600261 method.append("xyz.openbmc_project.Association.Definitions");
262 method.append("Associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500263 auto reply = bus.call(method);
264 if (reply.is_method_error())
265 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700266 // do not stop, continue with next elog
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500267 log<level::ERR>("Error in getting associations");
268 continue;
269 }
270
Patrick Williamsa41d2822020-05-13 17:57:23 -0500271 std::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700272 try
273 {
274 reply.read(assoc);
275 }
276 catch (const sdbusplus::exception::SdBusError& e)
277 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700278 log<level::ERR>(
279 "Failed to parse existing callouts associations message",
280 entry("ERROR=%s", e.what()),
281 entry("REPLY_SIG=%s", reply.get_signature()));
William A. Kennington III151122a2018-05-15 12:00:32 -0700282 continue;
283 }
Patrick Williams5ebebef2020-05-13 11:47:27 -0500284 auto& assocs = std::get<AssociationList>(assoc);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500285 if (assocs.empty())
286 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700287 // no associations, skip
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500288 continue;
289 }
290
291 for (const auto& item : assocs)
292 {
293 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
294 {
295 removeWatches.emplace_back(
296 std::make_unique<Remove>(bus, std::get<2>(item)));
297 action(bus, std::get<2>(item), true);
298 }
299 }
300 }
301}
302
Patrick Williams3eedbe42017-05-31 17:27:05 -0500303void Remove::removed(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500304{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500305 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500306
Patrick Williams3eedbe42017-05-31 17:27:05 -0500307 action(bus, inventoryPath, false);
308 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500309}
310
Patrick Venture91ac8d32018-11-01 17:03:22 -0700311} // namespace monitor
312} // namespace fault
313} // namespace fru
314} // namespace led
315} // namespace phosphor