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; 34*f2044037SPatrick Williams using PropertyMap = std::unordered_map<PropertyName, Attributes>; 35b2f253b7SMatt Spinler using InterfaceName = std::string; 36*f2044037SPatrick 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>; 42*f2044037SPatrick Williams using MapperResponseType = 43*f2044037SPatrick 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 5091ac8d3aSPatrick Venture std::string getService(sdbusplus::bus::bus& 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 56*f2044037SPatrick 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 } 627152edcfSPatrick Williams catch (const sdbusplus::exception::exception& 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 8091ac8d3aSPatrick Venture void action(sdbusplus::bus::bus& 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 } 1197152edcfSPatrick Williams catch (const sdbusplus::exception::exception& 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 1283eedbe44SPatrick Williams void Add::created(sdbusplus::message::message& 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 } 1387152edcfSPatrick Williams catch (const sdbusplus::exception::exception& 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 18991122927SMatt Spinler void getLoggingSubTree(sdbusplus::bus::bus& 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 } 2037152edcfSPatrick Williams catch (const sdbusplus::exception::exception& 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 21191122927SMatt Spinler void Add::processExistingCallouts(sdbusplus::bus::bus& 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 } 2427152edcfSPatrick Williams catch (const sdbusplus::exception::exception& 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 2683eedbe44SPatrick Williams void Remove::removed(sdbusplus::message::message& 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