crit-service: check for bmc quiesce on startup

If the new bmc-bmc-service-quiesce target is entered, then change the
BMC state to Quiesced and do not allow it to change until the BMC is
rebooted out of the failure.

Tested:
- Installed new code on system and started target-monitor with new
  critical services json file as input. Verified that when a critical
  service was killed three times within quick succession, the service
  went into a failed state, the target-monitor detected it, and BMC went
  to Quiesced state.
- Restarted bmc-state manager application while BMC was in Quiesced
  state and verified it rediscovered that upon restart.

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I1096a29e4c244c0d0dfc9829f58fda6e1b2cba35
diff --git a/bmc_state_manager.cpp b/bmc_state_manager.cpp
index 4575a76..9c047c7 100644
--- a/bmc_state_manager.cpp
+++ b/bmc_state_manager.cpp
@@ -30,6 +30,7 @@
 using namespace phosphor::logging;
 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 
+constexpr auto obmcQuiesceTarget = "obmc-bmc-service-quiesce@0.target";
 constexpr auto obmcStandbyTarget = "multi-user.target";
 constexpr auto signalDone = "done";
 constexpr auto activeState = "active";
@@ -88,25 +89,22 @@
 
 void BMC::discoverInitialState()
 {
-    auto currentStateStr = getUnitState(obmcStandbyTarget);
+
+    // First look to see if the BMC quiesce target is active
+    auto currentStateStr = getUnitState(obmcQuiesceTarget);
+    if (currentStateStr == activeState)
+    {
+        info("Setting the BMCState field to BMC_QUIESCED");
+        this->currentBMCState(BMCState::Quiesced);
+        return;
+    }
+
+    // If not quiesced, then check standby target
+    currentStateStr = getUnitState(obmcStandbyTarget);
     if (currentStateStr == activeState)
     {
         info("Setting the BMCState field to BMC_READY");
         this->currentBMCState(BMCState::Ready);
-
-        // Unsubscribe so we stop processing all other signals
-        auto method =
-            this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
-                                      SYSTEMD_INTERFACE, "Unsubscribe");
-        try
-        {
-            this->bus.call(method);
-            this->stateSignal.release();
-        }
-        catch (const sdbusplus::exception::exception& e)
-        {
-            info("Error in Unsubscribe: {ERROR}", "ERROR", e);
-        }
     }
     else
     {
@@ -191,13 +189,13 @@
     // Read the msg and populate each variable
     msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
 
-    // Caught the signal that indicates the BMC is now BMC_READY
-    if ((newStateUnit == obmcStandbyTarget) && (newStateResult == signalDone))
+    if ((newStateUnit == obmcQuiesceTarget) && (newStateResult == signalDone))
     {
-        info("BMC_READY");
-        this->currentBMCState(BMCState::Ready);
+        error("BMC has entered BMC_QUIESCED state");
+        this->currentBMCState(BMCState::Quiesced);
 
-        // Unsubscribe so we stop processing all other signals
+        // There is no getting out of Quiesced once entered (other then BMC
+        // reboot) so stop watching for signals
         auto method =
             this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
                                       SYSTEMD_INTERFACE, "Unsubscribe");
@@ -211,6 +209,15 @@
         {
             info("Error in Unsubscribe: {ERROR}", "ERROR", e);
         }
+
+        return 0;
+    }
+
+    // Caught the signal that indicates the BMC is now BMC_READY
+    if ((newStateUnit == obmcStandbyTarget) && (newStateResult == signalDone))
+    {
+        info("BMC_READY");
+        this->currentBMCState(BMCState::Ready);
     }
 
     return 0;