BMC: Store RedundancyPriority on System.

This commit extends the functionality of the BMC software updater by
preserving RedundancyPriority values through any kind of reset.

This is accomplished by storing priority values in serial files in
/var/lib/obmc/phosphor-bmc-code-mgmt/ using the Cereal library. Each
time a priority value is modified, the value in the corresponding
version file is adjusted.

Resolves openbmc/openbmc#2125

Change-Id: Ie697279895bc5ff5fdef31fa88c78dc2bc63390a
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index e652205..0af1b6d 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,6 +36,7 @@
 phosphor_image_updater_SOURCES = \
 	activation.cpp \
 	version.cpp \
+	serialize.cpp \
 	item_updater.cpp \
 	item_updater_main.cpp
 
diff --git a/activation.cpp b/activation.cpp
index 64fd53e..8dc4d38 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -1,6 +1,7 @@
 #include "activation.hpp"
 #include "item_updater.hpp"
 #include "config.h"
+#include "serialize.hpp"
 
 namespace phosphor
 {
@@ -141,6 +142,7 @@
 uint8_t RedundancyPriority::priority(uint8_t value)
 {
     parent.parent.freePriority(value);
+    storeToFile(parent.versionId, value);
     return softwareServer::RedundancyPriority::priority(value);
 }
 
diff --git a/configure.ac b/configure.ac
index 71ede44..c6ca235 100755
--- a/configure.ac
+++ b/configure.ac
@@ -68,7 +68,8 @@
     [The software version manager interface])
 AC_DEFINE(FILEPATH_IFACE, "xyz.openbmc_project.Common.FilePath",
     [The common file path interface])
-
+AC_DEFINE(PERSIST_DIR, "/var/lib/obmc/phosphor-bmc-code-mgmt/",
+    [The dir where activation data is stored in files])
 AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1",
     [The systemd busname])
 AC_DEFINE(SYSTEMD_PATH, "/org/freedesktop/systemd1",
diff --git a/item_updater.cpp b/item_updater.cpp
index 8bd868b..12f818b 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -6,6 +6,7 @@
 #include "xyz/openbmc_project/Software/Version/server.hpp"
 #include <experimental/filesystem>
 #include "version.hpp"
+#include "serialize.hpp"
 
 namespace phosphor
 {
@@ -194,6 +195,7 @@
     //       If not, don't continue.
 
     this->activations.erase(entryId);
+    removeFile(entryId);
 }
 
 ItemUpdater::ActivationStatus ItemUpdater::validateSquashFSImage(
diff --git a/serialize.cpp b/serialize.cpp
new file mode 100644
index 0000000..8c97c89
--- /dev/null
+++ b/serialize.cpp
@@ -0,0 +1,51 @@
+#include "config.h"
+#include <experimental/filesystem>
+#include <cereal/archives/json.hpp>
+#include <fstream>
+#include "serialize.hpp"
+
+namespace phosphor
+{
+namespace software
+{
+namespace updater
+{
+
+namespace fs = std::experimental::filesystem;
+
+void storeToFile(std::string versionId, uint8_t priority)
+{
+    if(!fs::is_directory(PERSIST_DIR))
+    {
+        fs::create_directory(PERSIST_DIR);
+    }
+    std::string path = PERSIST_DIR + versionId;
+
+    std::ofstream os(path.c_str());
+    cereal::JSONOutputArchive oarchive(os);
+    oarchive(cereal::make_nvp("priority", priority));
+}
+
+void restoreFromFile(std::string versionId, uint8_t& priority)
+{
+    std::string path = PERSIST_DIR + versionId;
+    if (fs::exists(path))
+    {
+        std::ifstream is(path.c_str(), std::ios::in);
+        cereal::JSONInputArchive iarchive(is);
+        iarchive(cereal::make_nvp("priority", priority));
+    }
+}
+
+void removeFile(std::string versionId)
+{
+    std::string path = PERSIST_DIR + versionId;
+    if (fs::exists(path))
+    {
+        fs::remove(path);
+    }
+}
+
+} // namespace phosphor
+} // namespace software
+} // namespace openpower
diff --git a/serialize.hpp b/serialize.hpp
new file mode 100644
index 0000000..7b6461f
--- /dev/null
+++ b/serialize.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <experimental/filesystem>
+#include "config.h"
+
+namespace phosphor
+{
+namespace software
+{
+namespace updater
+{
+
+namespace fs = std::experimental::filesystem;
+
+/** @brief Serialization function - stores activation information to file
+ *  @param[in] versionId - The version for which to store information.
+ *  @param[in] priority - RedundancyPriority value for that version.
+ **/
+void storeToFile(std::string versionId, uint8_t priority);
+
+/** @brief Serialization function - restores activation information from file
+ *  @param[in] versionId - The version for which to retrieve information.
+ *  @param[in] priority - RedundancyPriority reference for that version.
+ **/
+void restoreFromFile(std::string versionId, uint8_t& priority);
+
+/** @brief Removes the serial file for a given version.
+ *  @param[in] versionId - The version for which to remove a file, if it exists.
+ **/
+void removeFile(std::string versionId);
+
+} // namespace phosphor
+} // namespace software
+} // namespace openpower