Refactor: Split Activation into common and ubi

Activations has a few functions coupled with ubi, split them into
ubi/activation_ubi

* Keep common code in activation.
* Make start/finishActivation() pure virtual.
* Move ubi specific code into ubi.
* Move ubiVolumnCreated into ubi.
* Make validateSignature() not inline, otherwise it gets compile error.

Tested: On the last commit of the patch series, run code update and
        factory reset on Witherspoon and all work fine.

Change-Id: I7c8a0de6b0be4b1e9814ea75fd802a014b4aacfc
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/activation.cpp b/activation.cpp
index 52427f0..1660572 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -78,129 +78,9 @@
     return;
 }
 
-void Activation::startActivation()
-{
-    // Since the squashfs image has not yet been loaded to pnor and the
-    // RW volumes have not yet been created, we need to start the
-    // service files for each of those actions.
-
-    if (!activationProgress)
-    {
-        activationProgress = std::make_unique<ActivationProgress>(bus, path);
-    }
-
-    if (!activationBlocksTransition)
-    {
-        activationBlocksTransition =
-            std::make_unique<ActivationBlocksTransition>(bus, path);
-    }
-
-    constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
-    auto ubimountServiceFile =
-        std::string(ubimountService) + versionId + ".service";
-    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
-                                      SYSTEMD_INTERFACE, "StartUnit");
-    method.append(ubimountServiceFile, "replace");
-    bus.call_noreply(method);
-
-    activationProgress->progress(10);
-}
-
-void Activation::finishActivation()
-{
-    activationProgress->progress(90);
-
-    // Set Redundancy Priority before setting to Active
-    if (!redundancyPriority)
-    {
-        redundancyPriority =
-            std::make_unique<RedundancyPriority>(bus, path, *this, 0);
-    }
-
-    activationProgress->progress(100);
-
-    activationBlocksTransition.reset(nullptr);
-    activationProgress.reset(nullptr);
-
-    ubiVolumesCreated = false;
-    Activation::unsubscribeFromSystemdSignals();
-    // Remove version object from image manager
-    Activation::deleteImageManagerObject();
-    // Create active association
-    parent.createActiveAssociation(path);
-}
-
-auto Activation::activation(Activations value) -> Activations
-{
-
-    if (value != softwareServer::Activation::Activations::Active)
-    {
-        redundancyPriority.reset(nullptr);
-    }
-
-    if (value == softwareServer::Activation::Activations::Activating)
-    {
-        parent.freeSpace();
-        softwareServer::Activation::activation(value);
-
-        if (ubiVolumesCreated == false)
-        {
-            // Enable systemd signals
-            Activation::subscribeToSystemdSignals();
-
-#ifdef WANT_SIGNATURE_VERIFY
-            // Validate the signed image.
-            if (!validateSignature())
-            {
-                // Cleanup
-                activationBlocksTransition.reset(nullptr);
-                activationProgress.reset(nullptr);
-
-                return softwareServer::Activation::activation(
-                    softwareServer::Activation::Activations::Failed);
-            }
-#endif
-            Activation::startActivation();
-            return softwareServer::Activation::activation(value);
-        }
-        else if (ubiVolumesCreated == true)
-        {
-            // Only when the squashfs image is finished loading AND the RW
-            // volumes have been created do we proceed with activation. To
-            // verify that this happened, we check for the mount dirs PNOR_PRSV
-            // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0.
-
-            if ((fs::is_directory(PNOR_PRSV)) &&
-                (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
-                (fs::is_directory(PNOR_RO_PREFIX + versionId)))
-            {
-                Activation::finishActivation();
-                return softwareServer::Activation::activation(
-                    softwareServer::Activation::Activations::Active);
-            }
-            else
-            {
-                activationBlocksTransition.reset(nullptr);
-                activationProgress.reset(nullptr);
-                return softwareServer::Activation::activation(
-                    softwareServer::Activation::Activations::Failed);
-            }
-        }
-    }
-    else
-    {
-        activationBlocksTransition.reset(nullptr);
-        activationProgress.reset(nullptr);
-    }
-
-    return softwareServer::Activation::activation(value);
-}
-
 auto Activation::requestedActivation(RequestedActivations value)
     -> RequestedActivations
 {
-    ubiVolumesCreated = false;
-
     if ((value == softwareServer::Activation::RequestedActivations::Active) &&
         (softwareServer::Activation::requestedActivation() !=
          softwareServer::Activation::RequestedActivations::Active))
@@ -294,46 +174,11 @@
 uint8_t RedundancyPriority::priority(uint8_t value)
 {
     parent.parent.freePriority(value, parent.versionId);
-    storeToFile(parent.versionId, value);
     return softwareServer::RedundancyPriority::priority(value);
 }
 
-void Activation::unitStateChange(sdbusplus::message::message& msg)
-{
-    uint32_t newStateID{};
-    sdbusplus::message::object_path newStateObjPath;
-    std::string newStateUnit{};
-    std::string newStateResult{};
-
-    // Read the msg and populate each variable
-    msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
-
-    auto ubimountServiceFile =
-        "obmc-flash-bios-ubimount@" + versionId + ".service";
-
-    if (newStateUnit == ubimountServiceFile && newStateResult == "done")
-    {
-        ubiVolumesCreated = true;
-        activationProgress->progress(activationProgress->progress() + 50);
-    }
-
-    if (ubiVolumesCreated)
-    {
-        Activation::activation(
-            softwareServer::Activation::Activations::Activating);
-    }
-
-    if ((newStateUnit == ubimountServiceFile) &&
-        (newStateResult == "failed" || newStateResult == "dependency"))
-    {
-        Activation::activation(softwareServer::Activation::Activations::Failed);
-    }
-
-    return;
-}
-
 #ifdef WANT_SIGNATURE_VERIFY
-inline bool Activation::validateSignature()
+bool Activation::validateSignature()
 {
     using Signature = openpower::software::image::Signature;
     fs::path imageDir(IMG_DIR);
diff --git a/activation.hpp b/activation.hpp
index 2fc08d7..7e8eec5 100644
--- a/activation.hpp
+++ b/activation.hpp
@@ -64,7 +64,7 @@
         bus.emit_interfaces_added(path.c_str(), interfaces);
     }
 
-    ~RedundancyPriority()
+    virtual ~RedundancyPriority()
     {
         std::vector<std::string> interfaces({interface});
         bus.emit_interfaces_removed(path.c_str(), interfaces);
@@ -203,6 +203,7 @@
         // Emit deferred signal.
         emit_object_added();
     }
+    virtual ~Activation() = default;
 
     /** @brief Activation property get function
      *
@@ -210,14 +211,6 @@
      */
     using ActivationInherit::activation;
 
-    /** @brief Overloaded Activation property setter function
-     *
-     *  @param[in] value - One of Activation::Activations
-     *
-     *  @return Success or exception thrown
-     */
-    Activations activation(Activations value) override;
-
     /** @brief Overloaded requestedActivation property setter function
      *
      *  @param[in] value - One of Activation::RequestedActivations
@@ -227,16 +220,6 @@
     RequestedActivations
         requestedActivation(RequestedActivations value) override;
 
-    /** @brief Check if systemd state change is relevant to this object
-     *
-     * Instance specific interface to handle the detected systemd state
-     * change
-     *
-     * @param[in]  msg       - Data associated with subscribed signal
-     *
-     */
-    void unitStateChange(sdbusplus::message::message& msg);
-
     /**
      * @brief subscribe to the systemd signals
      *
@@ -279,17 +262,23 @@
     /** @brief Used to subscribe to dbus systemd signals **/
     sdbusplus::bus::match_t systemdSignals;
 
-    /** @brief Tracks whether the read-only & read-write volumes have been
-     *created as part of the activation process. **/
-    bool ubiVolumesCreated = false;
-
     /** @brief activation status property get function
      *
      * @returns Activations - The activation value
      */
     using ActivationInherit::activation;
 
-  private:
+  protected:
+    /** @brief Check if systemd state change is relevant to this object
+     *
+     * Instance specific interface to handle the detected systemd state
+     * change
+     *
+     * @param[in]  msg       - Data associated with subscribed signal
+     *
+     */
+    virtual void unitStateChange(sdbusplus::message::message& msg) = 0;
+
     /**
      * @brief Deletes the version from Image Manager and the
      *        untar image from image upload dir.
@@ -297,10 +286,10 @@
     void deleteImageManagerObject();
 
     /** @brief Member function for clarity & brevity at activation start */
-    void startActivation();
+    virtual void startActivation() = 0;
 
     /** @brief Member function for clarity & brevity at activation end */
-    void finishActivation();
+    virtual void finishActivation() = 0;
 
 #ifdef WANT_SIGNATURE_VERIFY
     /**
@@ -315,7 +304,7 @@
      *          false for unsuccessful signature validation or
      *          any internal failure during the mapper call.
      */
-    inline bool validateSignature();
+    bool validateSignature();
 
     /**
      * @brief Gets the fieldModeEnabled property value.
diff --git a/ubi/Makefile.am.include b/ubi/Makefile.am.include
index a836661..c75293d 100644
--- a/ubi/Makefile.am.include
+++ b/ubi/Makefile.am.include
@@ -1,3 +1,4 @@
 openpower_update_manager_SOURCES += \
+	%reldir%/activation_ubi.cpp \
 	%reldir%/item_updater_ubi.cpp \
 	%reldir%/watch.cpp
diff --git a/ubi/activation_ubi.cpp b/ubi/activation_ubi.cpp
new file mode 100644
index 0000000..9ce7085
--- /dev/null
+++ b/ubi/activation_ubi.cpp
@@ -0,0 +1,183 @@
+#include "activation_ubi.hpp"
+
+#include "item_updater.hpp"
+#include "serialize.hpp"
+
+#include <experimental/filesystem>
+
+namespace openpower
+{
+namespace software
+{
+namespace updater
+{
+namespace fs = std::experimental::filesystem;
+namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
+
+uint8_t RedundancyPriorityUbi::priority(uint8_t value)
+{
+    storeToFile(parent.versionId, value);
+    return RedundancyPriority::priority(value);
+}
+
+auto ActivationUbi::activation(Activations value) -> Activations
+{
+
+    if (value != softwareServer::Activation::Activations::Active)
+    {
+        redundancyPriority.reset(nullptr);
+    }
+
+    if (value == softwareServer::Activation::Activations::Activating)
+    {
+        parent.freeSpace();
+        softwareServer::Activation::activation(value);
+
+        if (ubiVolumesCreated == false)
+        {
+            // Enable systemd signals
+            subscribeToSystemdSignals();
+
+#ifdef WANT_SIGNATURE_VERIFY
+            // Validate the signed image.
+            if (!validateSignature())
+            {
+                // Cleanup
+                activationBlocksTransition.reset(nullptr);
+                activationProgress.reset(nullptr);
+
+                return softwareServer::Activation::activation(
+                    softwareServer::Activation::Activations::Failed);
+            }
+#endif
+            startActivation();
+            return softwareServer::Activation::activation(value);
+        }
+        else if (ubiVolumesCreated == true)
+        {
+            // Only when the squashfs image is finished loading AND the RW
+            // volumes have been created do we proceed with activation. To
+            // verify that this happened, we check for the mount dirs PNOR_PRSV
+            // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0.
+
+            if ((fs::is_directory(PNOR_PRSV)) &&
+                (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
+                (fs::is_directory(PNOR_RO_PREFIX + versionId)))
+            {
+                finishActivation();
+                return softwareServer::Activation::activation(
+                    softwareServer::Activation::Activations::Active);
+            }
+            else
+            {
+                activationBlocksTransition.reset(nullptr);
+                activationProgress.reset(nullptr);
+                return softwareServer::Activation::activation(
+                    softwareServer::Activation::Activations::Failed);
+            }
+        }
+    }
+    else
+    {
+        activationBlocksTransition.reset(nullptr);
+        activationProgress.reset(nullptr);
+    }
+
+    return softwareServer::Activation::activation(value);
+}
+
+auto ActivationUbi::requestedActivation(RequestedActivations value)
+    -> RequestedActivations
+{
+    ubiVolumesCreated = false;
+    return Activation::requestedActivation(value);
+}
+
+void ActivationUbi::startActivation()
+{
+    // Since the squashfs image has not yet been loaded to pnor and the
+    // RW volumes have not yet been created, we need to start the
+    // service files for each of those actions.
+
+    if (!activationProgress)
+    {
+        activationProgress = std::make_unique<ActivationProgress>(bus, path);
+    }
+
+    if (!activationBlocksTransition)
+    {
+        activationBlocksTransition =
+            std::make_unique<ActivationBlocksTransition>(bus, path);
+    }
+
+    constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
+    auto ubimountServiceFile =
+        std::string(ubimountService) + versionId + ".service";
+    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+                                      SYSTEMD_INTERFACE, "StartUnit");
+    method.append(ubimountServiceFile, "replace");
+    bus.call_noreply(method);
+
+    activationProgress->progress(10);
+}
+
+void ActivationUbi::unitStateChange(sdbusplus::message::message& msg)
+{
+    uint32_t newStateID{};
+    sdbusplus::message::object_path newStateObjPath;
+    std::string newStateUnit{};
+    std::string newStateResult{};
+
+    // Read the msg and populate each variable
+    msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+    auto ubimountServiceFile =
+        "obmc-flash-bios-ubimount@" + versionId + ".service";
+
+    if (newStateUnit == ubimountServiceFile && newStateResult == "done")
+    {
+        ubiVolumesCreated = true;
+        activationProgress->progress(activationProgress->progress() + 50);
+    }
+
+    if (ubiVolumesCreated)
+    {
+        activation(softwareServer::Activation::Activations::Activating);
+    }
+
+    if ((newStateUnit == ubimountServiceFile) &&
+        (newStateResult == "failed" || newStateResult == "dependency"))
+    {
+        activation(softwareServer::Activation::Activations::Failed);
+    }
+
+    return;
+}
+
+void ActivationUbi::finishActivation()
+{
+    activationProgress->progress(90);
+
+    // Set Redundancy Priority before setting to Active
+    if (!redundancyPriority)
+    {
+        redundancyPriority =
+            std::make_unique<RedundancyPriorityUbi>(bus, path, *this, 0);
+    }
+
+    activationProgress->progress(100);
+
+    activationBlocksTransition.reset(nullptr);
+    activationProgress.reset(nullptr);
+
+    ubiVolumesCreated = false;
+    unsubscribeFromSystemdSignals();
+    // Remove version object from image manager
+    deleteImageManagerObject();
+    // Create active association
+    parent.createActiveAssociation(path);
+}
+
+} // namespace updater
+} // namespace software
+} // namespace openpower
diff --git a/ubi/activation_ubi.hpp b/ubi/activation_ubi.hpp
new file mode 100644
index 0000000..a17bb82
--- /dev/null
+++ b/ubi/activation_ubi.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "activation.hpp"
+
+namespace openpower
+{
+namespace software
+{
+namespace updater
+{
+
+class RedundancyPriorityUbi : public RedundancyPriority
+{
+  public:
+    using RedundancyPriority::RedundancyPriority;
+    virtual ~RedundancyPriorityUbi() = default;
+
+    /** @brief Overloaded Priority property set function
+     *
+     *  @param[in] value - uint8_t
+     *
+     *  @return Success or exception thrown
+     */
+    uint8_t priority(uint8_t value) override;
+};
+
+/** @class ActivationUbi
+ *  @brief OpenBMC activation software management implementation.
+ *  @details A concrete implementation for
+ *  xyz.openbmc_project.Software.Activation DBus API.
+ */
+class ActivationUbi : public Activation
+{
+  public:
+    using Activation::Activation;
+    virtual ~ActivationUbi() = default;
+
+    /** @brief Overloaded Activation property setter function
+     *
+     *  @param[in] value - One of Activation::Activations
+     *
+     *  @return Success or exception thrown
+     */
+    Activations activation(Activations value) override;
+
+    RequestedActivations
+        requestedActivation(RequestedActivations value) override;
+
+  private:
+    /** @brief Tracks whether the read-only & read-write volumes have been
+     *created as part of the activation process. **/
+    bool ubiVolumesCreated = false;
+
+    void unitStateChange(sdbusplus::message::message& msg) override;
+    void startActivation() override;
+    void finishActivation() override;
+};
+
+} // namespace updater
+} // namespace software
+} // namespace openpower
diff --git a/ubi/item_updater_ubi.cpp b/ubi/item_updater_ubi.cpp
index 7a64244..f576b3c 100644
--- a/ubi/item_updater_ubi.cpp
+++ b/ubi/item_updater_ubi.cpp
@@ -2,7 +2,7 @@
 
 #include "item_updater_ubi.hpp"
 
-#include "activation.hpp"
+#include "activation_ubi.hpp"
 #include "serialize.hpp"
 #include "version.hpp"
 #include "xyz/openbmc_project/Common/error.hpp"
@@ -127,7 +127,7 @@
                 ->second;
 
         activations.insert(std::make_pair(
-            versionId, std::make_unique<Activation>(
+            versionId, std::make_unique<ActivationUbi>(
                            bus, path, *this, versionId, extendedVersion,
                            activationState, associations)));
 
@@ -202,7 +202,7 @@
 
             // Create Activation instance for this version.
             activations.insert(
-                std::make_pair(id, std::make_unique<Activation>(
+                std::make_pair(id, std::make_unique<ActivationUbi>(
                                        bus, path, *this, id, extendedVersion,
                                        activationState, associations)));
 
@@ -216,7 +216,7 @@
                                     entry("VERSIONID=%s", id.c_str()));
                 }
                 activations.find(id)->second->redundancyPriority =
-                    std::make_unique<RedundancyPriority>(
+                    std::make_unique<RedundancyPriorityUbi>(
                         bus, path, *(activations.find(id)->second), priority);
             }