blob: e6b6a61eba371923e2bb44f2ab1692c58f2e5818 [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
George Liu1f0b7152023-07-18 09:24:34 +080022static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
23static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
24static constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
25static constexpr auto objMgrIntf = "org.freedesktop.DBus.ObjectManager";
26static constexpr auto ledGroups = "/xyz/openbmc_project/led/groups/";
27static constexpr auto logIntf = "xyz.openbmc_project.Logging.Entry";
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050028
Patrick Venture91ac8d32018-11-01 17:03:22 -070029using AssociationList =
30 std::vector<std::tuple<std::string, std::string, std::string>>;
Patrick Williamsa41d2822020-05-13 17:57:23 -050031using Attributes = std::variant<bool, AssociationList>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050032using PropertyName = std::string;
Patrick Williamsf2044032022-03-17 05:12:30 -050033using PropertyMap = std::unordered_map<PropertyName, Attributes>;
Matt Spinlerb2f253b2018-06-13 09:54:13 -050034using InterfaceName = std::string;
Patrick Williamsf2044032022-03-17 05:12:30 -050035using InterfaceMap = std::unordered_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>;
Patrick Williamsf2044032022-03-17 05:12:30 -050041using MapperResponseType =
42 std::unordered_map<Path, std::unordered_map<Service, Interfaces>>;
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -050043
Patrick Williams9bd334f2022-03-16 11:28:26 -050044using ResourceNotFoundErr =
45 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
46using InvalidArgumentErr =
47 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050048
Patrick Williams3e073ba2022-07-22 19:26:52 -050049std::string getService(sdbusplus::bus_t& bus, const std::string& path)
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050050{
George Liu1f0b7152023-07-18 09:24:34 +080051 auto mapper = bus.new_method_call(mapperBusName, mapperObjPath, mapperIntf,
52 "GetObject");
53 mapper.append(path.c_str(), std::vector<std::string>({objMgrIntf}));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050054
Patrick Williamsf2044032022-03-17 05:12:30 -050055 std::unordered_map<std::string, std::vector<std::string>> mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -070056 try
57 {
George Liud78de142021-08-23 16:16:32 +080058 auto mapperResponseMsg = bus.call(mapper);
William A. Kennington III151122a2018-05-15 12:00:32 -070059 mapperResponseMsg.read(mapperResponse);
60 }
Patrick Williams3e073ba2022-07-22 19:26:52 -050061 catch (const sdbusplus::exception_t& e)
William A. Kennington III151122a2018-05-15 12:00:32 -070062 {
George Liue9fb5c62021-07-01 14:05:32 +080063 lg2::error(
64 "Failed to parse getService mapper response, ERROR = {ERROR}",
65 "ERROR", e);
Patrick Williams9bd334f2022-03-16 11:28:26 -050066 using namespace xyz::openbmc_project::Common;
67 elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
William A. Kennington III151122a2018-05-15 12:00:32 -070068 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050069 if (mapperResponse.empty())
70 {
Patrick Williams9bd334f2022-03-16 11:28:26 -050071 using namespace xyz::openbmc_project::Common;
72 elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
George Liuc5e0f312021-12-27 15:54:31 +080073 return {};
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050074 }
75
76 return mapperResponse.cbegin()->first;
77}
78
Patrick Williams3e073ba2022-07-22 19:26:52 -050079void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050080{
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050081 std::string service;
82 try
83 {
George Liu1f0b7152023-07-18 09:24:34 +080084 std::string groups{ledGroups};
Matt Spinlere77b8342018-09-12 10:41:53 -050085 groups.pop_back();
86 service = getService(bus, groups);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050087 }
Patrick Williams9bd334f2022-03-16 11:28:26 -050088 catch (const ResourceNotFoundErr& e)
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050089 {
Patrick Williams9bd334f2022-03-16 11:28:26 -050090 commit<ResourceNotFoundErr>();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050091 return;
92 }
93
94 auto pos = path.rfind("/");
95 if (pos == std::string::npos)
96 {
Patrick Williams9bd334f2022-03-16 11:28:26 -050097 using namespace xyz::openbmc_project::Common;
98 report<InvalidArgumentErr>(
99 InvalidArgument::ARGUMENT_NAME("path"),
100 InvalidArgument::ARGUMENT_VALUE(path.c_str()));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500101 return;
102 }
103 auto unit = path.substr(pos + 1);
104
George Liu1f0b7152023-07-18 09:24:34 +0800105 std::string ledPath = ledGroups + unit + '_' + LED_FAULT;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500106
Patrick Venture91ac8d32018-11-01 17:03:22 -0700107 auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
108 "org.freedesktop.DBus.Properties", "Set");
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500109 method.append("xyz.openbmc_project.Led.Group");
110 method.append("Asserted");
111
Patrick Williamsa41d2822020-05-13 17:57:23 -0500112 method.append(std::variant<bool>(assert));
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500113
114 try
115 {
116 bus.call_noreply(method);
117 }
Patrick Williams3e073ba2022-07-22 19:26:52 -0500118 catch (const sdbusplus::exception_t& e)
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500119 {
120 // Log an info message, system may not have all the LED Groups defined
George Liue9fb5c62021-07-01 14:05:32 +0800121 lg2::info("Failed to Assert LED Group, ERROR = {ERROR}", "ERROR", e);
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500122 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500123
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500124 return;
125}
126
Patrick Williams3e073ba2022-07-22 19:26:52 -0500127void Add::created(sdbusplus::message_t& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500128{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500129 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500130
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500131 sdbusplus::message::object_path objectPath;
132 InterfaceMap interfaces;
William A. Kennington III151122a2018-05-15 12:00:32 -0700133 try
134 {
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500135 msg.read(objectPath, interfaces);
William A. Kennington III151122a2018-05-15 12:00:32 -0700136 }
Patrick Williams3e073ba2022-07-22 19:26:52 -0500137 catch (const sdbusplus::exception_t& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700138 {
George Liue9fb5c62021-07-01 14:05:32 +0800139 lg2::error("Failed to parse created message, ERROR = {ERROR}", "ERROR",
140 e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700141 return;
142 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500143
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500144 std::size_t found = objectPath.str.find(ELOG_ENTRY);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500145 if (found == std::string::npos)
146 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700147 // Not a new error entry skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500148 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500149 }
Andrew Geisslera6e48922019-11-06 08:43:54 -0600150 auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500151 if (iter == interfaces.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500152 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500153 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500154 }
155
Patrick Venture91ac8d32018-11-01 17:03:22 -0700156 // Nothing else shows when a specific error log
157 // has been created. Do it here.
George Liub4c82cf2023-01-04 10:23:36 +0800158 lg2::info("{PATH} created", "PATH", objectPath);
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500159
Andrew Geisslera6e48922019-11-06 08:43:54 -0600160 auto attr = iter->second.find("Associations");
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500161 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500162 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500163 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500164 }
165
Patrick Williams5ebebef2020-05-13 11:47:27 -0500166 auto& assocs = std::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500167 if (assocs.empty())
168 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700169 // No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500170 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500171 }
172
173 for (const auto& item : assocs)
174 {
175 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
176 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500177 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500178 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500179 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500180 }
181 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500182
Patrick Williams3eedbe42017-05-31 17:27:05 -0500183 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500184}
185
Patrick Williams3e073ba2022-07-22 19:26:52 -0500186void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500187{
188 auto depth = 0;
George Liu1f0b7152023-07-18 09:24:34 +0800189 auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath,
190 mapperIntf, "GetSubTree");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500191 mapperCall.append("/");
192 mapperCall.append(depth);
George Liu1f0b7152023-07-18 09:24:34 +0800193 mapperCall.append(std::vector<Interface>({logIntf}));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500194
William A. Kennington III151122a2018-05-15 12:00:32 -0700195 try
196 {
Matt Spinler91122922018-09-24 11:31:44 -0500197 auto mapperResponseMsg = bus.call(mapperCall);
George Liud78de142021-08-23 16:16:32 +0800198 mapperResponseMsg.read(subtree);
William A. Kennington III151122a2018-05-15 12:00:32 -0700199 }
Patrick Williams3e073ba2022-07-22 19:26:52 -0500200 catch (const sdbusplus::exception_t& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700201 {
George Liue9fb5c62021-07-01 14:05:32 +0800202 lg2::error(
203 "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
204 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700205 }
Matt Spinler91122922018-09-24 11:31:44 -0500206}
207
Patrick Williams3e073ba2022-07-22 19:26:52 -0500208void Add::processExistingCallouts(sdbusplus::bus_t& bus)
Matt Spinler91122922018-09-24 11:31:44 -0500209{
Patrick Venture91ac8d32018-11-01 17:03:22 -0700210 MapperResponseType mapperResponse;
Matt Spinler91122922018-09-24 11:31:44 -0500211
212 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500213 if (mapperResponse.empty())
214 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700215 // No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500216 return;
217 }
218
219 for (const auto& elem : mapperResponse)
220 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700221 auto method = bus.new_method_call(
222 elem.second.begin()->first.c_str(), elem.first.c_str(),
223 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslera6e48922019-11-06 08:43:54 -0600224 method.append("xyz.openbmc_project.Association.Definitions");
225 method.append("Associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500226 auto reply = bus.call(method);
227 if (reply.is_method_error())
228 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700229 // do not stop, continue with next elog
George Liue9fb5c62021-07-01 14:05:32 +0800230 lg2::error("Error in getting associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500231 continue;
232 }
233
Patrick Williamsa41d2822020-05-13 17:57:23 -0500234 std::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700235 try
236 {
237 reply.read(assoc);
238 }
Patrick Williams3e073ba2022-07-22 19:26:52 -0500239 catch (const sdbusplus::exception_t& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700240 {
George Liue9fb5c62021-07-01 14:05:32 +0800241 lg2::error(
242 "Failed to parse existing callouts associations message, ERROR = {ERROR}",
243 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700244 continue;
245 }
Patrick Williams5ebebef2020-05-13 11:47:27 -0500246 auto& assocs = std::get<AssociationList>(assoc);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500247 if (assocs.empty())
248 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700249 // no associations, skip
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500250 continue;
251 }
252
253 for (const auto& item : assocs)
254 {
255 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
256 {
257 removeWatches.emplace_back(
258 std::make_unique<Remove>(bus, std::get<2>(item)));
259 action(bus, std::get<2>(item), true);
260 }
261 }
262 }
263}
264
Patrick Williams3e073ba2022-07-22 19:26:52 -0500265void Remove::removed(sdbusplus::message_t& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500266{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500267 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500268
Patrick Williams3eedbe42017-05-31 17:27:05 -0500269 action(bus, inventoryPath, false);
270 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500271}
272
Patrick Venture91ac8d32018-11-01 17:03:22 -0700273} // namespace monitor
274} // namespace fault
275} // namespace fru
276} // namespace led
277} // namespace phosphor