191ac8d3aSPatrick Venture #include "fru-fault-monitor.hpp"
291ac8d3aSPatrick Venture
39bd334ffSPatrick Williams #include <phosphor-logging/elog-errors.hpp>
491ac8d3aSPatrick Venture #include <phosphor-logging/elog.hpp>
5e9fb5c6aSGeorge Liu #include <phosphor-logging/lg2.hpp>
691ac8d3aSPatrick Venture #include <sdbusplus/exception.hpp>
79bd334ffSPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
83c6f29a0SDhruvaraj Subhashchandran
959b86cd7SDhruvaraj Subhashchandran namespace phosphor
1059b86cd7SDhruvaraj Subhashchandran {
1159b86cd7SDhruvaraj Subhashchandran namespace led
1259b86cd7SDhruvaraj Subhashchandran {
1359b86cd7SDhruvaraj Subhashchandran namespace fru
1459b86cd7SDhruvaraj Subhashchandran {
1559b86cd7SDhruvaraj Subhashchandran namespace fault
1659b86cd7SDhruvaraj Subhashchandran {
1759b86cd7SDhruvaraj Subhashchandran namespace monitor
1859b86cd7SDhruvaraj Subhashchandran {
1959b86cd7SDhruvaraj Subhashchandran
203c6f29a0SDhruvaraj Subhashchandran using namespace phosphor::logging;
213c6f29a0SDhruvaraj Subhashchandran
22*1f0b715aSGeorge Liu static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
23*1f0b715aSGeorge Liu static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
24*1f0b715aSGeorge Liu static constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
25*1f0b715aSGeorge Liu static constexpr auto objMgrIntf = "org.freedesktop.DBus.ObjectManager";
26*1f0b715aSGeorge Liu static constexpr auto ledGroups = "/xyz/openbmc_project/led/groups/";
27*1f0b715aSGeorge Liu static constexpr auto logIntf = "xyz.openbmc_project.Logging.Entry";
283c6f29a0SDhruvaraj Subhashchandran
2991ac8d3aSPatrick Venture using AssociationList =
3091ac8d3aSPatrick Venture std::vector<std::tuple<std::string, std::string, std::string>>;
31a41d282aSPatrick Williams using Attributes = std::variant<bool, AssociationList>;
32aebfde81SDhruvaraj Subhashchandran using PropertyName = std::string;
33f2044037SPatrick Williams using PropertyMap = std::unordered_map<PropertyName, Attributes>;
34b2f253b7SMatt Spinler using InterfaceName = std::string;
35f2044037SPatrick Williams using InterfaceMap = std::unordered_map<InterfaceName, PropertyMap>;
36aebfde81SDhruvaraj Subhashchandran
37891c4769SDhruvaraj Subhashchandran using Service = std::string;
38891c4769SDhruvaraj Subhashchandran using Path = std::string;
39891c4769SDhruvaraj Subhashchandran using Interface = std::string;
40891c4769SDhruvaraj Subhashchandran using Interfaces = std::vector<Interface>;
41f2044037SPatrick Williams using MapperResponseType =
42f2044037SPatrick Williams std::unordered_map<Path, std::unordered_map<Service, Interfaces>>;
43891c4769SDhruvaraj Subhashchandran
449bd334ffSPatrick Williams using ResourceNotFoundErr =
459bd334ffSPatrick Williams sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
469bd334ffSPatrick Williams using InvalidArgumentErr =
479bd334ffSPatrick Williams sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
483c6f29a0SDhruvaraj Subhashchandran
getService(sdbusplus::bus_t & bus,const std::string & path)493e073ba6SPatrick Williams std::string getService(sdbusplus::bus_t& bus, const std::string& path)
503c6f29a0SDhruvaraj Subhashchandran {
51*1f0b715aSGeorge Liu auto mapper = bus.new_method_call(mapperBusName, mapperObjPath, mapperIntf,
52*1f0b715aSGeorge Liu "GetObject");
53*1f0b715aSGeorge Liu mapper.append(path.c_str(), std::vector<std::string>({objMgrIntf}));
543c6f29a0SDhruvaraj Subhashchandran
55f2044037SPatrick Williams std::unordered_map<std::string, std::vector<std::string>> mapperResponse;
56151122aaSWilliam A. Kennington III try
57151122aaSWilliam A. Kennington III {
58d78de14dSGeorge Liu auto mapperResponseMsg = bus.call(mapper);
593c6f29a0SDhruvaraj Subhashchandran mapperResponseMsg.read(mapperResponse);
60151122aaSWilliam A. Kennington III }
613e073ba6SPatrick Williams catch (const sdbusplus::exception_t& e)
62151122aaSWilliam A. Kennington III {
63e9fb5c6aSGeorge Liu lg2::error(
64e9fb5c6aSGeorge Liu "Failed to parse getService mapper response, ERROR = {ERROR}",
65e9fb5c6aSGeorge Liu "ERROR", e);
669bd334ffSPatrick Williams using namespace xyz::openbmc_project::Common;
679bd334ffSPatrick Williams elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
68151122aaSWilliam A. Kennington III }
693c6f29a0SDhruvaraj Subhashchandran if (mapperResponse.empty())
703c6f29a0SDhruvaraj Subhashchandran {
719bd334ffSPatrick Williams using namespace xyz::openbmc_project::Common;
729bd334ffSPatrick Williams elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
73c5e0f31cSGeorge Liu return {};
743c6f29a0SDhruvaraj Subhashchandran }
753c6f29a0SDhruvaraj Subhashchandran
763c6f29a0SDhruvaraj Subhashchandran return mapperResponse.cbegin()->first;
773c6f29a0SDhruvaraj Subhashchandran }
783c6f29a0SDhruvaraj Subhashchandran
action(sdbusplus::bus_t & bus,const std::string & path,bool assert)793e073ba6SPatrick Williams void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
8059b86cd7SDhruvaraj Subhashchandran {
813c6f29a0SDhruvaraj Subhashchandran std::string service;
823c6f29a0SDhruvaraj Subhashchandran try
833c6f29a0SDhruvaraj Subhashchandran {
84*1f0b715aSGeorge Liu std::string groups{ledGroups};
85e77b8345SMatt Spinler groups.pop_back();
86e77b8345SMatt Spinler service = getService(bus, groups);
873c6f29a0SDhruvaraj Subhashchandran }
889bd334ffSPatrick Williams catch (const ResourceNotFoundErr& e)
893c6f29a0SDhruvaraj Subhashchandran {
909bd334ffSPatrick Williams commit<ResourceNotFoundErr>();
913c6f29a0SDhruvaraj Subhashchandran return;
923c6f29a0SDhruvaraj Subhashchandran }
933c6f29a0SDhruvaraj Subhashchandran
943c6f29a0SDhruvaraj Subhashchandran auto pos = path.rfind("/");
953c6f29a0SDhruvaraj Subhashchandran if (pos == std::string::npos)
963c6f29a0SDhruvaraj Subhashchandran {
979bd334ffSPatrick Williams using namespace xyz::openbmc_project::Common;
989bd334ffSPatrick Williams report<InvalidArgumentErr>(
999bd334ffSPatrick Williams InvalidArgument::ARGUMENT_NAME("path"),
1009bd334ffSPatrick Williams InvalidArgument::ARGUMENT_VALUE(path.c_str()));
1013c6f29a0SDhruvaraj Subhashchandran return;
1023c6f29a0SDhruvaraj Subhashchandran }
1033c6f29a0SDhruvaraj Subhashchandran auto unit = path.substr(pos + 1);
1043c6f29a0SDhruvaraj Subhashchandran
105*1f0b715aSGeorge Liu std::string ledPath = ledGroups + unit + '_' + LED_FAULT;
1063c6f29a0SDhruvaraj Subhashchandran
10791ac8d3aSPatrick Venture auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
10891ac8d3aSPatrick Venture "org.freedesktop.DBus.Properties", "Set");
1093c6f29a0SDhruvaraj Subhashchandran method.append("xyz.openbmc_project.Led.Group");
1103c6f29a0SDhruvaraj Subhashchandran method.append("Asserted");
1113c6f29a0SDhruvaraj Subhashchandran
112a41d282aSPatrick Williams method.append(std::variant<bool>(assert));
11308d613e7SAdriana Kobylak
11408d613e7SAdriana Kobylak try
11508d613e7SAdriana Kobylak {
1163c6f29a0SDhruvaraj Subhashchandran bus.call_noreply(method);
11708d613e7SAdriana Kobylak }
1183e073ba6SPatrick Williams catch (const sdbusplus::exception_t& e)
11908d613e7SAdriana Kobylak {
12008d613e7SAdriana Kobylak // Log an info message, system may not have all the LED Groups defined
121e9fb5c6aSGeorge Liu lg2::info("Failed to Assert LED Group, ERROR = {ERROR}", "ERROR", e);
12208d613e7SAdriana Kobylak }
1233c6f29a0SDhruvaraj Subhashchandran
12459b86cd7SDhruvaraj Subhashchandran return;
12559b86cd7SDhruvaraj Subhashchandran }
12659b86cd7SDhruvaraj Subhashchandran
created(sdbusplus::message_t & msg)1273e073ba6SPatrick Williams void Add::created(sdbusplus::message_t& msg)
12859b86cd7SDhruvaraj Subhashchandran {
1293eedbe44SPatrick Williams auto bus = msg.get_bus();
1303c6f29a0SDhruvaraj Subhashchandran
131b2f253b7SMatt Spinler sdbusplus::message::object_path objectPath;
132b2f253b7SMatt Spinler InterfaceMap interfaces;
133151122aaSWilliam A. Kennington III try
134151122aaSWilliam A. Kennington III {
135b2f253b7SMatt Spinler msg.read(objectPath, interfaces);
136151122aaSWilliam A. Kennington III }
1373e073ba6SPatrick Williams catch (const sdbusplus::exception_t& e)
138151122aaSWilliam A. Kennington III {
139e9fb5c6aSGeorge Liu lg2::error("Failed to parse created message, ERROR = {ERROR}", "ERROR",
140e9fb5c6aSGeorge Liu e);
141151122aaSWilliam A. Kennington III return;
142151122aaSWilliam A. Kennington III }
1433c6f29a0SDhruvaraj Subhashchandran
144b2f253b7SMatt Spinler std::size_t found = objectPath.str.find(ELOG_ENTRY);
1453c6f29a0SDhruvaraj Subhashchandran if (found == std::string::npos)
1463c6f29a0SDhruvaraj Subhashchandran {
1473c6f29a0SDhruvaraj Subhashchandran // Not a new error entry skip
1483eedbe44SPatrick Williams return;
1493c6f29a0SDhruvaraj Subhashchandran }
150a6e48929SAndrew Geissler auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
151b2f253b7SMatt Spinler if (iter == interfaces.end())
1523c6f29a0SDhruvaraj Subhashchandran {
1533eedbe44SPatrick Williams return;
1543c6f29a0SDhruvaraj Subhashchandran }
1553c6f29a0SDhruvaraj Subhashchandran
1563d2b0d62SMatt Spinler // Nothing else shows when a specific error log
1573d2b0d62SMatt Spinler // has been created. Do it here.
158b4c82cf4SGeorge Liu lg2::info("{PATH} created", "PATH", objectPath);
1593d2b0d62SMatt Spinler
160a6e48929SAndrew Geissler auto attr = iter->second.find("Associations");
161aebfde81SDhruvaraj Subhashchandran if (attr == iter->second.end())
1623c6f29a0SDhruvaraj Subhashchandran {
1633eedbe44SPatrick Williams return;
1643c6f29a0SDhruvaraj Subhashchandran }
1653c6f29a0SDhruvaraj Subhashchandran
1665ebebeffSPatrick Williams auto& assocs = std::get<AssociationList>(attr->second);
1673c6f29a0SDhruvaraj Subhashchandran if (assocs.empty())
1683c6f29a0SDhruvaraj Subhashchandran {
1693c6f29a0SDhruvaraj Subhashchandran // No associations skip
1703eedbe44SPatrick Williams return;
1713c6f29a0SDhruvaraj Subhashchandran }
1723c6f29a0SDhruvaraj Subhashchandran
1733c6f29a0SDhruvaraj Subhashchandran for (const auto& item : assocs)
1743c6f29a0SDhruvaraj Subhashchandran {
1753c6f29a0SDhruvaraj Subhashchandran if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
1763c6f29a0SDhruvaraj Subhashchandran {
1773eedbe44SPatrick Williams removeWatches.emplace_back(
1783c6f29a0SDhruvaraj Subhashchandran std::make_unique<Remove>(bus, std::get<2>(item)));
179891c4769SDhruvaraj Subhashchandran action(bus, std::get<2>(item), true);
1803c6f29a0SDhruvaraj Subhashchandran }
1813c6f29a0SDhruvaraj Subhashchandran }
182aebfde81SDhruvaraj Subhashchandran
1833eedbe44SPatrick Williams return;
18459b86cd7SDhruvaraj Subhashchandran }
18559b86cd7SDhruvaraj Subhashchandran
getLoggingSubTree(sdbusplus::bus_t & bus,MapperResponseType & subtree)1863e073ba6SPatrick Williams void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
187891c4769SDhruvaraj Subhashchandran {
188891c4769SDhruvaraj Subhashchandran auto depth = 0;
189*1f0b715aSGeorge Liu auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath,
190*1f0b715aSGeorge Liu mapperIntf, "GetSubTree");
191891c4769SDhruvaraj Subhashchandran mapperCall.append("/");
192891c4769SDhruvaraj Subhashchandran mapperCall.append(depth);
193*1f0b715aSGeorge Liu mapperCall.append(std::vector<Interface>({logIntf}));
194891c4769SDhruvaraj Subhashchandran
19591122927SMatt Spinler try
19691122927SMatt Spinler {
197891c4769SDhruvaraj Subhashchandran auto mapperResponseMsg = bus.call(mapperCall);
19891122927SMatt Spinler mapperResponseMsg.read(subtree);
199151122aaSWilliam A. Kennington III }
2003e073ba6SPatrick Williams catch (const sdbusplus::exception_t& e)
201151122aaSWilliam A. Kennington III {
202e9fb5c6aSGeorge Liu lg2::error(
203e9fb5c6aSGeorge Liu "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
204e9fb5c6aSGeorge Liu "ERROR", e);
20591122927SMatt Spinler }
20691122927SMatt Spinler }
20791122927SMatt Spinler
processExistingCallouts(sdbusplus::bus_t & bus)2083e073ba6SPatrick Williams void Add::processExistingCallouts(sdbusplus::bus_t& bus)
20991122927SMatt Spinler {
21091122927SMatt Spinler MapperResponseType mapperResponse;
21191122927SMatt Spinler
21291122927SMatt Spinler getLoggingSubTree(bus, mapperResponse);
213891c4769SDhruvaraj Subhashchandran if (mapperResponse.empty())
214891c4769SDhruvaraj Subhashchandran {
215fc30e0c1SDhruvaraj Subhashchandran // No errors to process.
216891c4769SDhruvaraj Subhashchandran return;
217891c4769SDhruvaraj Subhashchandran }
218891c4769SDhruvaraj Subhashchandran
219891c4769SDhruvaraj Subhashchandran for (const auto& elem : mapperResponse)
220891c4769SDhruvaraj Subhashchandran {
22191ac8d3aSPatrick Venture auto method = bus.new_method_call(
22291ac8d3aSPatrick Venture elem.second.begin()->first.c_str(), elem.first.c_str(),
22391ac8d3aSPatrick Venture "org.freedesktop.DBus.Properties", "Get");
224a6e48929SAndrew Geissler method.append("xyz.openbmc_project.Association.Definitions");
225a6e48929SAndrew Geissler method.append("Associations");
226891c4769SDhruvaraj Subhashchandran auto reply = bus.call(method);
227891c4769SDhruvaraj Subhashchandran if (reply.is_method_error())
228891c4769SDhruvaraj Subhashchandran {
229891c4769SDhruvaraj Subhashchandran // do not stop, continue with next elog
230e9fb5c6aSGeorge Liu lg2::error("Error in getting associations");
231891c4769SDhruvaraj Subhashchandran continue;
232891c4769SDhruvaraj Subhashchandran }
233891c4769SDhruvaraj Subhashchandran
234a41d282aSPatrick Williams std::variant<AssociationList> assoc;
235151122aaSWilliam A. Kennington III try
236151122aaSWilliam A. Kennington III {
237891c4769SDhruvaraj Subhashchandran reply.read(assoc);
238151122aaSWilliam A. Kennington III }
2393e073ba6SPatrick Williams catch (const sdbusplus::exception_t& e)
240151122aaSWilliam A. Kennington III {
241e9fb5c6aSGeorge Liu lg2::error(
242e9fb5c6aSGeorge Liu "Failed to parse existing callouts associations message, ERROR = {ERROR}",
243e9fb5c6aSGeorge Liu "ERROR", e);
244151122aaSWilliam A. Kennington III continue;
245151122aaSWilliam A. Kennington III }
2465ebebeffSPatrick Williams auto& assocs = std::get<AssociationList>(assoc);
247891c4769SDhruvaraj Subhashchandran if (assocs.empty())
248891c4769SDhruvaraj Subhashchandran {
249891c4769SDhruvaraj Subhashchandran // no associations, skip
250891c4769SDhruvaraj Subhashchandran continue;
251891c4769SDhruvaraj Subhashchandran }
252891c4769SDhruvaraj Subhashchandran
253891c4769SDhruvaraj Subhashchandran for (const auto& item : assocs)
254891c4769SDhruvaraj Subhashchandran {
255891c4769SDhruvaraj Subhashchandran if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
256891c4769SDhruvaraj Subhashchandran {
257891c4769SDhruvaraj Subhashchandran removeWatches.emplace_back(
258891c4769SDhruvaraj Subhashchandran std::make_unique<Remove>(bus, std::get<2>(item)));
259891c4769SDhruvaraj Subhashchandran action(bus, std::get<2>(item), true);
260891c4769SDhruvaraj Subhashchandran }
261891c4769SDhruvaraj Subhashchandran }
262891c4769SDhruvaraj Subhashchandran }
263891c4769SDhruvaraj Subhashchandran }
264891c4769SDhruvaraj Subhashchandran
removed(sdbusplus::message_t & msg)2653e073ba6SPatrick Williams void Remove::removed(sdbusplus::message_t& msg)
26659b86cd7SDhruvaraj Subhashchandran {
2673eedbe44SPatrick Williams auto bus = msg.get_bus();
2683c6f29a0SDhruvaraj Subhashchandran
2693eedbe44SPatrick Williams action(bus, inventoryPath, false);
2703eedbe44SPatrick Williams return;
27159b86cd7SDhruvaraj Subhashchandran }
27259b86cd7SDhruvaraj Subhashchandran
27359b86cd7SDhruvaraj Subhashchandran } // namespace monitor
27459b86cd7SDhruvaraj Subhashchandran } // namespace fault
27559b86cd7SDhruvaraj Subhashchandran } // namespace fru
27659b86cd7SDhruvaraj Subhashchandran } // namespace led
27759b86cd7SDhruvaraj Subhashchandran } // namespace phosphor
278