Redfish: BMC dump logEntry service implementation

This commit supports adding a BMC dump entry under /redfish/
v1/Managers/bmc/LogServices/Dump

* Removed the option for enabling each dump separately. Instead
introduced one common option to enable dump.

* Defined few methods that are common for both BMC and System dumps.

* Compilation flag DBMCWEB_ENABLE_REDFISH_DUMP_LOG must be enabled.

Tested-By:

* curl -k -H "X-Auth-Token: $bmc_token" -X GET https://${bmc}/
redfish/v1/Managers/bmc/LogServices/

* curl -k -H "X-Auth-Token: $bmc_token" -X GET https://${bmc}/
redfish/v1/Managers/bmc/LogServices/Dump

* curl -k -H "X-Auth-Token: $bmc_token" -X GET https://${bmc}/
redfish/v1/Managers/bmc/LogServices/Dump/Entries

* curl -k -H "X-Auth-Token: $bmc_token" -X GET https://${bmc}/
redfish/v1/Managers/bmc/LogServices/Dump/Entries/<dump-id>

* curl -k -H "X-Auth-Token: $bmc_token" -X DELETE https://${bmc}/
redfish/v1/Managers/bmc/LogServices/Dump/Entries/<dump-id>

Redfish Validator passed.

Signed-off-by: Asmitha Karunanithi <asmitk01@in.ibm.com>
Change-Id: Iac9daa8242154e249fad66609b837cf7d2b16091
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aacd34f..2886438 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,9 +71,10 @@
     OFF
 )
 option (
-    BMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG
-    "Enable System dump log service transactions through Redfish.  Paths are under
-    '/redfish/v1/Systems/system/LogServices/SystemDump'."
+    BMCWEB_ENABLE_REDFISH_DUMP_LOG
+    "Enable BMC and System dump log service transactions through Redfish. For BMC dump, paths
+    are under '/redfish/v1/Managers/bmc/LogServices/Dump' and for System dump,
+    paths are under '/redfish/v1/Systems/system/LogServices/Dump'."
     OFF
 )
 option (
@@ -413,8 +414,8 @@
     -DBMCWEB_ENABLE_REDFISH_RAW_PECI>
     $<$<BOOL:${BMCWEB_ENABLE_REDFISH_CPU_LOG}>:
     -DBMCWEB_ENABLE_REDFISH_CPU_LOG>
-    $<$<BOOL:${BMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG}>:
-    -DBMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG>
+    $<$<BOOL:${BMCWEB_ENABLE_REDFISH_DUMP_LOG}>:
+    -DBMCWEB_ENABLE_REDFISH_DUMP_LOG>
     $<$<BOOL:${BMCWEB_ENABLE_REDFISH_BMC_JOURNAL}>:
     -DBMCWEB_ENABLE_REDFISH_BMC_JOURNAL>
     $<$<BOOL:${BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES}>:
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index cc98e1a..5dee66b 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -104,12 +104,17 @@
         nodes.emplace_back(std::make_unique<PostCodesEntry>(app));
         nodes.emplace_back(std::make_unique<PostCodesEntryCollection>(app));
 
-#ifdef BMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG
+#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
         nodes.emplace_back(std::make_unique<SystemDumpService>(app));
         nodes.emplace_back(std::make_unique<SystemDumpEntryCollection>(app));
         nodes.emplace_back(std::make_unique<SystemDumpEntry>(app));
         nodes.emplace_back(std::make_unique<SystemDumpEntryDownload>(app));
         nodes.emplace_back(std::make_unique<SystemDumpClear>(app));
+
+        nodes.emplace_back(std::make_unique<BMCDumpService>(app));
+        nodes.emplace_back(std::make_unique<BMCDumpEntryCollection>(app));
+        nodes.emplace_back(std::make_unique<BMCDumpEntry>(app));
+
 #endif
 
 #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index baef92f..22c3ad7 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -143,28 +143,6 @@
     return "";
 }
 
-inline void deleteSystemDumpEntry(crow::Response& res,
-                                  const std::string& entryID)
-{
-    std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
-
-    auto respHandler = [asyncResp](const boost::system::error_code ec) {
-        BMCWEB_LOG_DEBUG << "System Dump Entry doDelete callback: Done";
-        if (ec)
-        {
-            BMCWEB_LOG_ERROR
-                << "System Dump (DBus) doDelete respHandler got error " << ec;
-            asyncResp->res.result(
-                boost::beast::http::status::internal_server_error);
-            return;
-        }
-    };
-    crow::connections::systemBus->async_method_call(
-        respHandler, "xyz.openbmc_project.Dump.Manager",
-        "/xyz/openbmc_project/dump/entry/" + entryID,
-        "xyz.openbmc_project.Object.Delete", "Delete");
-}
-
 static int getJournalMetadata(sd_journal* journal,
                               const std::string_view& field,
                               std::string_view& contents)
@@ -450,6 +428,317 @@
     return !redfishLogFiles.empty();
 }
 
+inline void getDumpEntryCollection(std::shared_ptr<AsyncResp>& asyncResp,
+                                   const std::string& dumpType)
+{
+    std::string dumpPath;
+    if (dumpType == "BMC")
+    {
+        dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/";
+    }
+    else if (dumpType == "System")
+    {
+        dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/";
+    }
+    else
+    {
+        BMCWEB_LOG_ERROR << "Invalid dump type" << dumpType;
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, dumpPath, dumpType](const boost::system::error_code ec,
+                                        GetManagedObjectsType& resp) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << "DumpEntry resp_handler got error " << ec;
+                messages::internalError(asyncResp->res);
+                return;
+            }
+
+            nlohmann::json& entriesArray = asyncResp->res.jsonValue["Members"];
+            entriesArray = nlohmann::json::array();
+
+            for (auto& object : resp)
+            {
+                bool foundDumpEntry = false;
+                for (auto& interfaceMap : object.second)
+                {
+                    if (interfaceMap.first ==
+                        ("xyz.openbmc_project.Dump.Entry." + dumpType))
+                    {
+                        foundDumpEntry = true;
+                        break;
+                    }
+                }
+
+                if (foundDumpEntry == false)
+                {
+                    continue;
+                }
+                std::time_t timestamp;
+                uint64_t size = 0;
+                entriesArray.push_back({});
+                nlohmann::json& thisEntry = entriesArray.back();
+                const std::string& path =
+                    static_cast<const std::string&>(object.first);
+                std::size_t lastPos = path.rfind("/");
+                if (lastPos == std::string::npos)
+                {
+                    continue;
+                }
+                std::string entryID = path.substr(lastPos + 1);
+
+                for (auto& interfaceMap : object.second)
+                {
+                    if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
+                    {
+
+                        for (auto& propertyMap : interfaceMap.second)
+                        {
+                            if (propertyMap.first == "Size")
+                            {
+                                auto sizePtr =
+                                    std::get_if<uint64_t>(&propertyMap.second);
+                                if (sizePtr == nullptr)
+                                {
+                                    messages::internalError(asyncResp->res);
+                                    break;
+                                }
+                                size = *sizePtr;
+                                break;
+                            }
+                        }
+                    }
+                    else if (interfaceMap.first ==
+                             "xyz.openbmc_project.Time.EpochTime")
+                    {
+
+                        for (auto& propertyMap : interfaceMap.second)
+                        {
+                            if (propertyMap.first == "Elapsed")
+                            {
+                                const uint64_t* usecsTimeStamp =
+                                    std::get_if<uint64_t>(&propertyMap.second);
+                                if (usecsTimeStamp == nullptr)
+                                {
+                                    messages::internalError(asyncResp->res);
+                                    break;
+                                }
+                                timestamp =
+                                    static_cast<std::time_t>(*usecsTimeStamp);
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                thisEntry["@odata.type"] = "#LogEntry.v1_5_1.LogEntry";
+                thisEntry["@odata.id"] = dumpPath + entryID;
+                thisEntry["Id"] = entryID;
+                thisEntry["EntryType"] = "Event";
+                thisEntry["Created"] = crow::utility::getDateTime(timestamp);
+                thisEntry["Name"] = dumpType + " Dump Entry";
+
+                thisEntry["Oem"]["OpenBmc"]["@odata.type"] =
+                    "#OemLogEntry.v1_0_0.OpenBmc";
+                thisEntry["Oem"]["OpenBmc"]["AdditionalDataSizeBytes"] = size;
+
+                if (dumpType == "BMC")
+                {
+                    thisEntry["Oem"]["OpenBmc"]["DiagnosticDataType"] =
+                        "Manager";
+                    thisEntry["Oem"]["OpenBmc"]["AdditionalDataURI"] =
+                        "/redfish/v1/Managers/bmc/LogServices/Dump/"
+                        "attachment/" +
+                        entryID;
+                }
+                else if (dumpType == "System")
+                {
+                    thisEntry["Oem"]["OpenBmc"]["DiagnosticDataType"] = "OEM";
+                    thisEntry["Oem"]["OpenBmc"]["OEMDiagnosticDataType"] =
+                        "System";
+                    thisEntry["Oem"]["OpenBmc"]["AdditionalDataURI"] =
+                        "/redfish/v1/Systems/system/LogServices/Dump/"
+                        "attachment/" +
+                        entryID;
+                }
+            }
+            asyncResp->res.jsonValue["Members@odata.count"] =
+                entriesArray.size();
+        },
+        "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump",
+        "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+}
+
+inline void getDumpEntryById(std::shared_ptr<AsyncResp>& asyncResp,
+                             const std::string& entryID,
+                             const std::string& dumpType)
+{
+    std::string dumpPath;
+    if (dumpType == "BMC")
+    {
+        dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/";
+    }
+    else if (dumpType == "System")
+    {
+        dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/";
+    }
+    else
+    {
+        BMCWEB_LOG_ERROR << "Invalid dump type" << dumpType;
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, entryID, dumpPath, dumpType](
+            const boost::system::error_code ec, GetManagedObjectsType& resp) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << "DumpEntry resp_handler got error " << ec;
+                messages::internalError(asyncResp->res);
+                return;
+            }
+
+            for (auto& objectPath : resp)
+            {
+                if (objectPath.first.str.find(
+                        "/xyz/openbmc_project/dump/entry/" + entryID) ==
+                    std::string::npos)
+                {
+                    continue;
+                }
+
+                bool foundDumpEntry = false;
+                for (auto& interfaceMap : objectPath.second)
+                {
+                    if (interfaceMap.first ==
+                        ("xyz.openbmc_project.Dump.Entry." + dumpType))
+                    {
+                        foundDumpEntry = true;
+                        break;
+                    }
+                }
+                if (foundDumpEntry == false)
+                {
+                    BMCWEB_LOG_ERROR << "Can't find Dump Entry";
+                    messages::internalError(asyncResp->res);
+                    return;
+                }
+
+                std::time_t timestamp;
+                uint64_t size = 0;
+
+                for (auto& interfaceMap : objectPath.second)
+                {
+                    if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
+                    {
+                        for (auto& propertyMap : interfaceMap.second)
+                        {
+                            if (propertyMap.first == "Size")
+                            {
+                                auto sizePtr =
+                                    std::get_if<uint64_t>(&propertyMap.second);
+                                if (sizePtr == nullptr)
+                                {
+                                    messages::internalError(asyncResp->res);
+                                    break;
+                                }
+                                size = *sizePtr;
+                                break;
+                            }
+                        }
+                    }
+                    else if (interfaceMap.first ==
+                             "xyz.openbmc_project.Time.EpochTime")
+                    {
+                        for (auto& propertyMap : interfaceMap.second)
+                        {
+                            if (propertyMap.first == "Elapsed")
+                            {
+                                const uint64_t* usecsTimeStamp =
+                                    std::get_if<uint64_t>(&propertyMap.second);
+                                if (usecsTimeStamp == nullptr)
+                                {
+                                    messages::internalError(asyncResp->res);
+                                    break;
+                                }
+                                timestamp =
+                                    static_cast<std::time_t>(*usecsTimeStamp);
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                asyncResp->res.jsonValue["@odata.type"] =
+                    "#LogEntry.v1_5_1.LogEntry";
+                asyncResp->res.jsonValue["@odata.id"] = dumpPath + entryID;
+                asyncResp->res.jsonValue["Id"] = entryID;
+                asyncResp->res.jsonValue["EntryType"] = "Event";
+                asyncResp->res.jsonValue["Created"] =
+                    crow::utility::getDateTime(timestamp);
+                asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
+
+                asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
+                    "#OemLogEntry.v1_0_0.OpenBmc";
+                asyncResp->res
+                    .jsonValue["Oem"]["OpenBmc"]["AdditionalDataSizeBytes"] =
+                    size;
+
+                if (dumpType == "BMC")
+                {
+                    asyncResp->res
+                        .jsonValue["Oem"]["OpenBmc"]["DiagnosticDataType"] =
+                        "Manager";
+                    asyncResp->res
+                        .jsonValue["Oem"]["OpenBmc"]["AdditionalDataURI"] =
+                        "/redfish/v1/Managers/bmc/LogServices/Dump/"
+                        "attachment/" +
+                        entryID;
+                }
+                else if (dumpType == "System")
+                {
+                    asyncResp->res
+                        .jsonValue["Oem"]["OpenBmc"]["DiagnosticDataType"] =
+                        "OEM";
+                    asyncResp->res
+                        .jsonValue["Oem"]["OpenBmc"]["OEMDiagnosticDataType"] =
+                        "System";
+                    asyncResp->res
+                        .jsonValue["Oem"]["OpenBmc"]["AdditionalDataURI"] =
+                        "/redfish/v1/Systems/system/LogServices/Dump/"
+                        "attachment/" +
+                        entryID;
+                }
+            }
+        },
+        "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump",
+        "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+}
+
+inline void deleteDumpEntry(crow::Response& res, const std::string& entryID)
+{
+    std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+    auto respHandler = [asyncResp](const boost::system::error_code ec) {
+        BMCWEB_LOG_DEBUG << "Dump Entry doDelete callback: Done";
+        if (ec)
+        {
+            BMCWEB_LOG_ERROR << "Dump (DBus) doDelete respHandler got error "
+                             << ec;
+            messages::internalError(asyncResp->res);
+            return;
+        }
+    };
+    crow::connections::systemBus->async_method_call(
+        respHandler, "xyz.openbmc_project.Dump.Manager",
+        "/xyz/openbmc_project/dump/entry/" + entryID,
+        "xyz.openbmc_project.Object.Delete", "Delete");
+}
+
 static void ParseCrashdumpParameters(
     const std::vector<std::pair<std::string, VariantType>>& params,
     std::string& filename, std::string& timestamp, std::string& logfile)
@@ -524,9 +813,9 @@
         logServiceArray = nlohmann::json::array();
         logServiceArray.push_back(
             {{"@odata.id", "/redfish/v1/Systems/system/LogServices/EventLog"}});
-#ifdef BMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG
+#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
         logServiceArray.push_back(
-            {{"@odata.id", "/redfish/v1/Systems/system/LogServices/System"}});
+            {{"@odata.id", "/redfish/v1/Systems/system/LogServices/Dump"}});
 #endif
 
 #ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG
@@ -1274,6 +1563,10 @@
             "Collection of LogServices for this Manager";
         nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
         logServiceArray = nlohmann::json::array();
+#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
+        logServiceArray.push_back(
+            {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump"}});
+#endif
 #ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
         logServiceArray.push_back(
             {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Journal"}});
@@ -1555,12 +1848,12 @@
     }
 };
 
-class SystemDumpService : public Node
+class BMCDumpService : public Node
 {
   public:
     template <typename CrowApp>
-    SystemDumpService(CrowApp& app) :
-        Node(app, "/redfish/v1/Systems/system/LogServices/System/")
+    BMCDumpService(CrowApp& app) :
+        Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/")
     {
         entityPrivileges = {
             {boost::beast::http::verb::get, {{"Login"}}},
@@ -1578,34 +1871,33 @@
         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
 
         asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/Systems/system/LogServices/System";
+            "/redfish/v1/Managers/bmc/LogServices/Dump";
         asyncResp->res.jsonValue["@odata.type"] =
             "#LogService.v1_1_0.LogService";
-        asyncResp->res.jsonValue["Name"] = "Dump Log Service";
-        asyncResp->res.jsonValue["Description"] = "System Dump Log Service";
-        asyncResp->res.jsonValue["Id"] = "System";
+        asyncResp->res.jsonValue["Name"] = "Dump LogService";
+        asyncResp->res.jsonValue["Description"] = "BMC Dump LogService";
+        asyncResp->res.jsonValue["Id"] = "Dump";
         asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
-        asyncResp->res.jsonValue["LogEntryTypes"] = "Dump";
-        asyncResp->res.jsonValue["Oem"]["DumpType"] = "System";
-
         asyncResp->res.jsonValue["Entries"] = {
-            {"@odata.id",
-             "/redfish/v1/Systems/system/LogServices/System/Entries"}};
-        asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
-            {"target", "/redfish/v1/Systems/system/LogServices/System/"
-                       "Actions/LogService.ClearLog"}};
-        asyncResp->res.jsonValue["Actions"]["#LogService.CreateLog"] = {
-            {"target", "/redfish/v1/Systems/system/LogServices/System/"
-                       "Actions/LogService.CreateLog"}};
+            {"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}};
+        asyncResp->res.jsonValue["Actions"] = {
+            {"#LogService.ClearLog",
+             {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
+                         "Actions/LogService.ClearLog"}}},
+            {"Oem",
+             {{"#OemLogService.CollectDiagnosticData",
+               {{"target",
+                 "/redfish/v1/Managers/bmc/LogServices/Dump/"
+                 "Actions/Oem/OemLogService.CollectDiagnosticData"}}}}}};
     }
 };
 
-class SystemDumpEntryCollection : public Node
+class BMCDumpEntryCollection : public Node
 {
   public:
     template <typename CrowApp>
-    SystemDumpEntryCollection(CrowApp& app) :
-        Node(app, "/redfish/v1/Systems/system/LogServices/System/Entries/")
+    BMCDumpEntryCollection(CrowApp& app) :
+        Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/")
     {
         entityPrivileges = {
             {boost::beast::http::verb::get, {{"Login"}}},
@@ -1628,56 +1920,20 @@
         asyncResp->res.jsonValue["@odata.type"] =
             "#LogEntryCollection.LogEntryCollection";
         asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/Systems/system/LogServices/System/Entries";
-        asyncResp->res.jsonValue["Name"] = "System Dump Entries";
+            "/redfish/v1/Managers/bmc/LogServices/Dump/Entries";
+        asyncResp->res.jsonValue["Name"] = "BMC Dump Entries";
         asyncResp->res.jsonValue["Description"] =
-            "Collection of System Dump Entries";
+            "Collection of BMC Dump Entries";
 
-        crow::connections::systemBus->async_method_call(
-            [asyncResp](const boost::system::error_code ec,
-                        const crow::openbmc_mapper::GetSubTreeType& resp) {
-                if (ec)
-                {
-                    BMCWEB_LOG_ERROR << " resp_handler got error " << ec;
-                    messages::internalError(asyncResp->res);
-                    return;
-                }
-
-                nlohmann::json& logArray = asyncResp->res.jsonValue["Members"];
-                logArray = nlohmann::json::array();
-                for (auto& object : resp)
-                {
-                    const std::string& path =
-                        static_cast<const std::string&>(object.first);
-                    std::size_t lastPos = path.rfind("/");
-                    if (lastPos == std::string::npos)
-                    {
-                        continue;
-                    }
-                    std::string logID = path.substr(lastPos + 1);
-                    logArray.push_back(
-                        {{"@odata.id", "/redfish/v1/Systems/system/LogServices/"
-                                       "System/Entries/" +
-                                           logID}});
-                }
-                asyncResp->res.jsonValue["Members@odata.count"] =
-                    logArray.size();
-            },
-            "xyz.openbmc_project.ObjectMapper",
-            "/xyz/openbmc_project/object_mapper",
-            "xyz.openbmc_project.ObjectMapper", "GetSubTree",
-            "/xyz/openbmc_project/dump", 0,
-            std::array<const char*, 1>{
-                "xyz.openbmc_project.Dump.Entry.System"});
+        getDumpEntryCollection(asyncResp, "BMC");
     }
 };
 
-class SystemDumpEntry : public Node
+class BMCDumpEntry : public Node
 {
   public:
-    SystemDumpEntry(CrowApp& app) :
-        Node(app,
-             "/redfish/v1/Systems/system/LogServices/System/Entries/<str>/",
+    BMCDumpEntry(CrowApp& app) :
+        Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/",
              std::string())
     {
         entityPrivileges = {
@@ -1699,161 +1955,143 @@
             messages::internalError(asyncResp->res);
             return;
         }
-        const std::string& entryID = params[0];
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, entryID](const boost::system::error_code ec,
-                                 GetManagedObjectsType& resp) {
-                if (ec)
-                {
-                    BMCWEB_LOG_ERROR
-                        << "SystemDumpEntry resp_handler got error " << ec;
-                    messages::internalError(asyncResp->res);
-                    return;
-                }
-
-                for (auto& objectPath : resp)
-                {
-                    if (objectPath.first.str.find(
-                            "/xyz/openbmc_project/dump/entry/" + entryID) ==
-                        std::string::npos)
-                    {
-                        continue;
-                    }
-
-                    bool foundSystemDumpEntry = false;
-                    for (auto& interfaceMap : objectPath.second)
-                    {
-                        if (interfaceMap.first ==
-                            "xyz.openbmc_project.Dump.Entry.System")
-                        {
-                            foundSystemDumpEntry = true;
-                            break;
-                        }
-                    }
-                    if (foundSystemDumpEntry == false)
-                    {
-                        BMCWEB_LOG_DEBUG << "Can't find System Dump Entry";
-                        messages::internalError(asyncResp->res);
-                        return;
-                    }
-
-                    std::string timestamp{};
-                    uint64_t size = 0;
-
-                    for (auto& interfaceMap : objectPath.second)
-                    {
-                        if (interfaceMap.first ==
-                            "xyz.openbmc_project.Dump.Entry")
-                        {
-                            for (auto& propertyMap : interfaceMap.second)
-                            {
-                                if (propertyMap.first == "Size")
-                                {
-                                    auto sizePtr = std::get_if<uint64_t>(
-                                        &propertyMap.second);
-                                    if (sizePtr == nullptr)
-                                    {
-                                        messages::propertyMissing(
-                                            asyncResp->res, "Size");
-                                        break;
-                                    }
-                                    size = *sizePtr;
-                                    break;
-                                }
-                            }
-                        }
-                        else if (interfaceMap.first ==
-                                 "xyz.openbmc_project.Time.EpochTime")
-                        {
-                            for (auto& propertyMap : interfaceMap.second)
-                            {
-                                if (propertyMap.first == "Elapsed")
-                                {
-                                    const uint64_t* usecsTimeStamp =
-                                        std::get_if<uint64_t>(
-                                            &propertyMap.second);
-                                    if (usecsTimeStamp == nullptr)
-                                    {
-                                        messages::propertyMissing(
-                                            asyncResp->res, "Elapsed");
-                                        break;
-                                    }
-                                    getTimestampStr(*usecsTimeStamp, timestamp);
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    asyncResp->res.jsonValue = {
-                        {"@odata.type", "#LogEntry.v1_4_0.LogEntry"},
-                        {"@odata.id",
-                         "/redfish/v1/Systems/system/LogServices/System/"
-                         "Entries/" +
-                             entryID},
-                        {"Name", "System Dump Entry"},
-                        {"Id", entryID},
-                        {"SizeInB", size},
-                        {"EntryType", "Dump"},
-                        {"EntryCode", "User generated dump"},
-                        {"Created", timestamp}};
-
-                    asyncResp->res
-                        .jsonValue["Actions"]["#LogEntry.DownloadLog"] = {
-                        {"target",
-                         "/redfish/v1/Systems/system/LogServices/System/"
-                         "Entries/" +
-                             entryID + "/Actions/LogEntry.DownloadLog"}};
-                }
-            },
-            "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump",
-            "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+        getDumpEntryById(asyncResp, params[0], "BMC");
     }
 
     void doDelete(crow::Response& res, const crow::Request& req,
                   const std::vector<std::string>& params) override
     {
-        BMCWEB_LOG_DEBUG << "Do delete single dump entry";
-
-        auto asyncResp = std::make_shared<AsyncResp>(res);
-
+        std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
         if (params.size() != 1)
         {
             messages::internalError(asyncResp->res);
             return;
         }
-        std::string entryID = params[0];
+        deleteDumpEntry(asyncResp->res, params[0]);
+    }
+};
 
-        crow::connections::systemBus->async_method_call(
-            [asyncResp,
-             entryID](const boost::system::error_code ec,
-                      const crow::openbmc_mapper::GetSubTreeType& resp) {
-                if (ec)
-                {
-                    BMCWEB_LOG_ERROR << " resp_handler got error " << ec;
-                    messages::internalError(asyncResp->res);
-                    return;
-                }
+class SystemDumpService : public Node
+{
+  public:
+    template <typename CrowApp>
+    SystemDumpService(CrowApp& app) :
+        Node(app, "/redfish/v1/Systems/system/LogServices/Dump/")
+    {
+        entityPrivileges = {
+            {boost::beast::http::verb::get, {{"Login"}}},
+            {boost::beast::http::verb::head, {{"Login"}}},
+            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+    }
 
-                for (auto& object : resp)
-                {
-                    const std::string& path =
-                        static_cast<const std::string&>(object.first);
+  private:
+    void doGet(crow::Response& res, const crow::Request& req,
+               const std::vector<std::string>& params) override
+    {
+        std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
 
-                    std::size_t pos = path.rfind(
-                        "/xyz/openbmc_project/dump/entry/" + entryID);
-                    if (pos != std::string::npos)
-                    {
-                        deleteSystemDumpEntry(asyncResp->res, entryID);
-                        return;
-                    }
-                }
-            },
-            "xyz.openbmc_project.ObjectMapper",
-            "/xyz/openbmc_project/object_mapper",
-            "xyz.openbmc_project.ObjectMapper", "GetSubTree",
-            "/xyz/openbmc_project/dump", 0,
-            std::array<const char*, 1>{
-                "xyz.openbmc_project.Dump.Entry.System"});
+        asyncResp->res.jsonValue["@odata.id"] =
+            "/redfish/v1/Systems/system/LogServices/Dump";
+        asyncResp->res.jsonValue["@odata.type"] =
+            "#LogService.v1_1_0.LogService";
+        asyncResp->res.jsonValue["Name"] = "Dump LogService";
+        asyncResp->res.jsonValue["Description"] = "System Dump LogService";
+        asyncResp->res.jsonValue["Id"] = "Dump";
+        asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+        asyncResp->res.jsonValue["Entries"] = {
+            {"@odata.id",
+             "/redfish/v1/Systems/system/LogServices/Dump/Entries"}};
+        asyncResp->res.jsonValue["Actions"] = {
+            {"#LogService.ClearLog",
+             {{"target", "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
+                         "LogService.ClearLog"}}},
+            {"Oem",
+             {{"#OemLogService.CollectDiagnosticData",
+               {{"target",
+                 "/redfish/v1/Systems/system/LogServices/Dump/Actions/Oem/"
+                 "OemLogService.CollectDiagnosticData"}}}}}};
+    }
+};
+
+class SystemDumpEntryCollection : public Node
+{
+  public:
+    template <typename CrowApp>
+    SystemDumpEntryCollection(CrowApp& app) :
+        Node(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/")
+    {
+        entityPrivileges = {
+            {boost::beast::http::verb::get, {{"Login"}}},
+            {boost::beast::http::verb::head, {{"Login"}}},
+            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+    }
+
+  private:
+    /**
+     * Functions triggers appropriate requests on DBus
+     */
+    void doGet(crow::Response& res, const crow::Request& req,
+               const std::vector<std::string>& params) override
+    {
+        std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+        asyncResp->res.jsonValue["@odata.type"] =
+            "#LogEntryCollection.LogEntryCollection";
+        asyncResp->res.jsonValue["@odata.id"] =
+            "/redfish/v1/Systems/system/LogServices/Dump/Entries";
+        asyncResp->res.jsonValue["Name"] = "System Dump Entries";
+        asyncResp->res.jsonValue["Description"] =
+            "Collection of System Dump Entries";
+
+        getDumpEntryCollection(asyncResp, "System");
+    }
+};
+
+class SystemDumpEntry : public Node
+{
+  public:
+    SystemDumpEntry(CrowApp& app) :
+        Node(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/",
+             std::string())
+    {
+        entityPrivileges = {
+            {boost::beast::http::verb::get, {{"Login"}}},
+            {boost::beast::http::verb::head, {{"Login"}}},
+            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+    }
+
+  private:
+    void doGet(crow::Response& res, const crow::Request& req,
+               const std::vector<std::string>& params) override
+    {
+        std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+        if (params.size() != 1)
+        {
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        getDumpEntryById(asyncResp, params[0], "System");
+    }
+
+    void doDelete(crow::Response& res, const crow::Request& req,
+                  const std::vector<std::string>& params) override
+    {
+        std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+        if (params.size() != 1)
+        {
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        deleteDumpEntry(asyncResp->res, params[0]);
     }
 };
 
@@ -1922,7 +2160,7 @@
                     if (pos != std::string::npos)
                     {
                         std::string logID = objectPath.substr(pos + 1);
-                        deleteSystemDumpEntry(asyncResp->res, logID);
+                        deleteDumpEntry(asyncResp->res, logID);
                     }
                 }
             },