Attn: Dump request and monitoring support
Support for requesting a dump from the dump manager and monitoring the
dump progress.
Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I03acd2b8c13ce0b5ced63ff7fbb32f7225467aee
diff --git a/attn/attn_dbus.cpp b/attn/attn_dbus.cpp
index 97843b8..faf5e1f 100644
--- a/attn/attn_dbus.cpp
+++ b/attn/attn_dbus.cpp
@@ -9,24 +9,11 @@
namespace attn
{
-/**
- * Create a dbus method
- *
- * Find the dbus service associated with the dbus object path and create
- * a dbus method for calling the specified dbus interface and function.
- *
- * @param i_path - dbus object path
- * @param i_interface - dbus method interface
- * @param i_function - dbus interface function
- * @param o_method - method that is created
- * @param i_extended - optional for extended methods
- * @return non-zero if error
- *
- **/
+/** @brief Create a dbus method */
int dbusMethod(const std::string& i_path, const std::string& i_interface,
const std::string& i_function,
sdbusplus::message::message& o_method,
- const std::string& i_extended = "")
+ const std::string& i_extended)
{
int rc = RC_DBUS_ERROR; // assume error
@@ -89,7 +76,7 @@
}
catch (const sdbusplus::exception::SdBusError& e)
{
- trace<level::INFO>("dbusMethod exception");
+ trace<level::ERROR>("dbusMethod exception");
std::string traceMsg = std::string(e.what(), maxTraceLen);
trace<level::ERROR>(traceMsg.c_str());
}
@@ -134,7 +121,7 @@
}
catch (const sdbusplus::exception::SdBusError& e)
{
- trace<level::INFO>("createPel exception");
+ trace<level::ERROR>("createPel exception");
std::string traceMsg = std::string(e.what(), maxTraceLen);
trace<level::ERROR>(traceMsg.c_str());
}
@@ -188,7 +175,7 @@
}
catch (const sdbusplus::exception::SdBusError& e)
{
- trace<level::INFO>("createPelRaw exception");
+ trace<level::ERROR>("createPelRaw exception");
std::string traceMsg = std::string(e.what(), maxTraceLen);
trace<level::ERROR>(traceMsg.c_str());
}
@@ -228,7 +215,7 @@
}
catch (const sdbusplus::exception::SdBusError& e)
{
- trace<level::INFO>("getPel exception");
+ trace<level::ERROR>("getPel exception");
std::string traceMsg = std::string(e.what(), maxTraceLen);
trace<level::ERROR>(traceMsg.c_str());
}
@@ -291,7 +278,7 @@
}
catch (const sdbusplus::exception::SdBusError& e)
{
- trace<level::INFO>("hostRunningState exception");
+ trace<level::ERROR>("hostRunningState exception");
std::string traceMsg = std::string(e.what(), maxTraceLen);
trace<level::ERROR>(traceMsg.c_str());
}
diff --git a/attn/attn_dbus.hpp b/attn/attn_dbus.hpp
index 700097f..088bf59 100644
--- a/attn/attn_dbus.hpp
+++ b/attn/attn_dbus.hpp
@@ -16,6 +16,25 @@
};
/**
+ * Create a dbus method
+ *
+ * Find the dbus service associated with the dbus object path and create
+ * a dbus method for calling the specified dbus interface and function.
+ *
+ * @param i_path - dbus object path
+ * @param i_interface - dbus method interface
+ * @param i_function - dbus interface function
+ * @param o_method - method that is created
+ * @param i_extended - optional for extended methods
+ * @return non-zero if error
+ *
+ **/
+int dbusMethod(const std::string& i_path, const std::string& i_interface,
+ const std::string& i_function,
+ sdbusplus::message::message& o_method,
+ const std::string& i_extended = "");
+
+/**
* Create a PEL for the specified event type
*
* The additional data provided in the map will be placed in a user data
diff --git a/attn/attn_logging.cpp b/attn/attn_logging.cpp
index a9be924..73eebdf 100644
--- a/attn/attn_logging.cpp
+++ b/attn/attn_logging.cpp
@@ -1,8 +1,10 @@
#include <unistd.h>
+#include <attn/attn_common.hpp>
#include <attn/attn_dbus.hpp>
#include <attn/attn_logging.hpp>
#include <attn/pel/pel_minimal.hpp>
+#include <attn/ti_handler.hpp>
#include <phosphor-logging/log.hpp>
namespace attn
@@ -404,6 +406,18 @@
close(pelFd);
}
}
+
+ uint8_t subsystem = std::stoi(i_additional["Subsystem"]);
+
+ // If not hypervisor TI
+ if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) != subsystem)
+ {
+ // Request a dump and transition the host
+ if ("true" == i_additional["Dump"])
+ {
+ requestDump(pelId); // will not return until dump is complete
+ }
+ }
}
}
diff --git a/attn/ti_handler.cpp b/attn/ti_handler.cpp
index fc546c4..8ecb64b 100644
--- a/attn/ti_handler.cpp
+++ b/attn/ti_handler.cpp
@@ -1,4 +1,5 @@
#include <attn/attn_common.hpp>
+#include <attn/attn_dbus.hpp>
#include <attn/attn_handler.hpp>
#include <attn/attn_logging.hpp>
#include <attn/pel/pel_common.hpp>
@@ -211,55 +212,46 @@
trace<level::INFO>("reason: other");
}
- break;
+ break; // case TI_WITH_SRC
}
}
- // gather additional data for PEL
- std::map<std::string, std::string> tiAdditionalData;
-
- if (nullptr != i_tiDataArea)
+ if (true == generatePel)
{
- parseHbTiInfo(tiAdditionalData, i_tiDataArea);
-
- if (true == generatePel)
+ if (nullptr != i_tiDataArea)
{
+ // gather additional data for PEL
+ std::map<std::string, std::string> tiAdditionalData;
+
+ parseHbTiInfo(tiAdditionalData, i_tiDataArea);
+
tiAdditionalData["Subsystem"] = std::to_string(
static_cast<uint8_t>(pel::SubsystemID::hostboot));
- // Translate hex src value to ascii. This results in an 8 character
- // SRC (hostboot SRC is 32 bits)
+ // Translate hex src value to ascii. This results in an 8
+ // character SRC (hostboot SRC is 32 bits)
std::stringstream src;
src << std::setw(8) << std::setfill('0') << std::uppercase
<< std::hex << be32toh(i_tiDataArea->srcWord12HbWord0);
tiAdditionalData["SrcAscii"] = src.str();
+ // Request dump after generating event log?
+ tiAdditionalData["Dump"] =
+ (true == hbDumpRequested) ? "true" : "false";
+
+ // Generate event log
eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
}
- }
- else
- {
- // TI data was not available This should not happen since we provide
- // a default TI info in the case where get TI info was not successful.
- eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL);
+ else
+ {
+ // TI data was not available This should not happen.
+ eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL);
+ }
}
if (true == terminateHost)
{
- // if hostboot dump is requested initiate dump
- if (hbDumpRequested)
- {
- // Until HB dump support available just quiesce the host - once
- // dump support is available the dump component will transition
- // (ipl/halt) the host.
- transitionHost(HostState::Quiesce);
- }
- else
- {
- // Quiese the host - when the host is quiesced it will either
- // "halt" or IPL depending on autoreboot setting.
- transitionHost(HostState::Quiesce);
- }
+ transitionHost(HostState::Quiesce);
}
}
@@ -430,4 +422,115 @@
return autoReboot;
}
+/**
+ * Callback for dump request properties change signal monitor
+ *
+ * @param[in] i_msg Dbus message from the dbus match infrastructure
+ * @param[in] i_path The object path we are monitoring
+ * @param[out] o_inProgress Used to break out of our dbus wait loop
+ * @reutn Always non-zero indicating no error, no cascading callbacks
+ */
+uint dumpStatusChanged(sdbusplus::message::message& i_msg, std::string i_path,
+ bool& o_inProgress)
+{
+ // 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) && ("xyz.openbmc_project.Common.Progress."
+ "OperationStatus.InProgress" != *status))
+ {
+ // dump is done, trace some info and change in progress flag
+ trace<level::INFO>(i_path.c_str());
+ trace<level::INFO>((*status).c_str());
+ o_inProgress = false;
+ }
+ }
+
+ 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)
+{
+ bool inProgress = true; // callback will update this
+
+ // setup the signal match rules and callback
+ std::string matchInterface = "xyz.openbmc_project.Common.Progress";
+ auto bus = sdbusplus::bus::new_system();
+
+ 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, i_path, inProgress);
+ });
+
+ // wait for dump status to be completed (complete == true)
+ trace<level::INFO>("hbdump requested");
+ while (true == inProgress)
+ {
+ bus.wait(0);
+ bus.process_discard();
+ }
+ trace<level::INFO>("hbdump completed");
+}
+
+/** Request a dump from the dump manager */
+void requestDump(const uint32_t logId)
+{
+ constexpr auto path = "/org/openpower/dump";
+ constexpr auto interface = "xyz.openbmc_project.Dump.Create";
+ constexpr auto function = "CreateDump";
+
+ sdbusplus::message::message method;
+
+ if (0 == dbusMethod(path, interface, function, method))
+ {
+ try
+ {
+ // dbus call arguments
+ std::map<std::string, std::string> createParams;
+ createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
+ "com.ibm.Dump.Create.DumpType.Hostboot";
+ createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
+ std::to_string(logId);
+ 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<level::ERROR>("requestDump exception");
+ std::string traceMsg = std::string(e.what(), maxTraceLen);
+ trace<level::ERROR>(traceMsg.c_str());
+ }
+ }
+}
+
} // namespace attn
diff --git a/attn/ti_handler.hpp b/attn/ti_handler.hpp
index 492868c..23cc58b 100644
--- a/attn/ti_handler.hpp
+++ b/attn/ti_handler.hpp
@@ -132,4 +132,14 @@
*/
bool autoRebootEnabled();
+/**
+ * Request a dump from the dump manager
+ *
+ * Request a dump from the dump manager and register a monitor for observing
+ * the dump progress.
+ *
+ * @param logId The id of the event log associated with this dump request
+ */
+void requestDump(const uint32_t logId);
+
} // namespace attn