blob: 57c7b78a59208bb490810415a6f7fea809b21f44 [file] [log] [blame]
Patrick Venture91ac8d32018-11-01 17:03:22 -07001#include "fru-fault-monitor.hpp"
2
3#include "elog-errors.hpp"
Patrick Venture91ac8d32018-11-01 17:03:22 -07004
5#include <phosphor-logging/elog.hpp>
George Liue9fb5c62021-07-01 14:05:32 +08006#include <phosphor-logging/lg2.hpp>
Patrick Venture91ac8d32018-11-01 17:03:22 -07007#include <sdbusplus/exception.hpp>
George Liu4b062012020-10-13 15:26:58 +08008#include <xyz/openbmc_project/Led/Fru/Monitor/error.hpp>
9#include <xyz/openbmc_project/Led/Mapper/error.hpp>
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050010
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050011namespace phosphor
12{
13namespace led
14{
15namespace fru
16{
17namespace fault
18{
19namespace monitor
20{
21
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050022using namespace phosphor::logging;
23
Patrick Venture91ac8d32018-11-01 17:03:22 -070024constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
25constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
26constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
27constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager";
28constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/";
29constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
30constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry";
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050031
Patrick Venture91ac8d32018-11-01 17:03:22 -070032using AssociationList =
33 std::vector<std::tuple<std::string, std::string, std::string>>;
Patrick Williamsa41d2822020-05-13 17:57:23 -050034using Attributes = std::variant<bool, AssociationList>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050035using PropertyName = std::string;
Matt Spinlerb2f253b2018-06-13 09:54:13 -050036using PropertyMap = std::map<PropertyName, Attributes>;
37using InterfaceName = std::string;
38using InterfaceMap = std::map<InterfaceName, PropertyMap>;
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -050039
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
Patrick Venture91ac8d32018-11-01 17:03:22 -070046using MethodErr =
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050047 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::MethodError;
48using ObjectNotFoundErr =
49 sdbusplus::xyz::openbmc_project::Led::Mapper::Error::ObjectNotFoundError;
Patrick Venture91ac8d32018-11-01 17:03:22 -070050using InventoryPathErr = sdbusplus::xyz::openbmc_project::Led::Fru::Monitor::
51 Error::InventoryPathError;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050052
Patrick Venture91ac8d32018-11-01 17:03:22 -070053std::string getService(sdbusplus::bus::bus& bus, const std::string& path)
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050054{
Patrick Venture91ac8d32018-11-01 17:03:22 -070055 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050056 MAPPER_IFACE, "GetObject");
57 mapper.append(path.c_str(), std::vector<std::string>({OBJMGR_IFACE}));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050058
59 std::map<std::string, std::vector<std::string>> mapperResponse;
William A. Kennington III151122a2018-05-15 12:00:32 -070060 try
61 {
George Liud78de142021-08-23 16:16:32 +080062 auto mapperResponseMsg = bus.call(mapper);
William A. Kennington III151122a2018-05-15 12:00:32 -070063 mapperResponseMsg.read(mapperResponse);
64 }
Patrick Williams7152edc2021-09-02 09:41:54 -050065 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -070066 {
George Liue9fb5c62021-07-01 14:05:32 +080067 lg2::error(
68 "Failed to parse getService mapper response, ERROR = {ERROR}",
69 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -070070 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -070071 elog<ObjectNotFoundErr>(ObjectNotFoundError::METHOD_NAME("GetObject"),
72 ObjectNotFoundError::PATH(path.c_str()),
73 ObjectNotFoundError::INTERFACE(OBJMGR_IFACE));
William A. Kennington III151122a2018-05-15 12:00:32 -070074 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050075 if (mapperResponse.empty())
76 {
77 using namespace xyz::openbmc_project::Led::Mapper;
Patrick Venture91ac8d32018-11-01 17:03:22 -070078 elog<ObjectNotFoundErr>(ObjectNotFoundError::METHOD_NAME("GetObject"),
79 ObjectNotFoundError::PATH(path.c_str()),
80 ObjectNotFoundError::INTERFACE(OBJMGR_IFACE));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050081 }
82
83 return mapperResponse.cbegin()->first;
84}
85
Patrick Venture91ac8d32018-11-01 17:03:22 -070086void action(sdbusplus::bus::bus& bus, const std::string& path, bool assert)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -050087{
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050088 std::string service;
89 try
90 {
Matt Spinlere77b8342018-09-12 10:41:53 -050091 std::string groups{LED_GROUPS};
92 groups.pop_back();
93 service = getService(bus, groups);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -050094 }
95 catch (MethodErr& e)
96 {
97 commit<MethodErr>();
98 return;
99 }
100 catch (ObjectNotFoundErr& e)
101 {
102 commit<ObjectNotFoundErr>();
103 return;
104 }
105
106 auto pos = path.rfind("/");
107 if (pos == std::string::npos)
108 {
109 using namespace xyz::openbmc_project::Led::Fru::Monitor;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700110 report<InventoryPathErr>(InventoryPathError::PATH(path.c_str()));
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500111 return;
112 }
113 auto unit = path.substr(pos + 1);
114
Patrick Venture91ac8d32018-11-01 17:03:22 -0700115 std::string ledPath = LED_GROUPS + unit + '_' + LED_FAULT;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500116
Patrick Venture91ac8d32018-11-01 17:03:22 -0700117 auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
118 "org.freedesktop.DBus.Properties", "Set");
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500119 method.append("xyz.openbmc_project.Led.Group");
120 method.append("Asserted");
121
Patrick Williamsa41d2822020-05-13 17:57:23 -0500122 method.append(std::variant<bool>(assert));
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500123
124 try
125 {
126 bus.call_noreply(method);
127 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500128 catch (const sdbusplus::exception::exception& e)
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500129 {
130 // Log an info message, system may not have all the LED Groups defined
George Liue9fb5c62021-07-01 14:05:32 +0800131 lg2::info("Failed to Assert LED Group, ERROR = {ERROR}", "ERROR", e);
Adriana Kobylak08d613e2018-07-18 15:30:39 -0500132 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500133
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500134 return;
135}
136
Patrick Williams3eedbe42017-05-31 17:27:05 -0500137void Add::created(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500138{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500139 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500140
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500141 sdbusplus::message::object_path objectPath;
142 InterfaceMap interfaces;
William A. Kennington III151122a2018-05-15 12:00:32 -0700143 try
144 {
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500145 msg.read(objectPath, interfaces);
William A. Kennington III151122a2018-05-15 12:00:32 -0700146 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500147 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700148 {
George Liue9fb5c62021-07-01 14:05:32 +0800149 lg2::error("Failed to parse created message, ERROR = {ERROR}", "ERROR",
150 e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700151 return;
152 }
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500153
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500154 std::size_t found = objectPath.str.find(ELOG_ENTRY);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500155 if (found == std::string::npos)
156 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700157 // Not a new error entry skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500158 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500159 }
Andrew Geisslera6e48922019-11-06 08:43:54 -0600160 auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
Matt Spinlerb2f253b2018-06-13 09:54:13 -0500161 if (iter == interfaces.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 Venture91ac8d32018-11-01 17:03:22 -0700166 // Nothing else shows when a specific error log
167 // has been created. Do it here.
George Liue9fb5c62021-07-01 14:05:32 +0800168 // TODO:(phosphor-logging#25): support sdbusplus::message::object_path
169 // directly.
170 lg2::info("{PATH} created", "PATH", objectPath.str);
Matt Spinler3d2b0d62018-03-29 08:48:37 -0500171
Andrew Geisslera6e48922019-11-06 08:43:54 -0600172 auto attr = iter->second.find("Associations");
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500173 if (attr == iter->second.end())
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500174 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500175 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500176 }
177
Patrick Williams5ebebef2020-05-13 11:47:27 -0500178 auto& assocs = std::get<AssociationList>(attr->second);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500179 if (assocs.empty())
180 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700181 // No associations skip
Patrick Williams3eedbe42017-05-31 17:27:05 -0500182 return;
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500183 }
184
185 for (const auto& item : assocs)
186 {
187 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
188 {
Patrick Williams3eedbe42017-05-31 17:27:05 -0500189 removeWatches.emplace_back(
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500190 std::make_unique<Remove>(bus, std::get<2>(item)));
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500191 action(bus, std::get<2>(item), true);
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500192 }
193 }
Dhruvaraj Subhashchandranaebfde82017-07-11 01:36:33 -0500194
Patrick Williams3eedbe42017-05-31 17:27:05 -0500195 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500196}
197
Matt Spinler91122922018-09-24 11:31:44 -0500198void getLoggingSubTree(sdbusplus::bus::bus& bus, MapperResponseType& subtree)
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500199{
200 auto depth = 0;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700201 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
202 MAPPER_IFACE, "GetSubTree");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500203 mapperCall.append("/");
204 mapperCall.append(depth);
205 mapperCall.append(std::vector<Interface>({LOG_IFACE}));
206
William A. Kennington III151122a2018-05-15 12:00:32 -0700207 try
208 {
Matt Spinler91122922018-09-24 11:31:44 -0500209 auto mapperResponseMsg = bus.call(mapperCall);
George Liud78de142021-08-23 16:16:32 +0800210 mapperResponseMsg.read(subtree);
William A. Kennington III151122a2018-05-15 12:00:32 -0700211 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500212 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700213 {
George Liue9fb5c62021-07-01 14:05:32 +0800214 lg2::error(
215 "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
216 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700217 }
Matt Spinler91122922018-09-24 11:31:44 -0500218}
219
220void Add::processExistingCallouts(sdbusplus::bus::bus& bus)
221{
Patrick Venture91ac8d32018-11-01 17:03:22 -0700222 MapperResponseType mapperResponse;
Matt Spinler91122922018-09-24 11:31:44 -0500223
224 getLoggingSubTree(bus, mapperResponse);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500225 if (mapperResponse.empty())
226 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700227 // No errors to process.
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500228 return;
229 }
230
231 for (const auto& elem : mapperResponse)
232 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700233 auto method = bus.new_method_call(
234 elem.second.begin()->first.c_str(), elem.first.c_str(),
235 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslera6e48922019-11-06 08:43:54 -0600236 method.append("xyz.openbmc_project.Association.Definitions");
237 method.append("Associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500238 auto reply = bus.call(method);
239 if (reply.is_method_error())
240 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700241 // do not stop, continue with next elog
George Liue9fb5c62021-07-01 14:05:32 +0800242 lg2::error("Error in getting associations");
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500243 continue;
244 }
245
Patrick Williamsa41d2822020-05-13 17:57:23 -0500246 std::variant<AssociationList> assoc;
William A. Kennington III151122a2018-05-15 12:00:32 -0700247 try
248 {
249 reply.read(assoc);
250 }
Patrick Williams7152edc2021-09-02 09:41:54 -0500251 catch (const sdbusplus::exception::exception& e)
William A. Kennington III151122a2018-05-15 12:00:32 -0700252 {
George Liue9fb5c62021-07-01 14:05:32 +0800253 lg2::error(
254 "Failed to parse existing callouts associations message, ERROR = {ERROR}",
255 "ERROR", e);
William A. Kennington III151122a2018-05-15 12:00:32 -0700256 continue;
257 }
Patrick Williams5ebebef2020-05-13 11:47:27 -0500258 auto& assocs = std::get<AssociationList>(assoc);
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500259 if (assocs.empty())
260 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700261 // no associations, skip
Dhruvaraj Subhashchandran891c4762017-07-31 14:26:37 -0500262 continue;
263 }
264
265 for (const auto& item : assocs)
266 {
267 if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
268 {
269 removeWatches.emplace_back(
270 std::make_unique<Remove>(bus, std::get<2>(item)));
271 action(bus, std::get<2>(item), true);
272 }
273 }
274 }
275}
276
Patrick Williams3eedbe42017-05-31 17:27:05 -0500277void Remove::removed(sdbusplus::message::message& msg)
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500278{
Patrick Williams3eedbe42017-05-31 17:27:05 -0500279 auto bus = msg.get_bus();
Dhruvaraj Subhashchandran3c6f29a2017-04-20 09:47:28 -0500280
Patrick Williams3eedbe42017-05-31 17:27:05 -0500281 action(bus, inventoryPath, false);
282 return;
Dhruvaraj Subhashchandran59b86cd2017-04-13 00:19:44 -0500283}
284
Patrick Venture91ac8d32018-11-01 17:03:22 -0700285} // namespace monitor
286} // namespace fault
287} // namespace fru
288} // namespace led
289} // namespace phosphor