serialize: Add version purpose

Add store/restore of the version purpose. Only need to store it if the
activation was successful, since those are the only versions that are
restored after BMC reboot.

Tested: Verified a code update with an image of purpose System got its
        value restored instead of being set to BMC by default.

Change-Id: I6414e9f3b992a8c29046b4d3a3d581c20a166cee
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/serialize.cpp b/serialize.cpp
index 483cd7a..31ac971 100644
--- a/serialize.cpp
+++ b/serialize.cpp
@@ -19,6 +19,7 @@
 namespace fs = std::experimental::filesystem;
 
 const std::string priorityName = "priority";
+const std::string purposeName = "purpose";
 
 void storePriority(const std::string& versionId, uint8_t priority)
 {
@@ -41,6 +42,27 @@
     oarchive(cereal::make_nvp(priorityName, priority));
 }
 
+void storePurpose(const std::string& versionId, VersionPurpose purpose)
+{
+    auto path = fs::path(PERSIST_DIR) / versionId;
+    if (!fs::is_directory(path))
+    {
+        if (fs::exists(path))
+        {
+            // Delete if it's a non-directory file
+            log<level::WARNING>("Removing non-directory file",
+                                entry("PATH=%s", path.c_str()));
+            fs::remove_all(path);
+        }
+        fs::create_directories(path);
+    }
+    path = path / purposeName;
+
+    std::ofstream os(path.c_str());
+    cereal::JSONOutputArchive oarchive(os);
+    oarchive(cereal::make_nvp(purposeName, purpose));
+}
+
 bool restorePriority(const std::string& versionId, uint8_t& priority)
 {
     auto path = fs::path(PERSIST_DIR) / versionId / priorityName;
@@ -100,6 +122,27 @@
     return false;
 }
 
+bool restorePurpose(const std::string& versionId, VersionPurpose& purpose)
+{
+    auto path = fs::path(PERSIST_DIR) / versionId / purposeName;
+    if (fs::exists(path))
+    {
+        std::ifstream is(path.c_str(), std::ios::in);
+        try
+        {
+            cereal::JSONInputArchive iarchive(is);
+            iarchive(cereal::make_nvp(purposeName, purpose));
+            return true;
+        }
+        catch (cereal::Exception& e)
+        {
+            fs::remove_all(path);
+        }
+    }
+
+    return false;
+}
+
 void removePersistDataDirectory(const std::string& versionId)
 {
     auto path = fs::path(PERSIST_DIR) / versionId;