blob: d128f12aa4d7b26343e78123bc6ae7d05e4e8d99 [file] [log] [blame]
#include "config.h"
#include "elog_watch.hpp"
#include "dump_internal.hpp"
#include "dump_serialize.hpp"
#include "dump_types.hpp"
#include "xyz/openbmc_project/Dump/Create/error.hpp"
#include <cereal/cereal.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/exception.hpp>
#include <fstream>
// Register class version with Cereal
CEREAL_CLASS_VERSION(phosphor::dump::elog::Watch, CLASS_VERSION)
namespace phosphor
{
namespace dump
{
namespace elog
{
constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
using Message = std::string;
using Attributes = std::variant<Message>;
using AttributeName = std::string;
using AttributeMap = std::map<AttributeName, Attributes>;
using PropertyName = std::string;
using PropertyMap = std::map<PropertyName, AttributeMap>;
Watch::Watch(sdbusplus::bus_t& bus, Mgr& mgr) :
mgr(mgr),
addMatch(bus,
sdbusplus::bus::match::rules::interfacesAdded() +
sdbusplus::bus::match::rules::path_namespace(OBJ_LOGGING),
std::bind(std::mem_fn(&Watch::addCallback), this,
std::placeholders::_1)),
delMatch(bus,
sdbusplus::bus::match::rules::interfacesRemoved() +
sdbusplus::bus::match::rules::path_namespace(OBJ_LOGGING),
std::bind(std::mem_fn(&Watch::delCallback), this,
std::placeholders::_1))
{
std::filesystem::path file(ELOG_ID_PERSIST_PATH);
if (std::filesystem::exists(file))
{
if (!deserialize(ELOG_ID_PERSIST_PATH, elogList))
{
lg2::error("Error occurred during error id deserialize");
}
}
}
void Watch::addCallback(sdbusplus::message_t& msg)
{
using QuotaExceeded =
sdbusplus::xyz::openbmc_project::Dump::Create::Error::QuotaExceeded;
sdbusplus::message::object_path objectPath;
PropertyMap propertyMap;
try
{
msg.read(objectPath, propertyMap);
}
catch (const sdbusplus::exception_t& e)
{
lg2::error("Failed to parse elog add signal, errormsg: {ERROR}, "
"REPLY_SIG: {REPLY_SIG}",
"ERROR", e, "REPLY_SIG", msg.get_signature());
return;
}
std::size_t found = objectPath.str.find("entry");
if (found == std::string::npos)
{
// Not a new error entry skip
return;
}
auto eId = getEid(objectPath);
auto search = elogList.find(eId);
if (search != elogList.end())
{
// elog exists in the list, Skip the dump
return;
}
auto iter = propertyMap.find("xyz.openbmc_project.Logging.Entry");
if (iter == propertyMap.end())
{
return;
}
auto attr = iter->second.find("Message");
if (attr == iter->second.end())
{
return;
}
auto& data = std::get<PropertyName>(attr->second);
if (data.empty())
{
// No Message skip
return;
}
auto etype = findErrorType(data);
if (!etype.has_value())
{
// error not supported in the configuration
return;
}
auto errorType = etype.value();
DumpCreateParams params;
using DumpIntr = sdbusplus::common::xyz::openbmc_project::dump::Create;
using CreateParameters =
sdbusplus::common::xyz::openbmc_project::dump::Create::CreateParameters;
using DumpType =
sdbusplus::common::xyz::openbmc_project::dump::Create::DumpType;
params[DumpIntr::convertCreateParametersToString(
CreateParameters::FilePath)] = objectPath;
params[DumpIntr::convertCreateParametersToString(
CreateParameters::DumpType)] =
DumpIntr::convertDumpTypeToString(DumpType::ErrorLog);
params[DumpIntr::convertCreateParametersToString(
CreateParameters::ErrorType)] = errorType;
try
{
// Save the elog information. This is to avoid dump requests
// in elog restore path.
elogList.insert(eId);
phosphor::dump::elog::serialize(elogList);
mgr.Mgr::createDump(params);
}
catch (const QuotaExceeded& e)
{
// No action now
}
return;
}
void Watch::delCallback(sdbusplus::message_t& msg)
{
sdbusplus::message::object_path objectPath;
try
{
msg.read(objectPath);
}
catch (const sdbusplus::exception_t& e)
{
lg2::error("Failed to parse elog del signal, errormsg: {ERROR}, "
"REPLY_SIG: {REPLY_SIG}",
"ERROR", e, "REPLY_SIG", msg.get_signature());
return;
}
std::size_t found = objectPath.str.find("entry");
if (found == std::string::npos)
{
// Not a error entry so skip
return;
}
// Get elog id
auto eId = getEid(objectPath);
// Delete the elog entry from the list and serialize
auto search = elogList.find(eId);
if (search != elogList.end())
{
elogList.erase(search);
phosphor::dump::elog::serialize(elogList);
}
}
} // namespace elog
} // namespace dump
} // namespace phosphor