xref: /openbmc/phosphor-led-manager/fault-monitor/fru-fault-monitor.cpp (revision b6da78887c6906d9a07b9142e66f2ba7ff582449)
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 
221f0b715aSGeorge Liu static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
231f0b715aSGeorge Liu static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
241f0b715aSGeorge Liu static constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
251f0b715aSGeorge Liu static constexpr auto objMgrIntf = "org.freedesktop.DBus.ObjectManager";
261f0b715aSGeorge Liu static constexpr auto ledGroups = "/xyz/openbmc_project/led/groups/";
271f0b715aSGeorge 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 {
511f0b715aSGeorge Liu     auto mapper = bus.new_method_call(mapperBusName, mapperObjPath, mapperIntf,
521f0b715aSGeorge Liu                                       "GetObject");
531f0b715aSGeorge 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     {
841f0b715aSGeorge 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 
944bb15d80SGeorge Liu     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 
1051f0b715aSGeorge 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 
1683c6f29a0SDhruvaraj Subhashchandran     for (const auto& item : assocs)
1693c6f29a0SDhruvaraj Subhashchandran     {
170*b6da7888SGeorge Liu         if (std::get<1>(item) == CALLOUT_REV_ASSOCIATION)
1713c6f29a0SDhruvaraj Subhashchandran         {
1723eedbe44SPatrick Williams             removeWatches.emplace_back(
1733c6f29a0SDhruvaraj Subhashchandran                 std::make_unique<Remove>(bus, std::get<2>(item)));
174891c4769SDhruvaraj Subhashchandran             action(bus, std::get<2>(item), true);
1753c6f29a0SDhruvaraj Subhashchandran         }
1763c6f29a0SDhruvaraj Subhashchandran     }
177aebfde81SDhruvaraj Subhashchandran 
1783eedbe44SPatrick Williams     return;
17959b86cd7SDhruvaraj Subhashchandran }
18059b86cd7SDhruvaraj Subhashchandran 
getLoggingSubTree(sdbusplus::bus_t & bus,MapperResponseType & subtree)1813e073ba6SPatrick Williams void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
182891c4769SDhruvaraj Subhashchandran {
183891c4769SDhruvaraj Subhashchandran     auto depth = 0;
1841f0b715aSGeorge Liu     auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath,
1851f0b715aSGeorge Liu                                           mapperIntf, "GetSubTree");
186891c4769SDhruvaraj Subhashchandran     mapperCall.append("/");
187891c4769SDhruvaraj Subhashchandran     mapperCall.append(depth);
1881f0b715aSGeorge Liu     mapperCall.append(std::vector<Interface>({logIntf}));
189891c4769SDhruvaraj Subhashchandran 
19091122927SMatt Spinler     try
19191122927SMatt Spinler     {
192891c4769SDhruvaraj Subhashchandran         auto mapperResponseMsg = bus.call(mapperCall);
19391122927SMatt Spinler         mapperResponseMsg.read(subtree);
194151122aaSWilliam A. Kennington III     }
1953e073ba6SPatrick Williams     catch (const sdbusplus::exception_t& e)
196151122aaSWilliam A. Kennington III     {
197e9fb5c6aSGeorge Liu         lg2::error(
198e9fb5c6aSGeorge Liu             "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
199e9fb5c6aSGeorge Liu             "ERROR", e);
20091122927SMatt Spinler     }
20191122927SMatt Spinler }
20291122927SMatt Spinler 
processExistingCallouts(sdbusplus::bus_t & bus)2033e073ba6SPatrick Williams void Add::processExistingCallouts(sdbusplus::bus_t& bus)
20491122927SMatt Spinler {
20591122927SMatt Spinler     MapperResponseType mapperResponse;
20691122927SMatt Spinler 
20791122927SMatt Spinler     getLoggingSubTree(bus, mapperResponse);
208891c4769SDhruvaraj Subhashchandran     if (mapperResponse.empty())
209891c4769SDhruvaraj Subhashchandran     {
210fc30e0c1SDhruvaraj Subhashchandran         // No errors to process.
211891c4769SDhruvaraj Subhashchandran         return;
212891c4769SDhruvaraj Subhashchandran     }
213891c4769SDhruvaraj Subhashchandran 
214891c4769SDhruvaraj Subhashchandran     for (const auto& elem : mapperResponse)
215891c4769SDhruvaraj Subhashchandran     {
21691ac8d3aSPatrick Venture         auto method = bus.new_method_call(
21791ac8d3aSPatrick Venture             elem.second.begin()->first.c_str(), elem.first.c_str(),
21891ac8d3aSPatrick Venture             "org.freedesktop.DBus.Properties", "Get");
219a6e48929SAndrew Geissler         method.append("xyz.openbmc_project.Association.Definitions");
220a6e48929SAndrew Geissler         method.append("Associations");
221891c4769SDhruvaraj Subhashchandran         auto reply = bus.call(method);
222891c4769SDhruvaraj Subhashchandran         if (reply.is_method_error())
223891c4769SDhruvaraj Subhashchandran         {
224891c4769SDhruvaraj Subhashchandran             // do not stop, continue with next elog
225e9fb5c6aSGeorge Liu             lg2::error("Error in getting associations");
226891c4769SDhruvaraj Subhashchandran             continue;
227891c4769SDhruvaraj Subhashchandran         }
228891c4769SDhruvaraj Subhashchandran 
229a41d282aSPatrick Williams         std::variant<AssociationList> assoc;
230151122aaSWilliam A. Kennington III         try
231151122aaSWilliam A. Kennington III         {
232891c4769SDhruvaraj Subhashchandran             reply.read(assoc);
233151122aaSWilliam A. Kennington III         }
2343e073ba6SPatrick Williams         catch (const sdbusplus::exception_t& e)
235151122aaSWilliam A. Kennington III         {
236e9fb5c6aSGeorge Liu             lg2::error(
237e9fb5c6aSGeorge Liu                 "Failed to parse existing callouts associations message, ERROR = {ERROR}",
238e9fb5c6aSGeorge Liu                 "ERROR", e);
239151122aaSWilliam A. Kennington III             continue;
240151122aaSWilliam A. Kennington III         }
2415ebebeffSPatrick Williams         auto& assocs = std::get<AssociationList>(assoc);
242891c4769SDhruvaraj Subhashchandran 
243891c4769SDhruvaraj Subhashchandran         for (const auto& item : assocs)
244891c4769SDhruvaraj Subhashchandran         {
245*b6da7888SGeorge Liu             if (std::get<1>(item) == CALLOUT_REV_ASSOCIATION)
246891c4769SDhruvaraj Subhashchandran             {
247891c4769SDhruvaraj Subhashchandran                 removeWatches.emplace_back(
248891c4769SDhruvaraj Subhashchandran                     std::make_unique<Remove>(bus, std::get<2>(item)));
249891c4769SDhruvaraj Subhashchandran                 action(bus, std::get<2>(item), true);
250891c4769SDhruvaraj Subhashchandran             }
251891c4769SDhruvaraj Subhashchandran         }
252891c4769SDhruvaraj Subhashchandran     }
253891c4769SDhruvaraj Subhashchandran }
254891c4769SDhruvaraj Subhashchandran 
removed(sdbusplus::message_t & msg)2553e073ba6SPatrick Williams void Remove::removed(sdbusplus::message_t& msg)
25659b86cd7SDhruvaraj Subhashchandran {
2573eedbe44SPatrick Williams     auto bus = msg.get_bus();
2583c6f29a0SDhruvaraj Subhashchandran 
2593eedbe44SPatrick Williams     action(bus, inventoryPath, false);
2603eedbe44SPatrick Williams     return;
26159b86cd7SDhruvaraj Subhashchandran }
26259b86cd7SDhruvaraj Subhashchandran 
26359b86cd7SDhruvaraj Subhashchandran } // namespace monitor
26459b86cd7SDhruvaraj Subhashchandran } // namespace fault
26559b86cd7SDhruvaraj Subhashchandran } // namespace fru
26659b86cd7SDhruvaraj Subhashchandran } // namespace led
26759b86cd7SDhruvaraj Subhashchandran } // namespace phosphor
268