Activation: store PSU image in persistent storage

When an activation succeeds, store the PSU image into persistent
storage, which will be used in future in case a PSU is replaced, and the
BMC will need to update the replaced PSU's firmware.
Only the latest image is saved, and old ones are removed for each model.

Tested: On witherspoon, verify the PSU image is saved in persistent
        storage after a successful activation with dummy service, and
        the FilePath inteface is updated with the stored path.
        And after another successful activation, the new image is saved
        and the old one is removed in persistent storage.

Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I11f3d4a91d045d2316242d8eef968f05250d862e
diff --git a/src/activation.cpp b/src/activation.cpp
index 2ca7d86..4d190f9 100644
--- a/src/activation.cpp
+++ b/src/activation.cpp
@@ -221,6 +221,7 @@
 
 void Activation::finishActivation()
 {
+    storeImage();
     activationProgress->progress(100);
 
     // TODO: delete the old software object
@@ -293,6 +294,27 @@
     return true;
 }
 
+void Activation::storeImage()
+{
+    // Store image in persistent dir separated by model
+    // and only store the latest one by removing old ones
+    auto src = fs::path(IMG_DIR) / versionId;
+    auto dst = fs::path(IMG_DIR_PERSIST) / model;
+    try
+    {
+        fs::remove_all(dst);
+        fs::create_directories(dst);
+        fs::copy(src, dst);
+        path(dst.string()); // Update the FilePath interface
+    }
+    catch (const fs::filesystem_error& e)
+    {
+        log<level::ERR>("Error storing PSU image", entry("ERROR=%s", e.what()),
+                        entry("SRC=%s", src.c_str()),
+                        entry("DST=%s", dst.c_str()));
+    }
+}
+
 } // namespace updater
 } // namespace software
 } // namespace phosphor