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-extensions/openpower-dumps/dump_manager_system.cpp b/dump-extensions/openpower-dumps/dump_manager_system.cpp
index 2aaa35e..23d1994 100644
--- a/dump-extensions/openpower-dumps/dump_manager_system.cpp
+++ b/dump-extensions/openpower-dumps/dump_manager_system.cpp
@@ -69,9 +69,9 @@
     if (upEntry != nullptr)
     {
         log<level::INFO>(
-            fmt::format(
-                "System Dump Notify: Updating dumpId({}) Id({}) Size({})",
-                upEntry->getDumpId(), dumpId, size)
+            fmt::format("System Dump Notify: Updating dump entry with Id({}) "
+                        "with source  Id({}) and Size({})",
+                        upEntry->getDumpId(), dumpId, size)
                 .c_str());
         upEntry->update(timeStamp, size, dumpId);
         return;
@@ -86,10 +86,11 @@
     // For now replacing it with null
     try
     {
-        log<level::INFO>(fmt::format("System Dump Notify: creating new dump "
-                                     "entry dumpId({}) Id({}) Size({})",
-                                     id, dumpId, size)
-                             .c_str());
+        log<level::INFO>(
+            fmt::format("System Dump Notify: creating new dump "
+                        "entry with dumpId({}) with source Id({}) and Size({})",
+                        id, dumpId, size)
+                .c_str());
         entries.insert(std::make_pair(
             id, std::make_unique<system::Entry>(
                     bus, objPath.c_str(), id, timeStamp, size, dumpId,
@@ -130,7 +131,8 @@
     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
 
     // Allow creating system dump only when the host is up.
-    if (!phosphor::dump::isHostRunning())
+    if (!(((phosphor::dump::isHostRunning()) ||
+           (phosphor::dump::isHostQuiesced()))))
     {
         elog<NotAllowed>(
             Reason("System dump can be initiated only when the host is up"));
diff --git a/dump_utils.cpp b/dump_utils.cpp
index 830cce5..45f4153 100644
--- a/dump_utils.cpp
+++ b/dump_utils.cpp
@@ -55,19 +55,37 @@
         "xyz.openbmc_project.State.Boot.Progress";
     // TODO Need to change host instance if multiple instead "0"
     constexpr auto hostStateObjPath = "/xyz/openbmc_project/state/host0";
+    auto value =
+        getStateValue(bootProgressInterface, hostStateObjPath, "BootProgress");
+    return sdbusplus::xyz::openbmc_project::State::Boot::server::Progress::
+        convertProgressStagesFromString(value);
+}
 
-    BootProgress bootProgessStage;
+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";
+    auto value =
+        getStateValue(hostStateInterface, hostStateObjPath, "CurrentHostState");
+    return sdbusplus::xyz::openbmc_project::State::server::Host::
+        convertHostStateFromString(value);
+}
 
+std::string getStateValue(const std::string& intf, const std::string& objPath,
+                          const std::string& state)
+{
+    std::string stateVal;
     try
     {
         auto bus = sdbusplus::bus::new_default();
-        auto service = getService(bus, hostStateObjPath, bootProgressInterface);
+        auto service = getService(bus, objPath, intf);
 
         auto method =
-            bus.new_method_call(service.c_str(), hostStateObjPath,
+            bus.new_method_call(service.c_str(), objPath.c_str(),
                                 "org.freedesktop.DBus.Properties", "Get");
 
-        method.append(bootProgressInterface, "BootProgress");
+        method.append(intf, state);
 
         auto reply = bus.call(method);
 
@@ -78,32 +96,27 @@
 
         reply.read(propertyVal);
 
-        // BootProgress property type is string
-        std::string bootPgs(std::get<std::string>(propertyVal));
-
-        bootProgessStage = sdbusplus::xyz::openbmc_project::State::Boot::
-            server::Progress::convertProgressStagesFromString(bootPgs);
+        stateVal = std::get<std::string>(propertyVal);
     }
     catch (const sdbusplus::exception_t& e)
     {
         log<level::ERR>(fmt::format("D-Bus call exception, OBJPATH({}), "
-                                    "INTERFACE({}), EXCEPTION({})",
-                                    hostStateObjPath, bootProgressInterface,
-                                    e.what())
+                                    "INTERFACE({}), PROPERTY({}) EXCEPTION({})",
+                                    objPath, intf, state, e.what())
                             .c_str());
-        throw std::runtime_error("Failed to get BootProgress stage");
+        throw std::runtime_error("Failed to get state property");
     }
     catch (const std::bad_variant_access& e)
     {
         log<level::ERR>(
-            fmt::format("Exception raised while read BootProgress property "
+            fmt::format("Exception raised while read host state({}) property "
                         "value,  OBJPATH({}), INTERFACE({}), EXCEPTION({})",
-                        hostStateObjPath, bootProgressInterface, e.what())
+                        state, objPath, intf, e.what())
                 .c_str());
-        throw std::runtime_error("Failed to get BootProgress stage");
+        throw std::runtime_error("Failed to get host state property");
     }
 
-    return bootProgessStage;
+    return stateVal;
 }
 
 bool isHostRunning()
@@ -121,5 +134,10 @@
     }
     return false;
 }
+
+bool isHostQuiesced()
+{
+    return (phosphor::dump::getHostState() == HostState::Quiesced);
+}
 } // namespace dump
 } // namespace phosphor
diff --git a/dump_utils.hpp b/dump_utils.hpp
index 83952a3..82fff10 100644
--- a/dump_utils.hpp
+++ b/dump_utils.hpp
@@ -12,6 +12,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>
 
@@ -22,6 +23,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;
@@ -86,6 +89,15 @@
                        const std::string& interface);
 
 /**
+ * @brief Get the host state
+ *
+ * @return HostState on success
+ *         Throw exception on failure
+ *
+ */
+HostState getHostState();
+
+/**
  * @brief Get the host boot progress stage
  *
  * @return BootProgress on success
@@ -95,6 +107,19 @@
 BootProgress getBootProgress();
 
 /**
+ * @brief Get the host 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 on success
+ *         Throw exception on failure
+ */
+std::string getStateValue(const std::string& intf, const std::string& objPath,
+                          const std::string& state);
+
+/**
  * @brief Check whether host is running
  *
  * @return true if the host running else false.
@@ -169,5 +194,13 @@
     }
 }
 
+/**
+ * @brief Check whether host is quiesced
+ *
+ * @return true if the host is quiesced else false.
+ *         Throw exception on failure.
+ */
+bool isHostQuiesced();
+
 } // namespace dump
 } // namespace phosphor