blob: 363cabca8f0ed317242a5dfc1fc439bccbec9114 [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 Subhashchandran891c4762017-07-31 14:26:37 -05007#include <phosphor-logging/elog-errors.hpp>
8#include "xyz/openbmc_project/Common/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
23constexpr 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";
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050029constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry";
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050030
31using AssociationList = std::vector<std::tuple<
32 std::string, std::string, std::string>>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050033using Attributes = sdbusplus::message::variant<bool,AssociationList>;
34using AttributeName = std::string;
35using AttributeMap = std::map<AttributeName, Attributes>;
36using PropertyName = std::string;
37using PropertyMap = std::map<PropertyName, AttributeMap>;
38using LogEntryMsg = std::pair<sdbusplus::message::object_path, PropertyMap>;
39
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050040using Service = std::string;
41using Path = std::string;
42using Interface = std::string;
43using Interfaces = std::vector<Interface>;
44using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
45
46using InternalFailure =
47 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
48
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050049using MethodErr =
50 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::MethodError;
51using ObjectNotFoundErr =
52 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::ObjectNotFoundError;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050053using InventoryPathErr =
54 sdbusplus::xyz::openbmc_project::
55 Led::Fru::Monitor::Error::InventoryPathError;
56
57std::string getService(sdbusplus::bus::bus& bus,
58 const std::string& path)
59{
60 auto mapper = bus.new_method_call(MAPPER_BUSNAME,
61 MAPPER_OBJ_PATH,
62 MAPPER_IFACE, "GetObject");
63 mapper.append(path.c_str(), std::vector<std::string>({OBJMGR_IFACE}));
64 auto mapperResponseMsg = bus.call(mapper);
65 if (mapperResponseMsg.is_method_error())
66 {
67 using namespace xyz::openbmc_project::Led::Mapper;
68 elog<MethodErr>(
69 MethodError::METHOD_NAME("GetObject"),
70 MethodError::PATH(path.c_str()),
71 MethodError::INTERFACE(
72 OBJMGR_IFACE));
73 }
74
75 std::map<std::string, std::vector<std::string>> mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -070076 try
77 {
78 mapperResponseMsg.read(mapperResponse);
79 }
80 catch (const sdbusplus::exception::SdBusError& e)
81 {
82 log<level::ERR>("Failed to parse getService mapper response",
83 entry("ERROR=%s", e.what()),
84 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
85 using namespace xyz::openbmc_project::Led::Mapper;
86 elog<ObjectNotFoundErr>(
87 ObjectNotFoundError::METHOD_NAME("GetObject"),
88 ObjectNotFoundError::PATH(path.c_str()),
89 ObjectNotFoundError::INTERFACE(
90 OBJMGR_IFACE));
91 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050092 if (mapperResponse.empty())
93 {
94 using namespace xyz::openbmc_project::Led::Mapper;
95 elog<ObjectNotFoundErr>(
96 ObjectNotFoundError::METHOD_NAME("GetObject"),
97 ObjectNotFoundError::PATH(path.c_str()),
98 ObjectNotFoundError::INTERFACE(
99 OBJMGR_IFACE));
100 }
101
102 return mapperResponse.cbegin()->first;
103}
104
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500105void action(sdbusplus::bus::bus& bus,
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500106 const std::string& path,
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500107 bool assert)
108{
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500109 std::string service;
110 try
111 {
112 service = getService(bus, LED_GROUPS);
113 }
114 catch (MethodErr& e)
115 {
116 commit<MethodErr>();
117 return;
118 }
119 catch (ObjectNotFoundErr& e)
120 {
121 commit<ObjectNotFoundErr>();
122 return;
123 }
124
125 auto pos = path.rfind("/");
126 if (pos == std::string::npos)
127 {
128 using namespace xyz::openbmc_project::Led::Fru::Monitor;
129 report<InventoryPathErr>(
130 InventoryPathError::PATH(
131 path.c_str()));
132 return;
133 }
134 auto unit = path.substr(pos + 1);
135
136 std::string ledPath = LED_GROUPS +
137 unit + '_' + LED_FAULT;
138
139 auto method = bus.new_method_call(service.c_str(),
140 ledPath.c_str(),
141 "org.freedesktop.DBus.Properties",
142 "Set");
143 method.append("xyz.openbmc_project.Led.Group");
144 method.append("Asserted");
145
146 method.append(sdbusplus::message::variant<bool>(assert));
147 bus.call_noreply(method);
148
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500149 return;
150}
151
Patrick Williams3eedbe42017-05-31 17:27:05 -0500152void Add::created(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500153{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500154 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500155
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500156 LogEntryMsg logEntry;
William A. Kennington III151122a2018-05-15 12:00:32 -0700157 try
158 {
159 msg.read(logEntry);
160 }
161 catch (const sdbusplus::exception::SdBusError& e)
162 {
163 log<level::ERR>("Failed to parse created message",
164 entry("ERROR=%s", e.what()),
165 entry("REPLY_SIG=%s", msg.get_signature()));
166 return;
167 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500168 std::string objectPath(std::move(logEntry.first));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500169
170 std::size_t found = objectPath.find(ELOG_ENTRY);
171 if (found == std::string::npos)
172 {
173 //Not a new error entry skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500174 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500175 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500176 auto iter = logEntry.second.find("org.openbmc.Associations");
177 if (iter == logEntry.second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500178 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500179 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500180 }
181
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500182 //Nothing else shows when a specific error log
183 //has been created. Do it here.
184 std::string message{objectPath + " created"};
185 log<level::INFO>(message.c_str());
186
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500187 auto attr = iter->second.find("associations");
188 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500189 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500190 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500191 }
192
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500193 auto& assocs =
194 sdbusplus::message::variant_ns::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500195 if (assocs.empty())
196 {
197 //No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500198 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500199 }
200
201 for (const auto& item : assocs)
202 {
203 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
204 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500205 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500206 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500207 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500208 }
209 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500210
Patrick Williams3eedbe42017-05-31 17:27:05 -0500211 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500212}
213
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500214void Add::processExistingCallouts(sdbusplus::bus::bus& bus)
215{
216 auto depth = 0;
217 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME,
218 MAPPER_OBJ_PATH,
219 MAPPER_IFACE,
220 "GetSubTree");
221 mapperCall.append("/");
222 mapperCall.append(depth);
223 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
224
225 auto mapperResponseMsg = bus.call(mapperCall);
226 if (mapperResponseMsg.is_method_error())
227 {
228 using namespace xyz::openbmc_project::Led::Mapper;
229 report<MethodErr>(
230 MethodError::METHOD_NAME("GetSubTree"),
231 MethodError::PATH(MAPPER_OBJ_PATH),
232 MethodError::INTERFACE(
233 OBJMGR_IFACE));
234 return;
235 }
236
237 MapperResponseType mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -0700238 try
239 {
240 mapperResponseMsg.read(mapperResponse);
241 }
242 catch (const sdbusplus::exception::SdBusError& e)
243 {
244 log<level::ERR>("Failed to parse existing callouts subtree message",
245 entry("ERROR=%s", e.what()),
246 entry("REPLY_SIG=%s", mapperResponseMsg.get_signature()));
247 return;
248 }
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500249 if (mapperResponse.empty())
250 {
Dhruvaraj Subhashchandranfc30e0c2017-09-19 03:59:08 -0500251 //No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500252 return;
253 }
254
255 for (const auto& elem : mapperResponse)
256 {
257 auto method = bus.new_method_call(elem.second.begin()->first.c_str(),
258 elem.first.c_str(),
259 "org.freedesktop.DBus.Properties",
260 "Get");
261 method.append("org.openbmc.Associations");
262 method.append("associations");
263 auto reply = bus.call(method);
264 if (reply.is_method_error())
265 {
266 //do not stop, continue with next elog
267 log<level::ERR>("Error in getting associations");
268 continue;
269 }
270
271 sdbusplus::message::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 {
278 log<level::ERR>("Failed to parse existing callouts associations message",
279 entry("ERROR=%s", e.what()),
280 entry("REPLY_SIG=%s", reply.get_signature()));
281 continue;
282 }
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500283 auto& assocs = assoc.get<AssociationList>();
284 if (assocs.empty())
285 {
286 //no associations, skip
287 continue;
288 }
289
290 for (const auto& item : assocs)
291 {
292 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
293 {
294 removeWatches.emplace_back(
295 std::make_unique<Remove>(bus, std::get<2>(item)));
296 action(bus, std::get<2>(item), true);
297 }
298 }
299 }
300}
301
Patrick Williams3eedbe42017-05-31 17:27:05 -0500302void Remove::removed(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500303{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500304 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500305
Patrick Williams3eedbe42017-05-31 17:27:05 -0500306 action(bus, inventoryPath, false);
307 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500308}
309
310}//namespace monitor
311}//namespace fault
312}//namespace fru
313}//namespace led
314}//namespace phosphor