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 
223c6f29a0SDhruvaraj Subhashchandran constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
233c6f29a0SDhruvaraj Subhashchandran constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
243c6f29a0SDhruvaraj Subhashchandran constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
253c6f29a0SDhruvaraj Subhashchandran constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager";
263c6f29a0SDhruvaraj Subhashchandran constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/";
273c6f29a0SDhruvaraj Subhashchandran constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
28891c4769SDhruvaraj Subhashchandran constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry";
293c6f29a0SDhruvaraj Subhashchandran 
3091ac8d3aSPatrick Venture using AssociationList =
3191ac8d3aSPatrick Venture     std::vector<std::tuple<std::string, std::string, std::string>>;
32a41d282aSPatrick Williams using Attributes = std::variant<bool, AssociationList>;
33aebfde81SDhruvaraj Subhashchandran using PropertyName = std::string;
34f2044037SPatrick Williams using PropertyMap = std::unordered_map<PropertyName, Attributes>;
35b2f253b7SMatt Spinler using InterfaceName = std::string;
36f2044037SPatrick Williams using InterfaceMap = std::unordered_map<InterfaceName, PropertyMap>;
37aebfde81SDhruvaraj Subhashchandran 
38891c4769SDhruvaraj Subhashchandran using Service = std::string;
39891c4769SDhruvaraj Subhashchandran using Path = std::string;
40891c4769SDhruvaraj Subhashchandran using Interface = std::string;
41891c4769SDhruvaraj Subhashchandran using Interfaces = std::vector<Interface>;
42f2044037SPatrick Williams using MapperResponseType =
43f2044037SPatrick Williams     std::unordered_map<Path, std::unordered_map<Service, Interfaces>>;
44891c4769SDhruvaraj Subhashchandran 
459bd334ffSPatrick Williams using ResourceNotFoundErr =
469bd334ffSPatrick Williams     sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
479bd334ffSPatrick Williams using InvalidArgumentErr =
489bd334ffSPatrick Williams     sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
493c6f29a0SDhruvaraj Subhashchandran 
50*3e073ba6SPatrick Williams std::string getService(sdbusplus::bus_t& bus, const std::string& path)
513c6f29a0SDhruvaraj Subhashchandran {
5291ac8d3aSPatrick Venture     auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
533c6f29a0SDhruvaraj Subhashchandran                                       MAPPER_IFACE, "GetObject");
543c6f29a0SDhruvaraj Subhashchandran     mapper.append(path.c_str(), std::vector<std::string>({OBJMGR_IFACE}));
553c6f29a0SDhruvaraj Subhashchandran 
56f2044037SPatrick Williams     std::unordered_map<std::string, std::vector<std::string>> mapperResponse;
57151122aaSWilliam A. Kennington III     try
58151122aaSWilliam A. Kennington III     {
59d78de14dSGeorge Liu         auto mapperResponseMsg = bus.call(mapper);
603c6f29a0SDhruvaraj Subhashchandran         mapperResponseMsg.read(mapperResponse);
61151122aaSWilliam A. Kennington III     }
62*3e073ba6SPatrick Williams     catch (const sdbusplus::exception_t& e)
63151122aaSWilliam A. Kennington III     {
64e9fb5c6aSGeorge Liu         lg2::error(
65e9fb5c6aSGeorge Liu             "Failed to parse getService mapper response, ERROR = {ERROR}",
66e9fb5c6aSGeorge Liu             "ERROR", e);
679bd334ffSPatrick Williams         using namespace xyz::openbmc_project::Common;
689bd334ffSPatrick Williams         elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
69151122aaSWilliam A. Kennington III     }
703c6f29a0SDhruvaraj Subhashchandran     if (mapperResponse.empty())
713c6f29a0SDhruvaraj Subhashchandran     {
729bd334ffSPatrick Williams         using namespace xyz::openbmc_project::Common;
739bd334ffSPatrick Williams         elog<ResourceNotFoundErr>(ResourceNotFound::RESOURCE(path.c_str()));
74c5e0f31cSGeorge Liu         return {};
753c6f29a0SDhruvaraj Subhashchandran     }
763c6f29a0SDhruvaraj Subhashchandran 
773c6f29a0SDhruvaraj Subhashchandran     return mapperResponse.cbegin()->first;
783c6f29a0SDhruvaraj Subhashchandran }
793c6f29a0SDhruvaraj Subhashchandran 
80*3e073ba6SPatrick Williams void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
8159b86cd7SDhruvaraj Subhashchandran {
823c6f29a0SDhruvaraj Subhashchandran     std::string service;
833c6f29a0SDhruvaraj Subhashchandran     try
843c6f29a0SDhruvaraj Subhashchandran     {
85e77b8345SMatt Spinler         std::string groups{LED_GROUPS};
86e77b8345SMatt Spinler         groups.pop_back();
87e77b8345SMatt Spinler         service = getService(bus, groups);
883c6f29a0SDhruvaraj Subhashchandran     }
899bd334ffSPatrick Williams     catch (const ResourceNotFoundErr& e)
903c6f29a0SDhruvaraj Subhashchandran     {
919bd334ffSPatrick Williams         commit<ResourceNotFoundErr>();
923c6f29a0SDhruvaraj Subhashchandran         return;
933c6f29a0SDhruvaraj Subhashchandran     }
943c6f29a0SDhruvaraj Subhashchandran 
953c6f29a0SDhruvaraj Subhashchandran     auto pos = path.rfind("/");
963c6f29a0SDhruvaraj Subhashchandran     if (pos == std::string::npos)
973c6f29a0SDhruvaraj Subhashchandran     {
989bd334ffSPatrick Williams         using namespace xyz::openbmc_project::Common;
999bd334ffSPatrick Williams         report<InvalidArgumentErr>(
1009bd334ffSPatrick Williams             InvalidArgument::ARGUMENT_NAME("path"),
1019bd334ffSPatrick Williams             InvalidArgument::ARGUMENT_VALUE(path.c_str()));
1023c6f29a0SDhruvaraj Subhashchandran         return;
1033c6f29a0SDhruvaraj Subhashchandran     }
1043c6f29a0SDhruvaraj Subhashchandran     auto unit = path.substr(pos + 1);
1053c6f29a0SDhruvaraj Subhashchandran 
10691ac8d3aSPatrick Venture     std::string ledPath = LED_GROUPS + unit + '_' + LED_FAULT;
1073c6f29a0SDhruvaraj Subhashchandran 
10891ac8d3aSPatrick Venture     auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
10991ac8d3aSPatrick Venture                                       "org.freedesktop.DBus.Properties", "Set");
1103c6f29a0SDhruvaraj Subhashchandran     method.append("xyz.openbmc_project.Led.Group");
1113c6f29a0SDhruvaraj Subhashchandran     method.append("Asserted");
1123c6f29a0SDhruvaraj Subhashchandran 
113a41d282aSPatrick Williams     method.append(std::variant<bool>(assert));
11408d613e7SAdriana Kobylak 
11508d613e7SAdriana Kobylak     try
11608d613e7SAdriana Kobylak     {
1173c6f29a0SDhruvaraj Subhashchandran         bus.call_noreply(method);
11808d613e7SAdriana Kobylak     }
119*3e073ba6SPatrick Williams     catch (const sdbusplus::exception_t& e)
12008d613e7SAdriana Kobylak     {
12108d613e7SAdriana Kobylak         // Log an info message, system may not have all the LED Groups defined
122e9fb5c6aSGeorge Liu         lg2::info("Failed to Assert LED Group, ERROR = {ERROR}", "ERROR", e);
12308d613e7SAdriana Kobylak     }
1243c6f29a0SDhruvaraj Subhashchandran 
12559b86cd7SDhruvaraj Subhashchandran     return;
12659b86cd7SDhruvaraj Subhashchandran }
12759b86cd7SDhruvaraj Subhashchandran 
128*3e073ba6SPatrick Williams void Add::created(sdbusplus::message_t& msg)
12959b86cd7SDhruvaraj Subhashchandran {
1303eedbe44SPatrick Williams     auto bus = msg.get_bus();
1313c6f29a0SDhruvaraj Subhashchandran 
132b2f253b7SMatt Spinler     sdbusplus::message::object_path objectPath;
133b2f253b7SMatt Spinler     InterfaceMap interfaces;
134151122aaSWilliam A. Kennington III     try
135151122aaSWilliam A. Kennington III     {
136b2f253b7SMatt Spinler         msg.read(objectPath, interfaces);
137151122aaSWilliam A. Kennington III     }
138*3e073ba6SPatrick Williams     catch (const sdbusplus::exception_t& e)
139151122aaSWilliam A. Kennington III     {
140e9fb5c6aSGeorge Liu         lg2::error("Failed to parse created message, ERROR = {ERROR}", "ERROR",
141e9fb5c6aSGeorge Liu                    e);
142151122aaSWilliam A. Kennington III         return;
143151122aaSWilliam A. Kennington III     }
1443c6f29a0SDhruvaraj Subhashchandran 
145b2f253b7SMatt Spinler     std::size_t found = objectPath.str.find(ELOG_ENTRY);
1463c6f29a0SDhruvaraj Subhashchandran     if (found == std::string::npos)
1473c6f29a0SDhruvaraj Subhashchandran     {
1483c6f29a0SDhruvaraj Subhashchandran         // Not a new error entry skip
1493eedbe44SPatrick Williams         return;
1503c6f29a0SDhruvaraj Subhashchandran     }
151a6e48929SAndrew Geissler     auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
152b2f253b7SMatt Spinler     if (iter == interfaces.end())
1533c6f29a0SDhruvaraj Subhashchandran     {
1543eedbe44SPatrick Williams         return;
1553c6f29a0SDhruvaraj Subhashchandran     }
1563c6f29a0SDhruvaraj Subhashchandran 
1573d2b0d62SMatt Spinler     // Nothing else shows when a specific error log
1583d2b0d62SMatt Spinler     // has been created. Do it here.
159e9fb5c6aSGeorge Liu     // TODO:(phosphor-logging#25): support sdbusplus::message::object_path
160e9fb5c6aSGeorge Liu     // directly.
161e9fb5c6aSGeorge Liu     lg2::info("{PATH} created", "PATH", objectPath.str);
1623d2b0d62SMatt Spinler 
163a6e48929SAndrew Geissler     auto attr = iter->second.find("Associations");
164aebfde81SDhruvaraj Subhashchandran     if (attr == iter->second.end())
1653c6f29a0SDhruvaraj Subhashchandran     {
1663eedbe44SPatrick Williams         return;
1673c6f29a0SDhruvaraj Subhashchandran     }
1683c6f29a0SDhruvaraj Subhashchandran 
1695ebebeffSPatrick Williams     auto& assocs = std::get<AssociationList>(attr->second);
1703c6f29a0SDhruvaraj Subhashchandran     if (assocs.empty())
1713c6f29a0SDhruvaraj Subhashchandran     {
1723c6f29a0SDhruvaraj Subhashchandran         // No associations skip
1733eedbe44SPatrick Williams         return;
1743c6f29a0SDhruvaraj Subhashchandran     }
1753c6f29a0SDhruvaraj Subhashchandran 
1763c6f29a0SDhruvaraj Subhashchandran     for (const auto& item : assocs)
1773c6f29a0SDhruvaraj Subhashchandran     {
1783c6f29a0SDhruvaraj Subhashchandran         if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
1793c6f29a0SDhruvaraj Subhashchandran         {
1803eedbe44SPatrick Williams             removeWatches.emplace_back(
1813c6f29a0SDhruvaraj Subhashchandran                 std::make_unique<Remove>(bus, std::get<2>(item)));
182891c4769SDhruvaraj Subhashchandran             action(bus, std::get<2>(item), true);
1833c6f29a0SDhruvaraj Subhashchandran         }
1843c6f29a0SDhruvaraj Subhashchandran     }
185aebfde81SDhruvaraj Subhashchandran 
1863eedbe44SPatrick Williams     return;
18759b86cd7SDhruvaraj Subhashchandran }
18859b86cd7SDhruvaraj Subhashchandran 
189*3e073ba6SPatrick Williams void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
190891c4769SDhruvaraj Subhashchandran {
191891c4769SDhruvaraj Subhashchandran     auto depth = 0;
19291ac8d3aSPatrick Venture     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
19391ac8d3aSPatrick Venture                                           MAPPER_IFACE, "GetSubTree");
194891c4769SDhruvaraj Subhashchandran     mapperCall.append("/");
195891c4769SDhruvaraj Subhashchandran     mapperCall.append(depth);
196891c4769SDhruvaraj Subhashchandran     mapperCall.append(std::vector<Interface>({LOG_IFACE}));
197891c4769SDhruvaraj Subhashchandran 
19891122927SMatt Spinler     try
19991122927SMatt Spinler     {
200891c4769SDhruvaraj Subhashchandran         auto mapperResponseMsg = bus.call(mapperCall);
20191122927SMatt Spinler         mapperResponseMsg.read(subtree);
202151122aaSWilliam A. Kennington III     }
203*3e073ba6SPatrick Williams     catch (const sdbusplus::exception_t& e)
204151122aaSWilliam A. Kennington III     {
205e9fb5c6aSGeorge Liu         lg2::error(
206e9fb5c6aSGeorge Liu             "Failed to parse existing callouts subtree message, ERROR = {ERROR}",
207e9fb5c6aSGeorge Liu             "ERROR", e);
20891122927SMatt Spinler     }
20991122927SMatt Spinler }
21091122927SMatt Spinler 
211*3e073ba6SPatrick Williams void Add::processExistingCallouts(sdbusplus::bus_t& bus)
21291122927SMatt Spinler {
21391122927SMatt Spinler     MapperResponseType mapperResponse;
21491122927SMatt Spinler 
21591122927SMatt Spinler     getLoggingSubTree(bus, mapperResponse);
216891c4769SDhruvaraj Subhashchandran     if (mapperResponse.empty())
217891c4769SDhruvaraj Subhashchandran     {
218fc30e0c1SDhruvaraj Subhashchandran         // No errors to process.
219891c4769SDhruvaraj Subhashchandran         return;
220891c4769SDhruvaraj Subhashchandran     }
221891c4769SDhruvaraj Subhashchandran 
222891c4769SDhruvaraj Subhashchandran     for (const auto& elem : mapperResponse)
223891c4769SDhruvaraj Subhashchandran     {
22491ac8d3aSPatrick Venture         auto method = bus.new_method_call(
22591ac8d3aSPatrick Venture             elem.second.begin()->first.c_str(), elem.first.c_str(),
22691ac8d3aSPatrick Venture             "org.freedesktop.DBus.Properties", "Get");
227a6e48929SAndrew Geissler         method.append("xyz.openbmc_project.Association.Definitions");
228a6e48929SAndrew Geissler         method.append("Associations");
229891c4769SDhruvaraj Subhashchandran         auto reply = bus.call(method);
230891c4769SDhruvaraj Subhashchandran         if (reply.is_method_error())
231891c4769SDhruvaraj Subhashchandran         {
232891c4769SDhruvaraj Subhashchandran             // do not stop, continue with next elog
233e9fb5c6aSGeorge Liu             lg2::error("Error in getting associations");
234891c4769SDhruvaraj Subhashchandran             continue;
235891c4769SDhruvaraj Subhashchandran         }
236891c4769SDhruvaraj Subhashchandran 
237a41d282aSPatrick Williams         std::variant<AssociationList> assoc;
238151122aaSWilliam A. Kennington III         try
239151122aaSWilliam A. Kennington III         {
240891c4769SDhruvaraj Subhashchandran             reply.read(assoc);
241151122aaSWilliam A. Kennington III         }
242*3e073ba6SPatrick Williams         catch (const sdbusplus::exception_t& e)
243151122aaSWilliam A. Kennington III         {
244e9fb5c6aSGeorge Liu             lg2::error(
245e9fb5c6aSGeorge Liu                 "Failed to parse existing callouts associations message, ERROR = {ERROR}",
246e9fb5c6aSGeorge Liu                 "ERROR", e);
247151122aaSWilliam A. Kennington III             continue;
248151122aaSWilliam A. Kennington III         }
2495ebebeffSPatrick Williams         auto& assocs = std::get<AssociationList>(assoc);
250891c4769SDhruvaraj Subhashchandran         if (assocs.empty())
251891c4769SDhruvaraj Subhashchandran         {
252891c4769SDhruvaraj Subhashchandran             // no associations, skip
253891c4769SDhruvaraj Subhashchandran             continue;
254891c4769SDhruvaraj Subhashchandran         }
255891c4769SDhruvaraj Subhashchandran 
256891c4769SDhruvaraj Subhashchandran         for (const auto& item : assocs)
257891c4769SDhruvaraj Subhashchandran         {
258891c4769SDhruvaraj Subhashchandran             if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
259891c4769SDhruvaraj Subhashchandran             {
260891c4769SDhruvaraj Subhashchandran                 removeWatches.emplace_back(
261891c4769SDhruvaraj Subhashchandran                     std::make_unique<Remove>(bus, std::get<2>(item)));
262891c4769SDhruvaraj Subhashchandran                 action(bus, std::get<2>(item), true);
263891c4769SDhruvaraj Subhashchandran             }
264891c4769SDhruvaraj Subhashchandran         }
265891c4769SDhruvaraj Subhashchandran     }
266891c4769SDhruvaraj Subhashchandran }
267891c4769SDhruvaraj Subhashchandran 
268*3e073ba6SPatrick Williams void Remove::removed(sdbusplus::message_t& msg)
26959b86cd7SDhruvaraj Subhashchandran {
2703eedbe44SPatrick Williams     auto bus = msg.get_bus();
2713c6f29a0SDhruvaraj Subhashchandran 
2723eedbe44SPatrick Williams     action(bus, inventoryPath, false);
2733eedbe44SPatrick Williams     return;
27459b86cd7SDhruvaraj Subhashchandran }
27559b86cd7SDhruvaraj Subhashchandran 
27659b86cd7SDhruvaraj Subhashchandran } // namespace monitor
27759b86cd7SDhruvaraj Subhashchandran } // namespace fault
27859b86cd7SDhruvaraj Subhashchandran } // namespace fru
27959b86cd7SDhruvaraj Subhashchandran } // namespace led
28059b86cd7SDhruvaraj Subhashchandran } // namespace phosphor
281