blob: aecb481c835dbc98e5b160967c2b8b438a335187 [file] [log] [blame]
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -05001#include <phosphor-logging/elog.hpp>
William A. Kennington III151122a2018-05-15 12:00:32 -07002#include <sdbusplus/exception.hpp>
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -05003#include "xyz/openbmc_project/Led/Fru/Monitor/error.hpp"
4#include "xyz/openbmc_project/Led/Mapper/error.hpp"
5#include "elog-errors.hpp"
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -05006#include "fru-fault-monitor.hpp"
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -05007
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -05008namespace phosphor
9{
10namespace led
11{
12namespace fru
13{
14namespace fault
15{
16namespace monitor
17{
18
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050019using namespace phosphor::logging;
20
21constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
22constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
23constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
24constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager";
25constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/";
26constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050027constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry";
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050028
29using AssociationList = std::vector<std::tuple<
30 std::string, std::string, std::string>>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050031using Attributes = sdbusplus::message::variant<bool,AssociationList>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050032using PropertyName = std::string;
Matt Spinlerb2f253b2018-06-13 09:54:13 -050033using PropertyMap = std::map<PropertyName, Attributes>;
34using InterfaceName = std::string;
35using InterfaceMap = std::map<InterfaceName, PropertyMap>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050036
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050037using Service = std::string;
38using Path = std::string;
39using Interface = std::string;
40using Interfaces = std::vector<Interface>;
41using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
42
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050043using MethodErr =
44 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::MethodError;
45using ObjectNotFoundErr =
46 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::ObjectNotFoundError;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050047using InventoryPathErr =
48 sdbusplus::xyz::openbmc_project::
49 Led::Fru::Monitor::Error::InventoryPathError;
50
51std::string getService(sdbusplus::bus::bus& bus,
52 const std::string& path)
53{
54 auto mapper = bus.new_method_call(MAPPER_BUSNAME,
55 MAPPER_OBJ_PATH,
56 MAPPER_IFACE, "GetObject");
57 mapper.append(path.c_str(), std::vector<std::string>({OBJMGR_IFACE}));
58 auto mapperResponseMsg = bus.call(mapper);
59 if (mapperResponseMsg.is_method_error())
60 {
61 using namespace xyz::openbmc_project::Led::Mapper;
62 elog<MethodErr>(
63 MethodError::METHOD_NAME("GetObject"),
64 MethodError::PATH(path.c_str()),
65 MethodError::INTERFACE(
66 OBJMGR_IFACE));
67 }
68
69 std::map<std::string, std::vector<std::string>> mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -070070 try
71 {
72 mapperResponseMsg.read(mapperResponse);
73 }
74 catch (const sdbusplus::exception::SdBusError& e)
75 {
76 log<level::ERR>("Failed to parse getService mapper response",
77 entry("ERROR=%s", e.what()),
78 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
79 using namespace xyz::openbmc_project::Led::Mapper;
80 elog<ObjectNotFoundErr>(
81 ObjectNotFoundError::METHOD_NAME("GetObject"),
82 ObjectNotFoundError::PATH(path.c_str()),
83 ObjectNotFoundError::INTERFACE(
84 OBJMGR_IFACE));
85 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050086 if (mapperResponse.empty())
87 {
88 using namespace xyz::openbmc_project::Led::Mapper;
89 elog<ObjectNotFoundErr>(
90 ObjectNotFoundError::METHOD_NAME("GetObject"),
91 ObjectNotFoundError::PATH(path.c_str()),
92 ObjectNotFoundError::INTERFACE(
93 OBJMGR_IFACE));
94 }
95
96 return mapperResponse.cbegin()->first;
97}
98
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050099void action(sdbusplus::bus::bus& bus,
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500100 const std::string& path,
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500101 bool assert)
102{
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500103 std::string service;
104 try
105 {
Matt Spinlere77b8342018-09-12 10:41:53 -0500106 std::string groups{LED_GROUPS};
107 groups.pop_back();
108 service = getService(bus, groups);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500109 }
110 catch (MethodErr& e)
111 {
112 commit<MethodErr>();
113 return;
114 }
115 catch (ObjectNotFoundErr& e)
116 {
117 commit<ObjectNotFoundErr>();
118 return;
119 }
120
121 auto pos = path.rfind("/");
122 if (pos == std::string::npos)
123 {
124 using namespace xyz::openbmc_project::Led::Fru::Monitor;
125 report<InventoryPathErr>(
126 InventoryPathError::PATH(
127 path.c_str()));
128 return;
129 }
130 auto unit = path.substr(pos + 1);
131
132 std::string ledPath = LED_GROUPS +
133 unit + '_' + LED_FAULT;
134
135 auto method = bus.new_method_call(service.c_str(),
136 ledPath.c_str(),
137 "org.freedesktop.DBus.Properties",
138 "Set");
139 method.append("xyz.openbmc_project.Led.Group");
140 method.append("Asserted");
141
142 method.append(sdbusplus::message::variant<bool>(assert));
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500143
144 try
145 {
146 bus.call_noreply(method);
147 }
148 catch (const sdbusplus::exception::SdBusError& e)
149 {
150 // Log an info message, system may not have all the LED Groups defined
151 log<level::INFO>("Failed to Assert LED Group",
152 entry("ERROR=%s", e.what()));
153 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500154
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500155 return;
156}
157
Patrick Williams3eedbe42017-05-31 17:27:05 -0500158void Add::created(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500159{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500160 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500161
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500162 sdbusplus::message::object_path objectPath;
163 InterfaceMap interfaces;
William A. Kennington III151122a2018-05-15 12:00:32 -0700164 try
165 {
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500166 msg.read(objectPath, interfaces);
William A. Kennington III151122a2018-05-15 12:00:32 -0700167 }
168 catch (const sdbusplus::exception::SdBusError& e)
169 {
170 log<level::ERR>("Failed to parse created message",
171 entry("ERROR=%s", e.what()),
172 entry("REPLY_SIG=%s", msg.get_signature()));
173 return;
174 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500175
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500176 std::size_t found = objectPath.str.find(ELOG_ENTRY);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500177 if (found == std::string::npos)
178 {
179 //Not a new error entry skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500180 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500181 }
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500182 auto iter = interfaces.find("org.openbmc.Associations");
183 if (iter == interfaces.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500184 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500185 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500186 }
187
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500188 //Nothing else shows when a specific error log
189 //has been created. Do it here.
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500190 std::string message{objectPath.str + " created"};
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500191 log<level::INFO>(message.c_str());
192
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500193 auto attr = iter->second.find("associations");
194 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500195 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500196 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500197 }
198
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500199 auto& assocs =
200 sdbusplus::message::variant_ns::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500201 if (assocs.empty())
202 {
203 //No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500204 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500205 }
206
207 for (const auto& item : assocs)
208 {
209 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
210 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500211 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500212 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500213 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500214 }
215 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500216
Patrick Williams3eedbe42017-05-31 17:27:05 -0500217 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500218}
219
Matt Spinler91122922018-09-24 11:31:44 -0500220void getLoggingSubTree(sdbusplus::bus::bus& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500221{
222 auto depth = 0;
223 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME,
224 MAPPER_OBJ_PATH,
225 MAPPER_IFACE,
226 "GetSubTree");
227 mapperCall.append("/");
228 mapperCall.append(depth);
229 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
230
William A. Kennington III151122a2018-05-15 12:00:32 -0700231 try
232 {
Matt Spinler91122922018-09-24 11:31:44 -0500233 auto mapperResponseMsg = bus.call(mapperCall);
234 if (mapperResponseMsg.is_method_error())
235 {
236 using namespace xyz::openbmc_project::Led::Mapper;
237 report<MethodErr>(
238 MethodError::METHOD_NAME("GetSubTree"),
239 MethodError::PATH(MAPPER_OBJ_PATH),
240 MethodError::INTERFACE(OBJMGR_IFACE));
241 return;
242 }
243
244 try
245 {
246 mapperResponseMsg.read(subtree);
247 }
248 catch (const sdbusplus::exception::SdBusError& e)
249 {
250 log<level::ERR>("Failed to parse existing callouts subtree message",
251 entry("ERROR=%s", e.what()),
252 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
253 }
William A. Kennington III151122a2018-05-15 12:00:32 -0700254 }
255 catch (const sdbusplus::exception::SdBusError& e)
256 {
Matt Spinler91122922018-09-24 11:31:44 -0500257 // Just means no log entries at the moment
William A. Kennington III151122a2018-05-15 12:00:32 -0700258 }
Matt Spinler91122922018-09-24 11:31:44 -0500259}
260
261void Add::processExistingCallouts(sdbusplus::bus::bus& bus)
262{
263 MapperResponseType mapperResponse;
264
265 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500266 if (mapperResponse.empty())
267 {
Dhruvaraj Subhashchandranfc30e0c2017-09-19 03:59:08 -0500268 //No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500269 return;
270 }
271
272 for (const auto& elem : mapperResponse)
273 {
274 auto method = bus.new_method_call(elem.second.begin()->first.c_str(),
275 elem.first.c_str(),
276 "org.freedesktop.DBus.Properties",
277 "Get");
278 method.append("org.openbmc.Associations");
279 method.append("associations");
280 auto reply = bus.call(method);
281 if (reply.is_method_error())
282 {
283 //do not stop, continue with next elog
284 log<level::ERR>("Error in getting associations");
285 continue;
286 }
287
288 sdbusplus::message::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700289 try
290 {
291 reply.read(assoc);
292 }
293 catch (const sdbusplus::exception::SdBusError& e)
294 {
295 log<level::ERR>("Failed to parse existing callouts associations message",
296 entry("ERROR=%s", e.what()),
297 entry("REPLY_SIG=%s", reply.get_signature()));
298 continue;
299 }
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500300 auto& assocs = assoc.get<AssociationList>();
301 if (assocs.empty())
302 {
303 //no associations, skip
304 continue;
305 }
306
307 for (const auto& item : assocs)
308 {
309 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
310 {
311 removeWatches.emplace_back(
312 std::make_unique<Remove>(bus, std::get<2>(item)));
313 action(bus, std::get<2>(item), true);
314 }
315 }
316 }
317}
318
Patrick Williams3eedbe42017-05-31 17:27:05 -0500319void Remove::removed(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500320{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500321 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500322
Patrick Williams3eedbe42017-05-31 17:27:05 -0500323 action(bus, inventoryPath, false);
324 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500325}
326
327}//namespace monitor
328}//namespace fault
329}//namespace fru
330}//namespace led
331}//namespace phosphor