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