blob: 847eb8e3da004418876af66f05c10a2fc95e43cd [file] [log] [blame]
#include <attn/attn_dbus.hpp>
#include <attn/attn_dump.hpp>
#include <attn/attn_logging.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>
#include <util/trace.hpp>
constexpr uint64_t dumpTimeout = 3600000000; // microseconds
constexpr auto operationStatusInProgress =
"xyz.openbmc_project.Common.Progress.OperationStatus.InProgress";
namespace attn
{
/**
* Callback for dump request properties change signal monitor
*
* @param[in] i_msg Dbus message from the dbus match infrastructure
* @param[out] o_dumpStatus Dump status dbus response string
* @return Always non-zero indicating no error, no cascading callbacks
*/
uint dumpStatusChanged(sdbusplus::message_t& i_msg, std::string& o_dumpStatus)
{
// reply (msg) will be a property change message
std::string interface;
std::map<std::string, std::variant<std::string, uint8_t>> property;
i_msg.read(interface, property);
// looking for property Status changes
std::string propertyType = "Status";
auto dumpStatus = property.find(propertyType);
if (dumpStatus != property.end())
{
const std::string* status =
std::get_if<std::string>(&(dumpStatus->second));
if (nullptr != status)
{
o_dumpStatus = *status;
}
}
return 1; // non-negative return code for successful callback
}
/**
* Register a callback for dump progress status changes
*
* @param[in] i_path The object path of the dump to monitor
*/
void monitorDump(const std::string& i_path)
{
// setup the signal match rules and callback
std::string matchInterface = "xyz.openbmc_project.Common.Progress";
auto bus = sdbusplus::bus::new_system();
// monitor dump status change property, will update dumpStatus
std::string dumpStatus = "requested";
std::unique_ptr<sdbusplus::bus::match_t> match =
std::make_unique<sdbusplus::bus::match_t>(
bus,
sdbusplus::bus::match::rules::propertiesChanged(
i_path.c_str(), matchInterface.c_str()),
[&](auto& msg) { return dumpStatusChanged(msg, dumpStatus); });
// wait for dump status to be completed (complete == true)
trace::inf("dump requested %s", i_path.c_str());
// wait for dump status not InProgress or timeout
uint64_t timeRemaining = dumpTimeout;
std::chrono::steady_clock::time_point begin =
std::chrono::steady_clock::now();
while (("requested" == dumpStatus ||
operationStatusInProgress == dumpStatus) &&
0 != timeRemaining)
{
bus.wait(timeRemaining);
uint64_t timeElapsed =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - begin)
.count();
timeRemaining =
timeElapsed > timeRemaining ? 0 : timeRemaining - timeElapsed;
bus.process_discard();
}
if (0 == timeRemaining)
{
trace::err("dump request timed out after %" PRIu64 " microseconds",
dumpTimeout);
}
trace::inf("dump status: %s", dumpStatus.c_str());
}
/** Request a dump from the dump manager */
void requestDump(uint32_t i_logId, const DumpParameters& i_dumpParameters)
{
constexpr auto path = "/org/openpower/dump";
constexpr auto interface = "xyz.openbmc_project.Dump.Create";
constexpr auto function = "CreateDump";
sdbusplus::message_t method;
if (0 == dbusMethod(path, interface, function, method))
{
try
{
// dbus call arguments
std::map<std::string, std::variant<std::string, uint64_t>>
createParams;
createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
uint64_t(i_logId);
if (DumpType::Hostboot == i_dumpParameters.dumpType)
{
createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
"com.ibm.Dump.Create.DumpType.Hostboot";
}
else if (DumpType::Hardware == i_dumpParameters.dumpType)
{
createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
"com.ibm.Dump.Create.DumpType.Hardware";
createParams
["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
i_dumpParameters.unitId;
}
else if (DumpType::SBE == i_dumpParameters.dumpType)
{
createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
"com.ibm.Dump.Create.DumpType.SBE";
createParams
["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
i_dumpParameters.unitId;
}
method.append(createParams);
// using system dbus
auto bus = sdbusplus::bus::new_system();
auto response = bus.call(method);
// reply will be type dbus::ObjectPath
sdbusplus::message::object_path reply;
response.read(reply);
// monitor dump progress
monitorDump(reply);
}
catch (const sdbusplus::exception::SdBusError& e)
{
trace::err("requestDump exception");
trace::err(e.what());
}
}
}
} // namespace attn