PEL: Add repository to save PELs

Create the Repository class that can save PELs in (and later retrieve
them from) the filesystem.  It provides an add() method that can add
a PEL object to the repository.

Now, when the Manager class sees an OpenBMC event log created with the
RAWPEL metadata in the AdditionalData property that points at a file
that contains a PEL, it can save that PEL.  Before the PEL is saved, the
log ID and commit timestamp fields in the PEL will be updated - the log
ID to a unique value, and the timestamp to the current time.

Change-Id: I8dbaddf0f155bcb6d40b933294ada83feb75ce53
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index 3e22336..a009188 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -1,6 +1,10 @@
 #include "manager.hpp"
 
 #include "additional_data.hpp"
+#include "pel.hpp"
+
+#include <filesystem>
+#include <fstream>
 
 namespace openpower
 {
@@ -8,6 +12,7 @@
 {
 
 using namespace phosphor::logging;
+namespace fs = std::filesystem;
 
 namespace additional_data
 {
@@ -36,6 +41,55 @@
 
 void Manager::addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID)
 {
+    if (fs::exists(rawPelPath))
+    {
+        std::ifstream file(rawPelPath, std::ios::in | std::ios::binary);
+
+        auto data = std::vector<uint8_t>(std::istreambuf_iterator<char>(file),
+                                         std::istreambuf_iterator<char>());
+        if (file.fail())
+        {
+            log<level::ERR>("Filesystem error reading a raw PEL",
+                            entry("PELFILE=%s", rawPelPath.c_str()),
+                            entry("OBMCLOGID=%d", obmcLogID));
+            // TODO, Decide what to do here. Maybe nothing.
+            return;
+        }
+
+        file.close();
+
+        auto pel = std::make_unique<PEL>(data, obmcLogID);
+        if (pel->valid())
+        {
+            // PELs created by others still need these fields set by us.
+            pel->assignID();
+            pel->setCommitTime();
+
+            try
+            {
+                _repo.add(pel);
+            }
+            catch (std::exception& e)
+            {
+                // Probably a full or r/o filesystem, not much we can do.
+                log<level::ERR>("Unable to add PEL to Repository",
+                                entry("PEL_ID=0x%X", pel->id()));
+            }
+        }
+        else
+        {
+            log<level::ERR>("Invalid PEL found",
+                            entry("PELFILE=%s", rawPelPath.c_str()),
+                            entry("OBMCLOGID=%d", obmcLogID));
+            // TODO, make a whole new OpenBMC event log + PEL
+        }
+    }
+    else
+    {
+        log<level::ERR>("Raw PEL file from BMC event log does not exist",
+                        entry("PELFILE=%s", (rawPelPath).c_str()),
+                        entry("OBMCLOGID=%d", obmcLogID));
+    }
 }
 
 void Manager::erase(uint32_t obmcLogID)