#include #include "xyz/openbmc_project/Led/Fru/Monitor/error.hpp" #include "xyz/openbmc_project/Led/Mapper/error.hpp" #include "elog-errors.hpp" #include "fru-fault-monitor.hpp" #include #include "xyz/openbmc_project/Common/error.hpp" namespace phosphor { namespace led { namespace fru { namespace fault { namespace monitor { using namespace phosphor::logging; constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper"; constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper"; constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager"; constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/"; constexpr auto LOG_PATH = "/xyz/openbmc_project/logging"; constexpr auto LOG_IFACE = "xyz.openbmc_project.Logging.Entry"; using AssociationList = std::vector>; using Attributes = sdbusplus::message::variant; using AttributeName = std::string; using AttributeMap = std::map; using PropertyName = std::string; using PropertyMap = std::map; using LogEntryMsg = std::pair; using Service = std::string; using Path = std::string; using Interface = std::string; using Interfaces = std::vector; using MapperResponseType = std::map>; using InternalFailure = sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; using MethodErr = sdbusplus::xyz::openbmc_project::Led::Mapper::Error::MethodError; using ObjectNotFoundErr = sdbusplus::xyz::openbmc_project::Led::Mapper::Error::ObjectNotFoundError; using InventoryPathErr = sdbusplus::xyz::openbmc_project:: Led::Fru::Monitor::Error::InventoryPathError; std::string getService(sdbusplus::bus::bus& bus, const std::string& path) { auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH, MAPPER_IFACE, "GetObject"); mapper.append(path.c_str(), std::vector({OBJMGR_IFACE})); auto mapperResponseMsg = bus.call(mapper); if (mapperResponseMsg.is_method_error()) { using namespace xyz::openbmc_project::Led::Mapper; elog( MethodError::METHOD_NAME("GetObject"), MethodError::PATH(path.c_str()), MethodError::INTERFACE( OBJMGR_IFACE)); } std::map> mapperResponse; mapperResponseMsg.read(mapperResponse); if (mapperResponse.empty()) { using namespace xyz::openbmc_project::Led::Mapper; elog( ObjectNotFoundError::METHOD_NAME("GetObject"), ObjectNotFoundError::PATH(path.c_str()), ObjectNotFoundError::INTERFACE( OBJMGR_IFACE)); } return mapperResponse.cbegin()->first; } void action(sdbusplus::bus::bus& bus, const std::string& path, bool assert) { std::string service; try { service = getService(bus, LED_GROUPS); } catch (MethodErr& e) { commit(); return; } catch (ObjectNotFoundErr& e) { commit(); return; } auto pos = path.rfind("/"); if (pos == std::string::npos) { using namespace xyz::openbmc_project::Led::Fru::Monitor; report( InventoryPathError::PATH( path.c_str())); return; } auto unit = path.substr(pos + 1); std::string ledPath = LED_GROUPS + unit + '_' + LED_FAULT; auto method = bus.new_method_call(service.c_str(), ledPath.c_str(), "org.freedesktop.DBus.Properties", "Set"); method.append("xyz.openbmc_project.Led.Group"); method.append("Asserted"); method.append(sdbusplus::message::variant(assert)); bus.call_noreply(method); return; } void Add::created(sdbusplus::message::message& msg) { auto bus = msg.get_bus(); LogEntryMsg logEntry; msg.read(logEntry); std::string objectPath(std::move(logEntry.first)); std::size_t found = objectPath.find(ELOG_ENTRY); if (found == std::string::npos) { //Not a new error entry skip return; } auto iter = logEntry.second.find("org.openbmc.Associations"); if (iter == logEntry.second.end()) { return; } //Nothing else shows when a specific error log //has been created. Do it here. std::string message{objectPath + " created"}; log(message.c_str()); auto attr = iter->second.find("associations"); if (attr == iter->second.end()) { return; } auto& assocs = sdbusplus::message::variant_ns::get(attr->second); if (assocs.empty()) { //No associations skip return; } for (const auto& item : assocs) { if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0) { removeWatches.emplace_back( std::make_unique(bus, std::get<2>(item))); action(bus, std::get<2>(item), true); } } return; } void Add::processExistingCallouts(sdbusplus::bus::bus& bus) { auto depth = 0; auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH, MAPPER_IFACE, "GetSubTree"); mapperCall.append("/"); mapperCall.append(depth); mapperCall.append(std::vector({LOG_IFACE})); auto mapperResponseMsg = bus.call(mapperCall); if (mapperResponseMsg.is_method_error()) { using namespace xyz::openbmc_project::Led::Mapper; report( MethodError::METHOD_NAME("GetSubTree"), MethodError::PATH(MAPPER_OBJ_PATH), MethodError::INTERFACE( OBJMGR_IFACE)); return; } MapperResponseType mapperResponse; mapperResponseMsg.read(mapperResponse); if (mapperResponse.empty()) { //No errors to process. return; } for (const auto& elem : mapperResponse) { auto method = bus.new_method_call(elem.second.begin()->first.c_str(), elem.first.c_str(), "org.freedesktop.DBus.Properties", "Get"); method.append("org.openbmc.Associations"); method.append("associations"); auto reply = bus.call(method); if (reply.is_method_error()) { //do not stop, continue with next elog log("Error in getting associations"); continue; } sdbusplus::message::variant assoc; reply.read(assoc); auto& assocs = assoc.get(); if (assocs.empty()) { //no associations, skip continue; } for (const auto& item : assocs) { if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0) { removeWatches.emplace_back( std::make_unique(bus, std::get<2>(item))); action(bus, std::get<2>(item), true); } } } } void Remove::removed(sdbusplus::message::message& msg) { auto bus = msg.get_bus(); action(bus, inventoryPath, false); return; } }//namespace monitor }//namespace fault }//namespace fru }//namespace led }//namespace phosphor