Update Uboot environment variables when a version is deleted or updated

- We need to update the uboot env variables to point to the
  version that has the lowest priority when
  the version with lowest priority gets deleted or when
  the version with lowest priority gets a higher priority

Resolves openbmc/openbmc#2372

Change-Id: If43105c9ee2c3ada8aeb19939a428eb05e621ee9
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
diff --git a/activation.cpp b/activation.cpp
index 6d503ee..73eb651 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -155,39 +155,10 @@
 {
     parent.parent.freePriority(value, parent.versionId);
     storeToFile(parent.versionId, value);
-
-    if (parent.parent.isLowestPriority(value))
-    {
-        parent.updateUbootEnvVars();
-    }
-
+    parent.parent.resetUbootEnvVars();
     return softwareServer::RedundancyPriority::priority(value);
 }
 
-// TODO: openbmc/openbmc#2369 Add recovery policy to updateubootvars
-//       unit template.
-// TODO: openbmc/openbmc#2370 Call StartUnit synchronously to handle
-//       Errors more gracefully.
-void Activation::updateUbootEnvVars()
-{
-    auto method = bus.new_method_call(
-            SYSTEMD_BUSNAME,
-            SYSTEMD_PATH,
-            SYSTEMD_INTERFACE,
-            "StartUnit");
-    auto updateEnvVarsFile = "obmc-flash-bmc-updateubootvars@" + versionId +
-            ".service";
-    method.append(updateEnvVarsFile, "replace");
-    auto result = bus.call(method);
-
-    //Check that the bus call didn't result in an error
-    if (result.is_method_error())
-    {
-        log<level::ERR>("Failed to update u-boot env variables",
-                        entry(" %s", SYSTEMD_INTERFACE));
-    }
-}
-
 void Activation::unitStateChange(sdbusplus::message::message& msg)
 {
     if (softwareServer::Activation::activation() !=
diff --git a/activation.hpp b/activation.hpp
index a3f2a62..cf4b5c2 100644
--- a/activation.hpp
+++ b/activation.hpp
@@ -266,12 +266,6 @@
         void unsubscribeFromSystemdSignals();
 
         /**
-         * @brief Updates the uboot variables to point to versionId, so that
-         *        the systems boots from this version on the next boot.
-         */
-        void updateUbootEnvVars();
-
-        /**
          * @brief delete the d-bus object.
          */
         void delete_() override;
diff --git a/item_updater.cpp b/item_updater.cpp
index 1cafb03..e2de36f 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -332,6 +332,7 @@
     }
 
     this->activations.erase(entryId);
+    ItemUpdater::resetUbootEnvVars();
 }
 
 void ItemUpdater::deleteAll()
@@ -580,6 +581,46 @@
     return true;
 }
 
+void ItemUpdater::resetUbootEnvVars()
+{
+    decltype(activations.begin()->second->redundancyPriority.get()->priority())
+             lowestPriority = std::numeric_limits<uint8_t>::max();
+    decltype(activations.begin()->second->versionId) lowestPriorityVersion;
+    for (const auto& intf : activations)
+    {
+        if (!intf.second->redundancyPriority.get())
+        {
+            // Skip this version if the redundancyPriority is not initialized.
+            continue;
+        }
+
+        if (intf.second->redundancyPriority.get()->priority()
+            <= lowestPriority)
+        {
+            lowestPriority = intf.second->redundancyPriority.get()->priority();
+            lowestPriorityVersion = intf.second->versionId;
+        }
+    }
+
+    // TODO: openbmc/openbmc#2369 Add recovery policy to updateubootvars
+    //       unit template.
+    auto method = bus.new_method_call(
+            SYSTEMD_BUSNAME,
+            SYSTEMD_PATH,
+            SYSTEMD_INTERFACE,
+            "StartUnit");
+    auto updateEnvVarsFile = "obmc-flash-bmc-updateubootvars@" +
+                             lowestPriorityVersion + ".service";
+    method.append(updateEnvVarsFile, "replace");
+    auto result = bus.call(method);
+
+    //Check that the bus call didn't result in an error
+    if (result.is_method_error())
+    {
+        log<level::ERR>("Failed to update u-boot env variables");
+    }
+}
+
 } // namespace updater
 } // namespace software
 } // namespace phosphor
diff --git a/item_updater.hpp b/item_updater.hpp
index 5a17993..7b65b80 100644
--- a/item_updater.hpp
+++ b/item_updater.hpp
@@ -114,6 +114,13 @@
          */
         bool isLowestPriority(uint8_t value);
 
+    /**
+     * @brief Updates the uboot variables to point to BMC version with lowest
+     *        priority, so that the system boots from this version on the
+     *        next boot.
+     */
+    void resetUbootEnvVars();
+
     private:
         /** @brief Callback function for Software.Version match.
          *  @details Creates an Activation D-Bus object.