blob: dca07a198ddf2b59c035227384a5406528e23725 [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 Williams3e073ba2022-07-22 19:26:52 -050050std::string getService(sdbusplus::bus_t& 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 Williams3e073ba2022-07-22 19:26:52 -050062 catch (const sdbusplus::exception_t& 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 Williams3e073ba2022-07-22 19:26:52 -050080void action(sdbusplus::bus_t& 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 Williams3e073ba2022-07-22 19:26:52 -0500119 catch (const sdbusplus::exception_t& 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 Williams3e073ba2022-07-22 19:26:52 -0500128void Add::created(sdbusplus::message_t& 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 Williams3e073ba2022-07-22 19:26:52 -0500138 catch (const sdbusplus::exception_t& 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 Liub4c82cf2023-01-04 10:23:36 +0800159 lg2::info("{PATH} created", "PATH", objectPath);
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500160
Andrew Geisslera6e48922019-11-06 08:43:54 -0600161 auto attr = iter->second.find("Associations");
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500162 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500163 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500164 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500165 }
166
Patrick Williams5ebebef2020-05-13 11:47:27 -0500167 auto& assocs = std::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500168 if (assocs.empty())
169 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700170 // No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500171 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500172 }
173
174 for (const auto& item : assocs)
175 {
176 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
177 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500178 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500179 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500180 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500181 }
182 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500183
Patrick Williams3eedbe42017-05-31 17:27:05 -0500184 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500185}
186
Patrick Williams3e073ba2022-07-22 19:26:52 -0500187void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500188{
189 auto depth = 0;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700190 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
191 MAPPER_IFACE, "GetSubTree");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500192 mapperCall.append("/");
193 mapperCall.append(depth);
194 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
195
William A. Kennington III151122a2018-05-15 12:00:32 -0700196 try
197 {
Matt Spinler91122922018-09-24 11:31:44 -0500198 auto mapperResponseMsg = bus.call(mapperCall);
George Liud78de142021-08-23 16:16:32 +0800199 mapperResponseMsg.read(subtree);
William A. Kennington III151122a2018-05-15 12:00:32 -0700200 }
Patrick Williams3e073ba2022-07-22 19:26:52 -0500201 catch (const sdbusplus::exception_t& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700202 {
George Liue9fb5c62021-07-01 14:05:32 +0800203 lg2::error(
204 "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
205 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700206 }
Matt Spinler91122922018-09-24 11:31:44 -0500207}
208
Patrick Williams3e073ba2022-07-22 19:26:52 -0500209void Add::processExistingCallouts(sdbusplus::bus_t& bus)
Matt Spinler91122922018-09-24 11:31:44 -0500210{
Patrick Venture91ac8d32018-11-01 17:03:22 -0700211 MapperResponseType mapperResponse;
Matt Spinler91122922018-09-24 11:31:44 -0500212
213 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500214 if (mapperResponse.empty())
215 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700216 // No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500217 return;
218 }
219
220 for (const auto& elem : mapperResponse)
221 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700222 auto method = bus.new_method_call(
223 elem.second.begin()->first.c_str(), elem.first.c_str(),
224 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslera6e48922019-11-06 08:43:54 -0600225 method.append("xyz.openbmc_project.Association.Definitions");
226 method.append("Associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500227 auto reply = bus.call(method);
228 if (reply.is_method_error())
229 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700230 // do not stop, continue with next elog
George Liue9fb5c62021-07-01 14:05:32 +0800231 lg2::error("Error in getting associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500232 continue;
233 }
234
Patrick Williamsa41d2822020-05-13 17:57:23 -0500235 std::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700236 try
237 {
238 reply.read(assoc);
239 }
Patrick Williams3e073ba2022-07-22 19:26:52 -0500240 catch (const sdbusplus::exception_t& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700241 {
George Liue9fb5c62021-07-01 14:05:32 +0800242 lg2::error(
243 "Failed to parse existing callouts associations message, ERROR = {ERROR}",
244 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700245 continue;
246 }
Patrick Williams5ebebef2020-05-13 11:47:27 -0500247 auto& assocs = std::get<AssociationList>(assoc);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500248 if (assocs.empty())
249 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700250 // no associations, skip
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500251 continue;
252 }
253
254 for (const auto& item : assocs)
255 {
256 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
257 {
258 removeWatches.emplace_back(
259 std::make_unique<Remove>(bus, std::get<2>(item)));
260 action(bus, std::get<2>(item), true);
261 }
262 }
263 }
264}
265
Patrick Williams3e073ba2022-07-22 19:26:52 -0500266void Remove::removed(sdbusplus::message_t& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500267{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500268 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500269
Patrick Williams3eedbe42017-05-31 17:27:05 -0500270 action(bus, inventoryPath, false);
271 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500272}
273
Patrick Venture91ac8d32018-11-01 17:03:22 -0700274} // namespace monitor
275} // namespace fault
276} // namespace fru
277} // namespace led
278} // namespace phosphor