blob: e1941cf0a1bb520c2352381d7a5b0edb98ea23ec [file] [log] [blame]
Patrick Venture91ac8d32018-11-01 17:03:22 -07001#include "fru-fault-monitor.hpp"
2
Patrick Williams9bd334f2022-03-16 11:28:26 -05003#include <phosphor-logging/elog-errors.hpp>
Patrick Venture91ac8d32018-11-01 17:03:22 -07004#include <phosphor-logging/elog.hpp>
George Liue9fb5c62021-07-01 14:05:32 +08005#include <phosphor-logging/lg2.hpp>
Patrick Venture91ac8d32018-11-01 17:03:22 -07006#include <sdbusplus/exception.hpp>
Patrick Williams9bd334f2022-03-16 11:28:26 -05007#include <xyz/openbmc_project/Common/error.hpp>
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -05008
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -05009namespace phosphor
10{
11namespace led
12{
13namespace fru
14{
15namespace fault
16{
17namespace monitor
18{
19
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050020using namespace phosphor::logging;
21
Patrick Venture91ac8d32018-11-01 17:03:22 -070022constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
23constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
24constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
25constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager";
26constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/";
27constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
28constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry";
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050029
Patrick Venture91ac8d32018-11-01 17:03:22 -070030using AssociationList =
31 std::vector<std::tuple<std::string, std::string, std::string>>;
Patrick Williamsa41d2822020-05-13 17:57:23 -050032using Attributes = std::variant<bool, AssociationList>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050033using PropertyName = std::string;
Patrick Williamsf2044032022-03-17 05:12:30 -050034using PropertyMap = std::unordered_map<PropertyName, Attributes>;
Matt Spinlerb2f253b2018-06-13 09:54:13 -050035using InterfaceName = std::string;
Patrick Williamsf2044032022-03-17 05:12:30 -050036using InterfaceMap = std::unordered_map<InterfaceName, PropertyMap>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050037
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050038using Service = std::string;
39using Path = std::string;
40using Interface = std::string;
41using Interfaces = std::vector<Interface>;
Patrick Williamsf2044032022-03-17 05:12:30 -050042using MapperResponseType =
43 std::unordered_map<Path, std::unordered_map<Service, Interfaces>>;
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050044
Patrick Williams9bd334f2022-03-16 11:28:26 -050045using ResourceNotFoundErr =
46 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
47using InvalidArgumentErr =
48 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050049
Patrick Venture91ac8d32018-11-01 17:03:22 -070050std::string getService(sdbusplus::bus::bus& bus, const std::string& path)
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050051{
Patrick Venture91ac8d32018-11-01 17:03:22 -070052 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050053 MAPPER_IFACE, "GetObject");
54 mapper.append(path.c_str(), std::vector<std::string>({OBJMGR_IFACE}));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050055
Patrick Williamsf2044032022-03-17 05:12:30 -050056 std::unordered_map<std::string, std::vector<std::string>> mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -070057 try
58 {
George Liud78de142021-08-23 16:16:32 +080059 auto mapperResponseMsg = bus.call(mapper);
William A. Kennington III151122a2018-05-15 12:00:32 -070060 mapperResponseMsg.read(mapperResponse);
61 }
Patrick Williams7152edc2021-09-02 09:41:54 -050062 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -070063 {
George Liue9fb5c62021-07-01 14:05:32 +080064 lg2::error(
65 "Failed to parse getService mapper response, ERROR = {ERROR}",
66 "ERROR", e);
Patrick Williams9bd334f2022-03-16 11:28:26 -050067 using namespace xyz::openbmc_project::Common;
68 elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
William A. Kennington III151122a2018-05-15 12:00:32 -070069 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050070 if (mapperResponse.empty())
71 {
Patrick Williams9bd334f2022-03-16 11:28:26 -050072 using namespace xyz::openbmc_project::Common;
73 elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
George Liuc5e0f312021-12-27 15:54:31 +080074 return {};
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050075 }
76
77 return mapperResponse.cbegin()->first;
78}
79
Patrick Venture91ac8d32018-11-01 17:03:22 -070080void action(sdbusplus::bus::bus& bus, const std::string& path, bool assert)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050081{
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050082 std::string service;
83 try
84 {
Matt Spinlere77b8342018-09-12 10:41:53 -050085 std::string groups{LED_GROUPS};
86 groups.pop_back();
87 service = getService(bus, groups);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050088 }
Patrick Williams9bd334f2022-03-16 11:28:26 -050089 catch (const ResourceNotFoundErr& e)
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050090 {
Patrick Williams9bd334f2022-03-16 11:28:26 -050091 commit<ResourceNotFoundErr>();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050092 return;
93 }
94
95 auto pos = path.rfind("/");
96 if (pos == std::string::npos)
97 {
Patrick Williams9bd334f2022-03-16 11:28:26 -050098 using namespace xyz::openbmc_project::Common;
99 report<InvalidArgumentErr>(
100 InvalidArgument::ARGUMENT_NAME("path"),
101 InvalidArgument::ARGUMENT_VALUE(path.c_str()));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500102 return;
103 }
104 auto unit = path.substr(pos + 1);
105
Patrick Venture91ac8d32018-11-01 17:03:22 -0700106 std::string ledPath = LED_GROUPS + unit + '_' + LED_FAULT;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500107
Patrick Venture91ac8d32018-11-01 17:03:22 -0700108 auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
109 "org.freedesktop.DBus.Properties", "Set");
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500110 method.append("xyz.openbmc_project.Led.Group");
111 method.append("Asserted");
112
Patrick Williamsa41d2822020-05-13 17:57:23 -0500113 method.append(std::variant<bool>(assert));
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500114
115 try
116 {
117 bus.call_noreply(method);
118 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500119 catch (const sdbusplus::exception::exception& e)
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500120 {
121 // Log an info message, system may not have all the LED Groups defined
George Liue9fb5c62021-07-01 14:05:32 +0800122 lg2::info("Failed to Assert LED Group, ERROR = {ERROR}", "ERROR", e);
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500123 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500124
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500125 return;
126}
127
Patrick Williams3eedbe42017-05-31 17:27:05 -0500128void Add::created(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500129{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500130 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500131
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500132 sdbusplus::message::object_path objectPath;
133 InterfaceMap interfaces;
William A. Kennington III151122a2018-05-15 12:00:32 -0700134 try
135 {
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500136 msg.read(objectPath, interfaces);
William A. Kennington III151122a2018-05-15 12:00:32 -0700137 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500138 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700139 {
George Liue9fb5c62021-07-01 14:05:32 +0800140 lg2::error("Failed to parse created message, ERROR = {ERROR}", "ERROR",
141 e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700142 return;
143 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500144
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500145 std::size_t found = objectPath.str.find(ELOG_ENTRY);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500146 if (found == std::string::npos)
147 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700148 // Not a new error entry skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500149 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500150 }
Andrew Geisslera6e48922019-11-06 08:43:54 -0600151 auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500152 if (iter == interfaces.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500153 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500154 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500155 }
156
Patrick Venture91ac8d32018-11-01 17:03:22 -0700157 // Nothing else shows when a specific error log
158 // has been created. Do it here.
George Liue9fb5c62021-07-01 14:05:32 +0800159 // TODO:(phosphor-logging#25): support sdbusplus::message::object_path
160 // directly.
161 lg2::info("{PATH} created", "PATH", objectPath.str);
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500162
Andrew Geisslera6e48922019-11-06 08:43:54 -0600163 auto attr = iter->second.find("Associations");
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500164 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500165 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500166 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500167 }
168
Patrick Williams5ebebef2020-05-13 11:47:27 -0500169 auto& assocs = std::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500170 if (assocs.empty())
171 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700172 // No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500173 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500174 }
175
176 for (const auto& item : assocs)
177 {
178 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
179 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500180 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500181 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500182 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500183 }
184 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500185
Patrick Williams3eedbe42017-05-31 17:27:05 -0500186 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500187}
188
Matt Spinler91122922018-09-24 11:31:44 -0500189void getLoggingSubTree(sdbusplus::bus::bus& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500190{
191 auto depth = 0;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700192 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
193 MAPPER_IFACE, "GetSubTree");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500194 mapperCall.append("/");
195 mapperCall.append(depth);
196 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
197
William A. Kennington III151122a2018-05-15 12:00:32 -0700198 try
199 {
Matt Spinler91122922018-09-24 11:31:44 -0500200 auto mapperResponseMsg = bus.call(mapperCall);
George Liud78de142021-08-23 16:16:32 +0800201 mapperResponseMsg.read(subtree);
William A. Kennington III151122a2018-05-15 12:00:32 -0700202 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500203 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700204 {
George Liue9fb5c62021-07-01 14:05:32 +0800205 lg2::error(
206 "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
207 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700208 }
Matt Spinler91122922018-09-24 11:31:44 -0500209}
210
211void Add::processExistingCallouts(sdbusplus::bus::bus& bus)
212{
Patrick Venture91ac8d32018-11-01 17:03:22 -0700213 MapperResponseType mapperResponse;
Matt Spinler91122922018-09-24 11:31:44 -0500214
215 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500216 if (mapperResponse.empty())
217 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700218 // No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500219 return;
220 }
221
222 for (const auto& elem : mapperResponse)
223 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700224 auto method = bus.new_method_call(
225 elem.second.begin()->first.c_str(), elem.first.c_str(),
226 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslera6e48922019-11-06 08:43:54 -0600227 method.append("xyz.openbmc_project.Association.Definitions");
228 method.append("Associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500229 auto reply = bus.call(method);
230 if (reply.is_method_error())
231 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700232 // do not stop, continue with next elog
George Liue9fb5c62021-07-01 14:05:32 +0800233 lg2::error("Error in getting associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500234 continue;
235 }
236
Patrick Williamsa41d2822020-05-13 17:57:23 -0500237 std::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700238 try
239 {
240 reply.read(assoc);
241 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500242 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700243 {
George Liue9fb5c62021-07-01 14:05:32 +0800244 lg2::error(
245 "Failed to parse existing callouts associations message, ERROR = {ERROR}",
246 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700247 continue;
248 }
Patrick Williams5ebebef2020-05-13 11:47:27 -0500249 auto& assocs = std::get<AssociationList>(assoc);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500250 if (assocs.empty())
251 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700252 // no associations, skip
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500253 continue;
254 }
255
256 for (const auto& item : assocs)
257 {
258 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
259 {
260 removeWatches.emplace_back(
261 std::make_unique<Remove>(bus, std::get<2>(item)));
262 action(bus, std::get<2>(item), true);
263 }
264 }
265 }
266}
267
Patrick Williams3eedbe42017-05-31 17:27:05 -0500268void Remove::removed(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500269{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500270 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500271
Patrick Williams3eedbe42017-05-31 17:27:05 -0500272 action(bus, inventoryPath, false);
273 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500274}
275
Patrick Venture91ac8d32018-11-01 17:03:22 -0700276} // namespace monitor
277} // namespace fault
278} // namespace fru
279} // namespace led
280} // namespace phosphor