Persist the snmp manager configuration

This commit persist the manager configuration D-Bus objects
and restores it once service starts.

This commit also deletes the associated persistent file whenever
snmp client D-Bus object gets deleted.

Change-Id: I1526b52870ee5dfea30e6527bad3fd12d1191a13
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/snmp_conf_manager.cpp b/snmp_conf_manager.cpp
index 3c7eaa6..831fd4b 100644
--- a/snmp_conf_manager.cpp
+++ b/snmp_conf_manager.cpp
@@ -1,5 +1,6 @@
 #include "config.h"
 #include "snmp_conf_manager.hpp"
+#include "snmp_serialize.hpp"
 #include "snmp_util.hpp"
 #include "xyz/openbmc_project/Common/error.hpp"
 
@@ -22,7 +23,9 @@
 using Argument = xyz::openbmc_project::Common::InvalidArgument;
 
 ConfManager::ConfManager(sdbusplus::bus::bus& bus, const char* objPath) :
-    details::CreateIface(bus, objPath, true), bus(bus), objectPath(objPath)
+    details::CreateIface(bus, objPath, true),
+    dbusPersistentLocation(SNMP_CONF_PERSIST_PATH), bus(bus),
+    objectPath(objPath)
 {
 }
 
@@ -51,9 +54,12 @@
     objPath /= objectPath;
     objPath /= generateId(address, port);
 
-    this->clients.emplace(
-        address, std::make_unique<phosphor::network::snmp::Client>(
-                     bus, objPath.string().c_str(), *this, address, port));
+    auto client = std::make_unique<phosphor::network::snmp::Client>(
+        bus, objPath.string().c_str(), *this, address, port);
+    // save the D-Bus object
+    serialize(*client, dbusPersistentLocation);
+
+    this->clients.emplace(address, std::move(client));
 }
 
 std::string ConfManager::generateId(const std::string& address, uint16_t port)
@@ -76,9 +82,65 @@
                         entry("ADDRESS=%s", address.c_str()));
         return;
     }
+
+    std::error_code ec;
+    // remove the persistent file
+    fs::path fileName = dbusPersistentLocation;
+    fileName /=
+        it->second->address() + SEPRATOR + std::to_string(it->second->port());
+
+    if (fs::exists(fileName))
+    {
+        if (!fs::remove(fileName, ec))
+        {
+            log<level::ERR>("Unable to delete the file",
+                            entry("FILE=%s", fileName.c_str()),
+                            entry("ERROR=%d", ec.value()));
+        }
+    }
+    else
+    {
+        log<level::ERR>("File doesn't exist",
+                        entry("FILE=%s", fileName.c_str()));
+    }
+    // remove the D-Bus Object.
     this->clients.erase(it);
 }
 
+void ConfManager::restoreClients()
+{
+    if (!fs::exists(dbusPersistentLocation) ||
+        fs::is_empty(dbusPersistentLocation))
+    {
+        return;
+    }
+
+    for (auto& confFile :
+         fs::recursive_directory_iterator(dbusPersistentLocation))
+    {
+        if (!fs::is_regular_file(confFile))
+        {
+            continue;
+        }
+
+        auto managerID = confFile.path().filename().string();
+        auto pos = managerID.find(SEPRATOR);
+        auto ipaddress = managerID.substr(0, pos);
+        auto port_str = managerID.substr(pos + 1);
+        uint16_t port = stoi(port_str, nullptr);
+
+        fs::path objPath = objectPath;
+        objPath /= generateId(ipaddress, port);
+        auto manager =
+            std::make_unique<Client>(bus, objPath.string().c_str(), *this);
+        if (deserialize(confFile.path(), *manager))
+        {
+            manager->emit_object_added();
+            this->clients.emplace(ipaddress, std::move(manager));
+        }
+    }
+}
+
 } // namespace snmp
 } // namespace network
 } // namespace phosphor