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