1 #include "config.h" 2 3 #include "elog_watch.hpp" 4 5 #include "dump_internal.hpp" 6 #include "dump_serialize.hpp" 7 #include "xyz/openbmc_project/Dump/Create/error.hpp" 8 9 #include <cereal/cereal.hpp> 10 #include <phosphor-logging/elog.hpp> 11 #include <sdbusplus/exception.hpp> 12 13 // Register class version with Cereal 14 CEREAL_CLASS_VERSION(phosphor::dump::elog::Watch, CLASS_VERSION); 15 16 namespace phosphor 17 { 18 namespace dump 19 { 20 namespace elog 21 { 22 23 using namespace phosphor::logging; 24 constexpr auto LOG_PATH = "/xyz/openbmc_project/logging"; 25 constexpr auto INTERNAL_FAILURE = 26 "xyz.openbmc_project.Common.Error.InternalFailure"; 27 using Message = std::string; 28 using Attributes = sdbusplus::message::variant<Message>; 29 using AttributeName = std::string; 30 using AttributeMap = std::map<AttributeName, Attributes>; 31 using PropertyName = std::string; 32 using PropertyMap = std::map<PropertyName, AttributeMap>; 33 34 Watch::Watch(sdbusplus::bus::bus& bus, IMgr& iMgr) : 35 iMgr(iMgr), 36 addMatch(bus, 37 sdbusplus::bus::match::rules::interfacesAdded() + 38 sdbusplus::bus::match::rules::path_namespace(OBJ_LOGGING), 39 std::bind(std::mem_fn(&Watch::addCallback), this, 40 std::placeholders::_1)), 41 delMatch(bus, 42 sdbusplus::bus::match::rules::interfacesRemoved() + 43 sdbusplus::bus::match::rules::path_namespace(OBJ_LOGGING), 44 std::bind(std::mem_fn(&Watch::delCallback), this, 45 std::placeholders::_1)) 46 { 47 48 fs::path file(ELOG_ID_PERSIST_PATH); 49 if (fs::exists(file)) 50 { 51 if (!deserialize(ELOG_ID_PERSIST_PATH, elogList)) 52 { 53 log<level::ERR>("Error occurred during error id deserialize"); 54 } 55 } 56 } 57 58 void Watch::addCallback(sdbusplus::message::message& msg) 59 { 60 using Type = 61 sdbusplus::xyz::openbmc_project::Dump::Internal::server::Create::Type; 62 using QuotaExceeded = 63 sdbusplus::xyz::openbmc_project::Dump::Create::Error::QuotaExceeded; 64 65 sdbusplus::message::object_path objectPath; 66 PropertyMap propertyMap; 67 try 68 { 69 msg.read(objectPath, propertyMap); 70 } 71 catch (const sdbusplus::exception::SdBusError& e) 72 { 73 log<level::ERR>("Failed to parse elog add signal", 74 entry("ERROR=%s", e.what()), 75 entry("REPLY_SIG=%s", msg.get_signature())); 76 return; 77 } 78 79 std::size_t found = objectPath.str.find("entry"); 80 if (found == std::string::npos) 81 { 82 // Not a new error entry skip 83 return; 84 } 85 86 auto eId = getEid(objectPath); 87 88 auto search = elogList.find(eId); 89 if (search != elogList.end()) 90 { 91 // elog exists in the list, Skip the dump 92 return; 93 } 94 95 auto iter = propertyMap.find("xyz.openbmc_project.Logging.Entry"); 96 if (iter == propertyMap.end()) 97 { 98 return; 99 } 100 101 auto attr = iter->second.find("Message"); 102 if (attr == iter->second.end()) 103 { 104 return; 105 } 106 107 auto& data = 108 sdbusplus::message::variant_ns::get<PropertyName>(attr->second); 109 if (data.empty()) 110 { 111 // No Message skip 112 return; 113 } 114 115 if (data != INTERNAL_FAILURE) 116 { 117 // Not a InternalFailure, skip 118 return; 119 } 120 121 std::vector<std::string> fullPaths; 122 fullPaths.push_back(objectPath); 123 124 try 125 { 126 // Save the elog information. This is to avoid dump requests 127 // in elog restore path. 128 elogList.insert(eId); 129 130 phosphor::dump::elog::serialize(elogList); 131 132 // Call internal create function to initiate dump 133 iMgr.IMgr::create(Type::InternalFailure, fullPaths); 134 } 135 catch (QuotaExceeded& e) 136 { 137 // No action now 138 } 139 return; 140 } 141 142 void Watch::delCallback(sdbusplus::message::message& msg) 143 { 144 sdbusplus::message::object_path objectPath; 145 try 146 { 147 msg.read(objectPath); 148 } 149 catch (const sdbusplus::exception::SdBusError& e) 150 { 151 log<level::ERR>("Failed to parse elog del signal", 152 entry("ERROR=%s", e.what()), 153 entry("REPLY_SIG=%s", msg.get_signature())); 154 return; 155 } 156 157 // Get elog id 158 auto eId = getEid(objectPath); 159 160 // Delete the elog entry from the list and serialize 161 auto search = elogList.find(eId); 162 if (search != elogList.end()) 163 { 164 elogList.erase(search); 165 phosphor::dump::elog::serialize(elogList); 166 } 167 } 168 169 } // namespace elog 170 } // namespace dump 171 } // namespace phosphor 172