blob: a7ed952c8e8ef31166c6ebd0ec08c63ad5400a9d [file] [log] [blame]
Patrick Venture91ac8d32018-11-01 17:03:22 -07001#include "fru-fault-monitor.hpp"
2
3#include "elog-errors.hpp"
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -05004#include "xyz/openbmc_project/Led/Fru/Monitor/error.hpp"
5#include "xyz/openbmc_project/Led/Mapper/error.hpp"
Patrick Venture91ac8d32018-11-01 17:03:22 -07006
7#include <phosphor-logging/elog.hpp>
8#include <sdbusplus/exception.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>>;
33using Attributes = sdbusplus::message::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
129 method.append(sdbusplus::message::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 }
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500169 auto iter = interfaces.find("org.openbmc.Associations");
170 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
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500180 auto attr = iter->second.find("associations");
181 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
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500186 auto& assocs =
187 sdbusplus::message::variant_ns::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500188 if (assocs.empty())
189 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700190 // No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500191 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500192 }
193
194 for (const auto& item : assocs)
195 {
196 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
197 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500198 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500199 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500200 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500201 }
202 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500203
Patrick Williams3eedbe42017-05-31 17:27:05 -0500204 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500205}
206
Matt Spinler91122922018-09-24 11:31:44 -0500207void getLoggingSubTree(sdbusplus::bus::bus& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500208{
209 auto depth = 0;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700210 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
211 MAPPER_IFACE, "GetSubTree");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500212 mapperCall.append("/");
213 mapperCall.append(depth);
214 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
215
William A. Kennington III151122a2018-05-15 12:00:32 -0700216 try
217 {
Matt Spinler91122922018-09-24 11:31:44 -0500218 auto mapperResponseMsg = bus.call(mapperCall);
219 if (mapperResponseMsg.is_method_error())
220 {
221 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700222 report<MethodErr>(MethodError::METHOD_NAME("GetSubTree"),
223 MethodError::PATH(MAPPER_OBJ_PATH),
224 MethodError::INTERFACE(OBJMGR_IFACE));
Matt Spinler91122922018-09-24 11:31:44 -0500225 return;
226 }
227
228 try
229 {
230 mapperResponseMsg.read(subtree);
231 }
232 catch (const sdbusplus::exception::SdBusError& e)
233 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700234 log<level::ERR>(
235 "Failed to parse existing callouts subtree message",
236 entry("ERROR=%s", e.what()),
237 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
Matt Spinler91122922018-09-24 11:31:44 -0500238 }
William A. Kennington III151122a2018-05-15 12:00:32 -0700239 }
240 catch (const sdbusplus::exception::SdBusError& e)
241 {
Matt Spinler91122922018-09-24 11:31:44 -0500242 // Just means no log entries at the moment
William A. Kennington III151122a2018-05-15 12:00:32 -0700243 }
Matt Spinler91122922018-09-24 11:31:44 -0500244}
245
246void Add::processExistingCallouts(sdbusplus::bus::bus& bus)
247{
Patrick Venture91ac8d32018-11-01 17:03:22 -0700248 MapperResponseType mapperResponse;
Matt Spinler91122922018-09-24 11:31:44 -0500249
250 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500251 if (mapperResponse.empty())
252 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700253 // No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500254 return;
255 }
256
257 for (const auto& elem : mapperResponse)
258 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700259 auto method = bus.new_method_call(
260 elem.second.begin()->first.c_str(), elem.first.c_str(),
261 "org.freedesktop.DBus.Properties", "Get");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500262 method.append("org.openbmc.Associations");
263 method.append("associations");
264 auto reply = bus.call(method);
265 if (reply.is_method_error())
266 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700267 // do not stop, continue with next elog
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500268 log<level::ERR>("Error in getting associations");
269 continue;
270 }
271
272 sdbusplus::message::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700273 try
274 {
275 reply.read(assoc);
276 }
277 catch (const sdbusplus::exception::SdBusError& e)
278 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700279 log<level::ERR>(
280 "Failed to parse existing callouts associations message",
281 entry("ERROR=%s", e.what()),
282 entry("REPLY_SIG=%s", reply.get_signature()));
William A. Kennington III151122a2018-05-15 12:00:32 -0700283 continue;
284 }
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500285 auto& assocs = assoc.get<AssociationList>();
286 if (assocs.empty())
287 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700288 // no associations, skip
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500289 continue;
290 }
291
292 for (const auto& item : assocs)
293 {
294 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
295 {
296 removeWatches.emplace_back(
297 std::make_unique<Remove>(bus, std::get<2>(item)));
298 action(bus, std::get<2>(item), true);
299 }
300 }
301 }
302}
303
Patrick Williams3eedbe42017-05-31 17:27:05 -0500304void Remove::removed(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500305{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500306 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500307
Patrick Williams3eedbe42017-05-31 17:27:05 -0500308 action(bus, inventoryPath, false);
309 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500310}
311
Patrick Venture91ac8d32018-11-01 17:03:22 -0700312} // namespace monitor
313} // namespace fault
314} // namespace fru
315} // namespace led
316} // namespace phosphor