BMC Activation: Implement ActivationProgress interface

This commit extends the BMC activation progress by implementing the
generic ActivationProgress interface, in order to periodically update
the user with the current status of the process.

Dependent on openbmc/openbmc#2031 to avoid crashes in multiple image
scenarios.

Resolves openbmc/openbmc#2030

Change-Id: If52426ea1eae93f32166a255072f813d6a056172
Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
diff --git a/activation.cpp b/activation.cpp
index 2a8c122..64fd53e 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -46,6 +46,12 @@
     {
         if (rwVolumeCreated == false && roVolumeCreated == false)
         {
+            if (!activationProgress)
+            {
+                activationProgress = std::make_unique<ActivationProgress>(bus,
+                        path);
+            }
+
             if (!activationBlocksTransition)
             {
                 activationBlocksTransition =
@@ -71,9 +77,13 @@
                     "StartUnit");
             method.append(roServiceFile, "replace");
             bus.call_noreply(method);
+
+            activationProgress->progress(10);
         }
         else if (rwVolumeCreated == true && roVolumeCreated == true)
         {
+            activationProgress->progress(90);
+
             if (!redundancyPriority)
             {
                 redundancyPriority =
@@ -84,7 +94,10 @@
                                     0);
             }
 
+            activationProgress->progress(100);
+
             activationBlocksTransition.reset(nullptr);
+            activationProgress.reset(nullptr);
 
             rwVolumeCreated = false;
             roVolumeCreated = false;
@@ -97,6 +110,7 @@
     else
     {
         activationBlocksTransition.reset(nullptr);
+        activationProgress.reset(nullptr);
     }
     return softwareServer::Activation::activation(value);
 }
@@ -132,6 +146,12 @@
 
 void Activation::unitStateChange(sdbusplus::message::message& msg)
 {
+    if (softwareServer::Activation::activation() !=
+                softwareServer::Activation::Activations::Activating)
+    {
+        return;
+    }
+
     uint32_t newStateID {};
     sdbusplus::message::object_path newStateObjPath;
     std::string newStateUnit{};
@@ -146,11 +166,13 @@
     if(newStateUnit == rwServiceFile && newStateResult == "done")
     {
         rwVolumeCreated = true;
+        activationProgress->progress(activationProgress->progress() + 20);
     }
 
     if(newStateUnit == roServiceFile && newStateResult == "done")
     {
         roVolumeCreated = true;
+        activationProgress->progress(activationProgress->progress() + 50);
     }
 
     if(rwVolumeCreated && roVolumeCreated)
diff --git a/activation.hpp b/activation.hpp
index 1e91759..b3ec44b 100644
--- a/activation.hpp
+++ b/activation.hpp
@@ -4,6 +4,7 @@
 #include <xyz/openbmc_project/Software/Activation/server.hpp>
 #include <xyz/openbmc_project/Software/ActivationBlocksTransition/server.hpp>
 #include "xyz/openbmc_project/Software/RedundancyPriority/server.hpp"
+#include "xyz/openbmc_project/Software/ActivationProgress/server.hpp"
 
 namespace phosphor
 {
@@ -18,6 +19,8 @@
  sdbusplus::xyz::openbmc_project::Software::server::ActivationBlocksTransition>;
 using RedundancyPriorityInherit = sdbusplus::server::object::object<
     sdbusplus::xyz::openbmc_project::Software::server::RedundancyPriority>;
+using ActivationProgressInherit = sdbusplus::server::object::object<
+    sdbusplus::xyz::openbmc_project::Software::server::ActivationProgress>;
 
 namespace sdbusRule = sdbusplus::bus::match::rules;
 
@@ -90,6 +93,23 @@
                    ActivationBlocksTransitionInherit(bus, path.c_str()) {}
 };
 
+class ActivationProgress : public ActivationProgressInherit
+{
+    public:
+        /** @brief Constructs ActivationProgress.
+          *
+          * @param[in] bus    - The Dbus bus object
+          * @param[in] path   - The Dbus object path
+          */
+        ActivationProgress(sdbusplus::bus::bus& bus,
+                           const std::string& path) :
+                ActivationProgressInherit(bus, path.c_str(), true)
+        {
+            progress(0);
+            emit_object_added();
+        }
+};
+
 /** @class Activation
  *  @brief OpenBMC activation software management implementation.
  *  @details A concrete implementation for
@@ -201,6 +221,9 @@
         /** @brief Persistent RedundancyPriority dbus object */
         std::unique_ptr<RedundancyPriority> redundancyPriority;
 
+        /** @brief Persistent ActivationProgress dbus object */
+        std::unique_ptr<ActivationProgress> activationProgress;
+
         /** @brief Used to subscribe to dbus systemd signals **/
         sdbusplus::bus::match_t systemdSignals;