OpenPOWER: Allow initiating mp reboot dump in quiesced state
When system dumps are disabled, a system dump collection
request will end up in quiesced state. A memory preserving
reboot from that state can get the failed data from the host.
So enabling the mp reboot dump collection from quiesced state.
Test:
Disable dump
Inject error in host to move to quiesced state
Start mp reboot
Dump should be generated
Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
Change-Id: I9f444752b321f1ab47b99e5b8ac32c79182d6453
diff --git a/dump_utils.hpp b/dump_utils.hpp
index 6e923bc..6d39bef 100644
--- a/dump_utils.hpp
+++ b/dump_utils.hpp
@@ -11,6 +11,7 @@
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Dump/Create/server.hpp>
#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
+#include <xyz/openbmc_project/State/Host/server.hpp>
#include <memory>
@@ -21,6 +22,8 @@
using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::server::
Progress::ProgressStages;
+using HostState =
+ sdbusplus::xyz::openbmc_project::State::server::Host::HostState;
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
@@ -79,26 +82,149 @@
* @param[in] path - D-Bus path name.
* @param[in] interface - D-Bus interface name.
* @return the bus service as a string
+ *
+ * @throws sdbusplus::exception::SdBusError - If any D-Bus error occurs during
+ * the call.
**/
std::string getService(sdbusplus::bus_t& bus, const std::string& path,
const std::string& interface);
/**
+ * @brief Read property value from the specified object and interface
+ * @param[in] bus D-Bus handle
+ * @param[in] service service which has implemented the interface
+ * @param[in] object object having has implemented the interface
+ * @param[in] intf interface having the property
+ * @param[in] prop name of the property to read
+ * @throws sdbusplus::exception::SdBusError if an error occurs in the dbus call
+ * @return property value
+ */
+template <typename T>
+T readDBusProperty(sdbusplus::bus_t& bus, const std::string& service,
+ const std::string& object, const std::string& intf,
+ const std::string& prop)
+{
+ T retVal{};
+ try
+ {
+ auto properties = bus.new_method_call(service.c_str(), object.c_str(),
+ "org.freedesktop.DBus.Properties",
+ "Get");
+ properties.append(intf);
+ properties.append(prop);
+ auto result = bus.call(properties);
+ result.read(retVal);
+ }
+ catch (const std::exception& ex)
+ {
+ lg2::error(
+ "Failed to get the property: {PROPERTY} interface: {INTERFACE} "
+ "object path: {OBJECT_PATH} error: {ERROR} ",
+ "PROPERTY", prop, "INTERFACE", intf, "OBJECT_PATH", object, "ERROR",
+ ex);
+ throw;
+ }
+ return retVal;
+}
+
+/**
+ * @brief Get the state value
+ *
+ * @param[in] intf - Interface to get the value
+ * @param[in] objPath - Object path of the service
+ * @param[in] state - State name to get
+ *
+ * @return The state value as type T on successful retrieval.
+ *
+ * @throws sdbusplus::exception for D-Bus failures and std::bad_variant_access
+ * for invalid value
+ */
+template <typename T>
+T getStateValue(const std::string& intf, const std::string& objPath,
+ const std::string& state)
+{
+ try
+ {
+ auto bus = sdbusplus::bus::new_default();
+ auto service = getService(bus, objPath, intf);
+ return std::get<T>(readDBusProperty<std::variant<T>>(
+ bus, service, objPath, intf, state));
+ }
+ catch (const sdbusplus::exception_t& e)
+ {
+ lg2::error(
+ "D-Bus call exception, OBJPATH: {OBJPATH}, "
+ "INTERFACE: {INTERFACE}, PROPERTY: {PROPERTY}, error: {ERROR}",
+ "OBJPATH", objPath, "INTERFACE", intf, "PROPERTY", state, "ERROR",
+ e);
+ throw;
+ }
+ catch (const std::bad_variant_access& e)
+ {
+ lg2::error("Exception raised while read state: {STATE} property "
+ "value, OBJPATH: {OBJPATH}, INTERFACE: {INTERFACE}, "
+ "error: {ERROR}",
+ "STATE", state, "OBJPATH", objPath, "INTERFACE", intf,
+ "ERROR", e);
+ throw;
+ }
+}
+
+/**
+ * @brief Get the host state
+ *
+ * @return HostState on success
+ *
+ * @throws std::runtime_error - If getting the state property fails
+ */
+inline HostState getHostState()
+{
+ constexpr auto hostStateInterface = "xyz.openbmc_project.State.Host";
+ // TODO Need to change host instance if multiple instead "0"
+ constexpr auto hostStateObjPath = "/xyz/openbmc_project/state/host0";
+ return getStateValue<HostState>(hostStateInterface, hostStateObjPath,
+ "CurrentHostState");
+}
+
+/**
* @brief Get the host boot progress stage
*
* @return BootProgress on success
- * Throw exception on failure
*
+ * @throws std::runtime_error - If getting the state property fails
*/
-BootProgress getBootProgress();
+inline BootProgress getBootProgress()
+{
+ constexpr auto bootProgressInterface =
+ "xyz.openbmc_project.State.Boot.Progress";
+ // TODO Need to change host instance if multiple instead "0"
+ constexpr auto hostStateObjPath = "/xyz/openbmc_project/state/host0";
+ return getStateValue<BootProgress>(bootProgressInterface, hostStateObjPath,
+ "BootProgress");
+}
/**
* @brief Check whether host is running
*
* @return true if the host running else false.
- * Throw exception on failure.
+ *
+ * @throws std::runtime_error - If getting the boot progress failed
*/
-bool isHostRunning();
+inline bool isHostRunning()
+{
+ // TODO #ibm-openbmc/dev/2858 Revisit the method for finding whether host
+ // is running.
+ BootProgress bootProgressStatus = getBootProgress();
+ if ((bootProgressStatus == BootProgress::SystemInitComplete) ||
+ (bootProgressStatus == BootProgress::SystemSetup) ||
+ (bootProgressStatus == BootProgress::OSStart) ||
+ (bootProgressStatus == BootProgress::OSRunning) ||
+ (bootProgressStatus == BootProgress::PCIInit))
+ {
+ return true;
+ }
+ return false;
+}
inline void extractOriginatorProperties(phosphor::dump::DumpCreateParams params,
std::string& originatorId,
@@ -162,5 +288,17 @@
}
}
+/**
+ * @brief Check whether host is quiesced
+ *
+ * @return true if the host is quiesced else false.
+ *
+ * @throws std::runtime_error - If getting the state failed
+ */
+inline bool isHostQuiesced()
+{
+ return (getHostState() == HostState::Quiesced);
+}
+
} // namespace dump
} // namespace phosphor