Refactor: Make createActivation() common

The function is almost the same for ubi and static layout, except a few
differences that creates the ubi objects.

Add below pure virtual functions for ubi to create ubi specific objects
* createActivationObject()
* createVersionObject()

Then it is possible to move most of the code in createActivation() into
the commone one.

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

Change-Id: Ieb3e783bc5b251529a55909f9e9f644230b274e7
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/activation.hpp b/activation.hpp
index 7e8eec5..29ef0e4 100644
--- a/activation.hpp
+++ b/activation.hpp
@@ -180,8 +180,8 @@
      * @param[in] assocs - Association objects
      */
     Activation(sdbusplus::bus::bus& bus, const std::string& path,
-               ItemUpdater& parent, std::string& versionId,
-               std::string& extVersion,
+               ItemUpdater& parent, const std::string& versionId,
+               const std::string& extVersion,
                sdbusplus::xyz::openbmc_project::Software::server::Activation::
                    Activations activationStatus,
                AssociationList& assocs) :
diff --git a/item_updater.cpp b/item_updater.cpp
index 06f3bc8..f321b02 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -4,6 +4,7 @@
 
 #include "xyz/openbmc_project/Common/error.hpp"
 
+#include <filesystem>
 #include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/log.hpp>
 
@@ -13,9 +14,114 @@
 {
 namespace updater
 {
+namespace server = sdbusplus::xyz::openbmc_project::Software::server;
+namespace fs = std::filesystem;
+
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 using namespace phosphor::logging;
 
+void ItemUpdater::createActivation(sdbusplus::message::message& m)
+{
+    using SVersion = server::Version;
+    using VersionPurpose = SVersion::VersionPurpose;
+    namespace msg = sdbusplus::message;
+    namespace variant_ns = msg::variant_ns;
+
+    sdbusplus::message::object_path objPath;
+    std::map<std::string, std::map<std::string, msg::variant<std::string>>>
+        interfaces;
+    m.read(objPath, interfaces);
+
+    std::string path(std::move(objPath));
+    std::string filePath;
+    auto purpose = VersionPurpose::Unknown;
+    std::string version;
+
+    for (const auto& intf : interfaces)
+    {
+        if (intf.first == VERSION_IFACE)
+        {
+            for (const auto& property : intf.second)
+            {
+                if (property.first == "Purpose")
+                {
+                    // Only process the Host and System images
+                    auto value = SVersion::convertVersionPurposeFromString(
+                        variant_ns::get<std::string>(property.second));
+
+                    if (value == VersionPurpose::Host ||
+                        value == VersionPurpose::System)
+                    {
+                        purpose = value;
+                    }
+                }
+                else if (property.first == "Version")
+                {
+                    version = variant_ns::get<std::string>(property.second);
+                }
+            }
+        }
+        else if (intf.first == FILEPATH_IFACE)
+        {
+            for (const auto& property : intf.second)
+            {
+                if (property.first == "Path")
+                {
+                    filePath = variant_ns::get<std::string>(property.second);
+                }
+            }
+        }
+    }
+    if ((filePath.empty()) || (purpose == VersionPurpose::Unknown))
+    {
+        return;
+    }
+
+    // Version id is the last item in the path
+    auto pos = path.rfind("/");
+    if (pos == std::string::npos)
+    {
+        log<level::ERR>("No version id found in object path",
+                        entry("OBJPATH=%s", path.c_str()));
+        return;
+    }
+
+    auto versionId = path.substr(pos + 1);
+
+    if (activations.find(versionId) == activations.end())
+    {
+        // Determine the Activation state by processing the given image dir.
+        auto activationState = server::Activation::Activations::Invalid;
+        AssociationList associations = {};
+        if (validateImage(filePath))
+        {
+            activationState = server::Activation::Activations::Ready;
+            // Create an association to the host inventory item
+            associations.emplace_back(std::make_tuple(
+                ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
+                HOST_INVENTORY_PATH));
+        }
+
+        fs::path manifestPath(filePath);
+        manifestPath /= MANIFEST_FILE;
+        std::string extendedVersion =
+            (Version::getValue(
+                 manifestPath.string(),
+                 std::map<std::string, std::string>{{"extended_version", ""}}))
+                .begin()
+                ->second;
+
+        auto activation = createActivationObject(
+            path, versionId, extendedVersion, activationState, associations);
+        activations.emplace(versionId, std::move(activation));
+
+        auto versionPtr =
+            createVersionObject(path, versionId, version, purpose, filePath);
+        versions.emplace(versionId, std::move(versionPtr));
+    }
+    return;
+}
+
 void ItemUpdater::createActiveAssociation(const std::string& path)
 {
     assocs.emplace_back(
diff --git a/item_updater.hpp b/item_updater.hpp
index 0e4c45c..8b1bf0d 100644
--- a/item_updater.hpp
+++ b/item_updater.hpp
@@ -170,7 +170,27 @@
      *
      * @param[in]  msg       - Data associated with subscribed signal
      */
-    virtual void createActivation(sdbusplus::message::message& msg) = 0;
+    virtual void createActivation(sdbusplus::message::message& msg);
+
+    /** @brief Create Activation object */
+    virtual std::unique_ptr<Activation> createActivationObject(
+        const std::string& path, const std::string& versionId,
+        const std::string& extVersion,
+        sdbusplus::xyz::openbmc_project::Software::server::Activation::
+            Activations activationStatus,
+        AssociationList& assocs) = 0;
+
+    /** @brief Create Version object */
+    virtual std::unique_ptr<Version>
+        createVersionObject(const std::string& objPath,
+                            const std::string& versionId,
+                            const std::string& versionString,
+                            sdbusplus::xyz::openbmc_project::Software::server::
+                                Version::VersionPurpose versionPurpose,
+                            const std::string& filePath) = 0;
+
+    /** @brief Validate if image is valid or not */
+    virtual bool validateImage(const std::string& path) = 0;
 
     /** @brief Persistent sdbusplus D-Bus bus connection. */
     sdbusplus::bus::bus& bus;
diff --git a/ubi/item_updater_ubi.cpp b/ubi/item_updater_ubi.cpp
index f576b3c..875847f 100644
--- a/ubi/item_updater_ubi.cpp
+++ b/ubi/item_updater_ubi.cpp
@@ -35,110 +35,34 @@
 constexpr auto MBOXD_INTERFACE = "org.openbmc.mboxd";
 constexpr auto MBOXD_PATH = "/org/openbmc/mboxd";
 
-void ItemUpdaterUbi::createActivation(sdbusplus::message::message& m)
+std::unique_ptr<Activation> ItemUpdaterUbi::createActivationObject(
+    const std::string& path, const std::string& versionId,
+    const std::string& extVersion,
+    sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations
+        activationStatus,
+    AssociationList& assocs)
 {
-    using SVersion = server::Version;
-    using VersionPurpose = SVersion::VersionPurpose;
-    namespace msg = sdbusplus::message;
-    namespace variant_ns = msg::variant_ns;
+    return std::make_unique<ActivationUbi>(
+        bus, path, *this, versionId, extVersion, activationStatus, assocs);
+}
 
-    sdbusplus::message::object_path objPath;
-    std::map<std::string, std::map<std::string, msg::variant<std::string>>>
-        interfaces;
-    m.read(objPath, interfaces);
+std::unique_ptr<Version> ItemUpdaterUbi::createVersionObject(
+    const std::string& objPath, const std::string& versionId,
+    const std::string& versionString,
+    sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
+        versionPurpose,
+    const std::string& filePath)
+{
+    auto version = std::make_unique<Version>(
+        bus, objPath, *this, versionId, versionString, versionPurpose, filePath,
+        std::bind(&ItemUpdaterUbi::erase, this, std::placeholders::_1));
+    version->deleteObject = std::make_unique<Delete>(bus, objPath, *version);
+    return version;
+}
 
-    std::string path(std::move(objPath));
-    std::string filePath;
-    auto purpose = VersionPurpose::Unknown;
-    std::string version;
-
-    for (const auto& intf : interfaces)
-    {
-        if (intf.first == VERSION_IFACE)
-        {
-            for (const auto& property : intf.second)
-            {
-                if (property.first == "Purpose")
-                {
-                    // Only process the Host and System images
-                    auto value = SVersion::convertVersionPurposeFromString(
-                        variant_ns::get<std::string>(property.second));
-
-                    if (value == VersionPurpose::Host ||
-                        value == VersionPurpose::System)
-                    {
-                        purpose = value;
-                    }
-                }
-                else if (property.first == "Version")
-                {
-                    version = variant_ns::get<std::string>(property.second);
-                }
-            }
-        }
-        else if (intf.first == FILEPATH_IFACE)
-        {
-            for (const auto& property : intf.second)
-            {
-                if (property.first == "Path")
-                {
-                    filePath = variant_ns::get<std::string>(property.second);
-                }
-            }
-        }
-    }
-    if ((filePath.empty()) || (purpose == VersionPurpose::Unknown))
-    {
-        return;
-    }
-
-    // Version id is the last item in the path
-    auto pos = path.rfind("/");
-    if (pos == std::string::npos)
-    {
-        log<level::ERR>("No version id found in object path",
-                        entry("OBJPATH=%s", path.c_str()));
-        return;
-    }
-
-    auto versionId = path.substr(pos + 1);
-
-    if (activations.find(versionId) == activations.end())
-    {
-        // Determine the Activation state by processing the given image dir.
-        auto activationState = server::Activation::Activations::Invalid;
-        AssociationList associations = {};
-        if (validateSquashFSImage(filePath) == 0)
-        {
-            activationState = server::Activation::Activations::Ready;
-            // Create an association to the host inventory item
-            associations.emplace_back(std::make_tuple(
-                ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
-                HOST_INVENTORY_PATH));
-        }
-
-        fs::path manifestPath(filePath);
-        manifestPath /= MANIFEST_FILE;
-        std::string extendedVersion =
-            (Version::getValue(
-                 manifestPath.string(),
-                 std::map<std::string, std::string>{{"extended_version", ""}}))
-                .begin()
-                ->second;
-
-        activations.insert(std::make_pair(
-            versionId, std::make_unique<ActivationUbi>(
-                           bus, path, *this, versionId, extendedVersion,
-                           activationState, associations)));
-
-        auto versionPtr = std::make_unique<Version>(
-            bus, path, *this, versionId, version, purpose, filePath,
-            std::bind(&ItemUpdaterUbi::erase, this, std::placeholders::_1));
-        versionPtr->deleteObject =
-            std::make_unique<Delete>(bus, path, *versionPtr);
-        versions.insert(std::make_pair(versionId, std::move(versionPtr)));
-    }
-    return;
+bool ItemUpdaterUbi::validateImage(const std::string& path)
+{
+    return validateSquashFSImage(path) == 0;
 }
 
 void ItemUpdaterUbi::processPNORImage()
diff --git a/ubi/item_updater_ubi.hpp b/ubi/item_updater_ubi.hpp
index ec9d05c..5de51d3 100644
--- a/ubi/item_updater_ubi.hpp
+++ b/ubi/item_updater_ubi.hpp
@@ -48,12 +48,22 @@
     static std::string determineId(const std::string& symlinkPath);
 
   private:
-    /** @brief Callback function for Software.Version match.
-     *  @details Creates an Activation D-Bus object.
-     *
-     * @param[in]  msg       - Data associated with subscribed signal
-     */
-    void createActivation(sdbusplus::message::message& msg) override;
+    std::unique_ptr<Activation> createActivationObject(
+        const std::string& path, const std::string& versionId,
+        const std::string& extVersion,
+        sdbusplus::xyz::openbmc_project::Software::server::Activation::
+            Activations activationStatus,
+        AssociationList& assocs) override;
+
+    std::unique_ptr<Version>
+        createVersionObject(const std::string& objPath,
+                            const std::string& versionId,
+                            const std::string& versionString,
+                            sdbusplus::xyz::openbmc_project::Software::server::
+                                Version::VersionPurpose versionPurpose,
+                            const std::string& filePath) override;
+
+    bool validateImage(const std::string& path) override;
 
     /** @brief Host factory reset - clears PNOR partitions for each
      * Activation D-Bus object */