PNOR: Fix the delete implementation

- In order to remove the delete object from functional
  image, the delete interface is moved inside the
  version class so that both item_updater and image_manager
  can make use of the same implementation.
- To avoid having two delete objects attached to the same
  HOST version (item_updater and image_manager), we are now
  deleting the image_manager object once the activation
  is complete.

Partially resolves openbmc/openbmc#2490

Change-Id: Ie515cc01d5f154e6e55b9a3fb71d831730cd46f6
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
diff --git a/version.hpp b/version.hpp
index 8cb7e37..13b42ea 100644
--- a/version.hpp
+++ b/version.hpp
@@ -3,6 +3,8 @@
 #include <sdbusplus/bus.hpp>
 #include "xyz/openbmc_project/Software/Version/server.hpp"
 #include "xyz/openbmc_project/Common/FilePath/server.hpp"
+#include "xyz/openbmc_project/Object/Delete/server.hpp"
+#include "config.h"
 
 namespace openpower
 {
@@ -13,9 +15,69 @@
 
 class ItemUpdater;
 
+typedef std::function<void(std::string)> eraseFunc;
+
 using VersionInherit = sdbusplus::server::object::object<
         sdbusplus::xyz::openbmc_project::Software::server::Version,
         sdbusplus::xyz::openbmc_project::Common::server::FilePath>;
+using DeleteInherit = sdbusplus::server::object::object<
+        sdbusplus::xyz::openbmc_project::Object::server::Delete>;
+
+namespace sdbusRule = sdbusplus::bus::match::rules;
+
+class Delete;
+class Version;
+
+/** @class Delete
+ *  @brief OpenBMC Delete implementation.
+ *  @details A concrete implementation for xyz.openbmc_project.Object.Delete
+ *  D-Bus API.
+*/
+class Delete : public DeleteInherit
+{
+    public:
+        /** @brief Constructs Delete.
+         *
+         *  @param[in] bus    - The D-Bus bus object
+         *  @param[in] path   - The D-Bus object path
+         *  @param[in] parent - Parent object.
+         */
+        Delete(sdbusplus::bus::bus& bus,
+               const std::string& path,
+               Version& parent) :
+                DeleteInherit(bus, path.c_str(), true),
+                parent(parent),
+                bus(bus),
+                path(path)
+        {
+            std::vector<std::string> interfaces({interface});
+            bus.emit_interfaces_added(path.c_str(), interfaces);
+        }
+
+        ~Delete()
+        {
+            std::vector<std::string> interfaces({interface});
+            bus.emit_interfaces_removed(path.c_str(), interfaces);
+        }
+
+        /**
+         * @brief Delete the D-Bus object.
+         *        Overrides the default delete function by calling
+         *        Version class erase Method.
+         **/
+        void delete_() override;
+
+    private:
+
+        /** @brief Parent Object. */
+        Version& parent;
+
+        // TODO Remove once openbmc/openbmc#1975 is resolved
+        static constexpr auto interface =
+                "xyz.openbmc_project.Object.Delete";
+        sdbusplus::bus::bus& bus;
+        std::string path;
+};
 
 /** @class Version
  *  @brief OpenBMC version software management implementation.
@@ -29,17 +91,39 @@
          *
          * @param[in] bus            - The D-Bus bus object
          * @param[in] objPath        - The D-Bus object path
+         * @param[in] parent         - Parent object.
+         * @param[in] versionId      - The version Id
          * @param[in] versionString  - The version string
          * @param[in] versionPurpose - The version purpose
          * @param[in] filePath       - The image filesystem path
+         * @param[in] callback       - The eraseFunc callback
          */
         Version(sdbusplus::bus::bus& bus,
                 const std::string& objPath,
+                ItemUpdater& parent,
+                const std::string& versionId,
                 const std::string& versionString,
                 VersionPurpose versionPurpose,
-                const std::string& filePath) :
-                        VersionInherit(bus, (objPath).c_str(), true)
+                const std::string& filePath, eraseFunc callback) :
+                        VersionInherit(bus, (objPath).c_str(), true),
+                        bus(bus),
+                        objPath(objPath),
+                        parent(parent),
+                        versionId(versionId),
+                        versionStr(versionString),
+                chassisStateSignals(
+                          bus,
+                          sdbusRule::type::signal() +
+                          sdbusRule::member("PropertiesChanged") +
+                          sdbusRule::path(CHASSIS_STATE_PATH) +
+                          sdbusRule::argN(0, CHASSIS_STATE_OBJ) +
+                          sdbusRule::interface(SYSTEMD_PROPERTY_INTERFACE),
+                          std::bind(std::mem_fn(
+                                  &Version::updateDeleteInterface), this,
+                                  std::placeholders::_1))
         {
+            // Bind erase method
+            eraseCallback = callback;
             // Set properties.
             purpose(versionPurpose);
             version(versionString);
@@ -50,6 +134,18 @@
         }
 
         /**
+         * @brief Update the Object.Delete interface for this activation
+         *
+         *        Update the delete interface based on whether or not this
+         *        activation is currently functional. A functional activation
+         *        will have no Object.Delete, while a non-functional activation
+         *        will have one.
+         *
+         * @param[in]  msg       - Data associated with subscribed signal
+         */
+        void updateDeleteInterface(sdbusplus::message::message& msg);
+
+        /**
          * @brief Read the manifest file to get the value of the key.
          *
          * @param[in] filePath - The path to the file which contains the value
@@ -73,6 +169,32 @@
          * @return The id.
          */
         static std::string getId(const std::string& version);
+
+        /** @brief Persistent Delete D-Bus object */
+        std::unique_ptr<Delete> deleteObject;
+
+        /** @brief The parent's erase callback. */
+        eraseFunc eraseCallback;
+
+    private:
+        /** @brief Persistent sdbusplus DBus bus connection */
+        sdbusplus::bus::bus& bus;
+
+        /** @brief Persistent DBus object path */
+        std::string objPath;
+
+        /** @brief Parent Object. */
+        ItemUpdater& parent;
+
+        /** @brief This Version's version Id */
+        const std::string versionId;
+
+        /** @brief This Version's version string */
+        const std::string versionStr;
+
+        /** @brief Used to subscribe to chassis power state changes **/
+        sdbusplus::bus::match_t chassisStateSignals;
+
 };
 
 } // namespace updater