Limit the number of Active pnor versions

- We need to limit the number of pnor versions because
  pnor chip has limited space. If we run out of space
  and the user tries another pnor code update then the
  update will fail.
- Currently we can only hold two images on pnor at this
  point. As we continue to decrease the size of pnor image
  we will increment the number of active pnor chips we can
  hold.
- This check will need to be removed once we have complete
  issue #1402 which will automatically monitor the flash
  usage and delete any image accordingly.

Resolves openbmc/openbmc#2155

Change-Id: Id62ba8554fba1ddb78286f70b0c3482a7beb8a6b
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
diff --git a/activation.cpp b/activation.cpp
index 55ce08e..3f16b7b 100755
--- a/activation.cpp
+++ b/activation.cpp
@@ -115,6 +115,7 @@
 
     if (value == softwareServer::Activation::Activations::Activating)
     {
+        parent.freeSpace();
         softwareServer::Activation::activation(value);
 
         if (squashfsLoaded == false && rwVolumesCreated == false)
diff --git a/activation.hpp b/activation.hpp
index 12e4f46..8908337 100755
--- a/activation.hpp
+++ b/activation.hpp
@@ -211,6 +211,12 @@
             emit_object_added();
         }
 
+        /** @brief Activation property get function
+         *
+         *  @returns One of Activation::Activations
+         */
+        using ActivationInherit::activation;
+
         /** @brief Overloaded Activation property setter function
          *
          *  @param[in] value - One of Activation::Activations
diff --git a/configure.ac b/configure.ac
index 48d359a..8abd1b5 100755
--- a/configure.ac
+++ b/configure.ac
@@ -99,5 +99,9 @@
 AC_DEFINE(PNOR_PRSV_ACTIVE_PATH, "/var/lib/phosphor-software-manager/pnor/prsv",
     [Path to the active preserved pnor partitions])
 
+AC_ARG_VAR(ACTIVE_PNOR_MAX_ALLOWED, [The maximum allowed active pnor versions])
+AS_IF([test "x$ACTIVE_PNOR_MAX_ALLOWED" == "x"], [ACTIVE_PNOR_MAX_ALLOWED=2])
+AC_DEFINE_UNQUOTED([ACTIVE_PNOR_MAX_ALLOWED], [$ACTIVE_PNOR_MAX_ALLOWED], [The maximum allowed active pnor versions])
+
 AC_CONFIG_FILES([Makefile test/Makefile])
 AC_OUTPUT
diff --git a/item_updater.cpp b/item_updater.cpp
index c6726d3..dd313a8 100755
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -355,6 +355,33 @@
     activations.erase(entryId);
 }
 
+// TODO: openbmc/openbmc#1402 Monitor flash usage
+void ItemUpdater::freeSpace()
+{
+    std::size_t count = 0;
+    decltype(activations.begin()->second->redundancyPriority.get()->priority())
+            highestPriority = 0;
+    decltype(activations.begin()->second->versionId) highestPriorityVersion;
+    for (const auto& iter : activations)
+    {
+        if (iter.second.get()->activation() == server::Activation::Activations::Active)
+        {
+            count++;
+            if (iter.second->redundancyPriority.get()->priority() > highestPriority)
+            {
+                highestPriority = iter.second->redundancyPriority.get()->priority();
+                highestPriorityVersion = iter.second->versionId;
+            }
+        }
+    }
+    // Remove the pnor version with highest priority since the PNOR
+    // can't hold more than 2 versions.
+    if (count >= ACTIVE_PNOR_MAX_ALLOWED)
+    {
+        erase(highestPriorityVersion);
+    }
+}
+
 } // namespace updater
 } // namespace software
 } // namespace openpower
diff --git a/item_updater.hpp b/item_updater.hpp
index 2f3b1ea..a9bc8f4 100755
--- a/item_updater.hpp
+++ b/item_updater.hpp
@@ -74,6 +74,11 @@
          */
         void erase(std::string entryId);
 
+        /** @brief Deletes the active pnor version with highest priority
+                   if the total number of volume exceeds the threshold.
+         */
+        void freeSpace();
+
     private:
         /** @brief Callback function for Software.Version match.
          *  @details Creates an Activation dbus object.