Add Resource dump support

To build use option -Dhost-transport=pldm and
-Dopenpower-dumps-extension=enabled
Add support for resource dump operations like
creation and offloading.
Tests:(Dump manager tests)
  Created dump entry.
  Faked notify to check whether progress is turning to completed.

Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
Change-Id: Ifeec5670a7806d7ee1b572158b4fff7dc14729a6
diff --git a/dump-extensions/openpower-dumps/dump-extensions.cpp b/dump-extensions/openpower-dumps/dump-extensions.cpp
index 6a707fa..739bc78 100644
--- a/dump-extensions/openpower-dumps/dump-extensions.cpp
+++ b/dump-extensions/openpower-dumps/dump-extensions.cpp
@@ -2,6 +2,7 @@
 
 #include "dump-extensions.hpp"
 
+#include "dump_manager_resource.hpp"
 #include "dump_manager_system.hpp"
 
 namespace phosphor
@@ -14,6 +15,8 @@
 
     dumpList.push_back(std::make_unique<phosphor::dump::system::Manager>(
         bus, SYSTEM_DUMP_OBJPATH, SYSTEM_DUMP_OBJ_ENTRY));
+    dumpList.push_back(std::make_unique<phosphor::dump::resource::Manager>(
+        bus, RESOURCE_DUMP_OBJPATH, RESOURCE_DUMP_OBJ_ENTRY));
 }
 } // namespace dump
 } // namespace phosphor
diff --git a/dump-extensions/openpower-dumps/dump_manager_resource.cpp b/dump-extensions/openpower-dumps/dump_manager_resource.cpp
new file mode 100644
index 0000000..cde0d52
--- /dev/null
+++ b/dump-extensions/openpower-dumps/dump_manager_resource.cpp
@@ -0,0 +1,126 @@
+#include "config.h"
+
+#include "dump_manager_resource.hpp"
+
+#include "dump_utils.hpp"
+#include "resource_dump_entry.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/elog.hpp>
+
+namespace phosphor
+{
+namespace dump
+{
+namespace resource
+{
+
+using namespace phosphor::logging;
+using InternalFailure =
+    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+void Manager::notify(uint32_t dumpId, uint64_t size)
+{
+    // Get the timestamp
+    std::time_t timeStamp = std::time(nullptr);
+
+    // If there is an entry with this sourceId or an invalid id
+    // update that.
+    // If host is sending the source id before the completion
+    // the source id will be updated by the transport layer with host.
+    // if not the source id will stay as invalid one.
+    for (auto& entry : entries)
+    {
+        phosphor::dump::resource::Entry* resEntry =
+            dynamic_cast<phosphor::dump::resource::Entry*>(entry.second.get());
+        if ((resEntry->status() ==
+             phosphor::dump::OperationStatus::InProgress) &&
+            ((resEntry->sourceDumpId() == dumpId) ||
+             (resEntry->sourceDumpId() == INVALID_SOURCE_ID)))
+        {
+            resEntry->update(timeStamp, size, dumpId);
+            return;
+        }
+    }
+    // Get the id
+    auto id = lastEntryId + 1;
+    auto idString = std::to_string(id);
+    auto objPath = fs::path(baseEntryPath) / idString;
+
+    try
+    {
+        entries.insert(std::make_pair(
+            id, std::make_unique<resource::Entry>(
+                    bus, objPath.c_str(), id, timeStamp, size, dumpId,
+                    std::string(), std::string(),
+                    phosphor::dump::OperationStatus::Completed, *this)));
+    }
+    catch (const std::invalid_argument& e)
+    {
+        log<level::ERR>(e.what());
+        log<level::ERR>("Error in creating resource dump entry",
+                        entry("OBJECTPATH=%s", objPath.c_str()),
+                        entry("ID=%d", id), entry("TIMESTAMP=%ull", timeStamp),
+                        entry("SIZE=%d", size), entry("SOURCEID=%d", dumpId));
+        report<InternalFailure>();
+        return;
+    }
+    lastEntryId++;
+}
+
+sdbusplus::message::object_path
+    Manager::createDump(std::map<std::string, std::string> params)
+{
+
+    using NotAllowed =
+        sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
+    using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
+
+    // Allow creating resource dump only when the host is up.
+    if (!phosphor::dump::isHostRunning())
+    {
+        elog<NotAllowed>(
+            Reason("Resource dump can be initiated only when the host is up"));
+        return std::string();
+    }
+    using CreateParameters =
+        sdbusplus::com::ibm::Dump::server::Create::CreateParameters;
+
+    auto id = lastEntryId + 1;
+    auto idString = std::to_string(id);
+    auto objPath = fs::path(baseEntryPath) / idString;
+    std::time_t timeStamp = std::time(nullptr);
+
+    std::string vspString = params[sdbusplus::com::ibm::Dump::server::Create::
+                                       convertCreateParametersToString(
+                                           CreateParameters::VSPString)];
+    std::string pwd =
+        params[sdbusplus::com::ibm::Dump::server::Create::
+                   convertCreateParametersToString(CreateParameters::Password)];
+
+    try
+    {
+        entries.insert(std::make_pair(
+            id, std::make_unique<resource::Entry>(
+                    bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
+                    vspString, pwd, phosphor::dump::OperationStatus::InProgress,
+                    *this)));
+    }
+    catch (const std::invalid_argument& e)
+    {
+        log<level::ERR>(e.what());
+        log<level::ERR>("Error in creating resource dump entry",
+                        entry("OBJECTPATH=%s", objPath.c_str()),
+                        entry("VSPSTRING=%s", vspString.c_str()),
+                        entry("ID=%d", id));
+        elog<InternalFailure>();
+        return std::string();
+    }
+    lastEntryId++;
+    return objPath.string();
+}
+
+} // namespace resource
+} // namespace dump
+} // namespace phosphor
diff --git a/dump-extensions/openpower-dumps/dump_manager_resource.hpp b/dump-extensions/openpower-dumps/dump_manager_resource.hpp
new file mode 100644
index 0000000..b8c8c73
--- /dev/null
+++ b/dump-extensions/openpower-dumps/dump_manager_resource.hpp
@@ -0,0 +1,76 @@
+#pragma once
+
+#include "dump_manager.hpp"
+#include "xyz/openbmc_project/Dump/NewDump/server.hpp"
+
+#include <com/ibm/Dump/Create/server.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/Dump/Create/server.hpp>
+
+namespace phosphor
+{
+namespace dump
+{
+namespace resource
+{
+
+constexpr uint32_t INVALID_SOURCE_ID = 0xFFFFFFFF;
+using NotifyIface = sdbusplus::server::object::object<
+    sdbusplus::xyz::openbmc_project::Dump::server::Create,
+    sdbusplus::com::ibm::Dump::server::Create,
+    sdbusplus::xyz::openbmc_project::Dump::server::NewDump>;
+
+/** @class Manager
+ *  @brief Resource Dump manager implementation.
+ *  @details A concrete implementation for the
+ *  xyz.openbmc_project.Dump.Notify and
+ *  xyz.openbmc_project.Dump.Create  DBus APIs
+ */
+class Manager : virtual public NotifyIface,
+                virtual public phosphor::dump::Manager
+{
+  public:
+    Manager() = delete;
+    Manager(const Manager&) = default;
+    Manager& operator=(const Manager&) = delete;
+    Manager(Manager&&) = delete;
+    Manager& operator=(Manager&&) = delete;
+    virtual ~Manager() = default;
+
+    /** @brief Constructor to put object onto bus at a dbus path.
+     *  @param[in] bus - Bus to attach to.
+     *  @param[in] path - Path to attach at.
+     *  @param[in] baseEntryPath - Base path of the dump entry.
+     */
+    Manager(sdbusplus::bus::bus& bus, const char* path,
+            const std::string& baseEntryPath) :
+        NotifyIface(bus, path),
+        phosphor::dump::Manager(bus, path, baseEntryPath)
+    {
+    }
+
+    void restore() override
+    {
+        // TODO #2597  Implement the restore to restore the dump entries
+        // after the service restart.
+    }
+
+    /** @brief Notify the resource dump manager about creation of a new dump.
+     *  @param[in] dumpId - Id from the source of the dump.
+     *  @param[in] size - Size of the dump.
+     */
+    void notify(uint32_t dumpId, uint64_t size) override;
+
+    /** @brief Implementation for CreateDump
+     *  Method to create Dump.
+     *
+     *  @return object_path - The object path of the new entry.
+     */
+    sdbusplus::message::object_path
+        createDump(std::map<std::string, std::string> params) override;
+};
+
+} // namespace resource
+} // namespace dump
+} // namespace phosphor
diff --git a/dump-extensions/openpower-dumps/meson.build b/dump-extensions/openpower-dumps/meson.build
index 308e167..efb1124 100644
--- a/dump-extensions/openpower-dumps/meson.build
+++ b/dump-extensions/openpower-dumps/meson.build
@@ -3,5 +3,7 @@
 phosphor_dump_manager_sources += [
         'dump-extensions/openpower-dumps/dump-extensions.cpp',
         'dump-extensions/openpower-dumps/dump_manager_system.cpp',
-        'dump-extensions/openpower-dumps/system_dump_entry.cpp'
+        'dump-extensions/openpower-dumps/system_dump_entry.cpp',
+        'dump-extensions/openpower-dumps/dump_manager_resource.cpp',
+        'dump-extensions/openpower-dumps/resource_dump_entry.cpp'
     ]
diff --git a/dump-extensions/openpower-dumps/resource_dump_entry.cpp b/dump-extensions/openpower-dumps/resource_dump_entry.cpp
new file mode 100644
index 0000000..144c42d
--- /dev/null
+++ b/dump-extensions/openpower-dumps/resource_dump_entry.cpp
@@ -0,0 +1,35 @@
+#include "resource_dump_entry.hpp"
+
+#include "dump_utils.hpp"
+#include "host_transport_exts.hpp"
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+namespace phosphor
+{
+namespace dump
+{
+namespace resource
+{
+using namespace phosphor::logging;
+
+void Entry::initiateOffload(std::string uri)
+{
+    using NotAllowed =
+        sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
+    using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
+
+    if (!phosphor::dump::isHostRunning())
+    {
+        elog<NotAllowed>(
+            Reason("This dump can be offloaded only when the host is up"));
+        return;
+    }
+    phosphor::dump::Entry::initiateOffload(uri);
+    phosphor::dump::host::requestOffload(sourceDumpId());
+}
+
+} // namespace resource
+} // namespace dump
+} // namespace phosphor
diff --git a/dump-extensions/openpower-dumps/resource_dump_entry.hpp b/dump-extensions/openpower-dumps/resource_dump_entry.hpp
new file mode 100644
index 0000000..e21111d
--- /dev/null
+++ b/dump-extensions/openpower-dumps/resource_dump_entry.hpp
@@ -0,0 +1,93 @@
+#pragma once
+
+#include "com/ibm/Dump/Entry/Resource/server.hpp"
+#include "dump_entry.hpp"
+
+#include <chrono>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+
+namespace phosphor
+{
+namespace dump
+{
+namespace resource
+{
+template <typename T>
+using ServerObject = typename sdbusplus::server::object::object<T>;
+
+using EntryIfaces = sdbusplus::server::object::object<
+    sdbusplus::com::ibm::Dump::Entry::server::Resource>;
+
+namespace fs = std::experimental::filesystem;
+
+class Manager;
+
+/** @class Entry
+ *  @brief Resource Dump Entry implementation.
+ *  @details An extension to Dump::Entry class and
+ *  A concrete implementation for the
+ *  com::ibm::Dump::Entry::Resource DBus API
+ */
+class Entry : virtual public EntryIfaces, virtual public phosphor::dump::Entry
+{
+  public:
+    Entry() = delete;
+    Entry(const Entry&) = delete;
+    Entry& operator=(const Entry&) = delete;
+    Entry(Entry&&) = delete;
+    Entry& operator=(Entry&&) = delete;
+    ~Entry() = default;
+
+    /** @brief Constructor for the resource dump Entry Object
+     *  @param[in] bus - Bus to attach to.
+     *  @param[in] objPath - Object path to attach to
+     *  @param[in] dumpId - Dump id.
+     *  @param[in] timeStamp - Dump creation timestamp
+     *             since the epoch.
+     *  @param[in] dumpSize - Dump size in bytes.
+     *  @param[in] sourceId - DumpId provided by the source.
+     *  @param[in] vspString - Input to host to generate the resource dump.
+     *  @param[in] pwd - Password needed by host to validate the request.
+     *  @param[in] status - status  of the dump.
+     *  @param[in] parent - The dump entry's parent.
+     */
+    Entry(sdbusplus::bus::bus& bus, const std::string& objPath, uint32_t dumpId,
+          uint64_t timeStamp, uint64_t dumpSize, const uint32_t sourceId,
+          std::string vspString, std::string pwd,
+          phosphor::dump::OperationStatus status,
+          phosphor::dump::Manager& parent) :
+        EntryIfaces(bus, objPath.c_str(), true),
+        phosphor::dump::Entry(bus, objPath.c_str(), dumpId, timeStamp, dumpSize,
+                              status, parent)
+    {
+        sourceDumpId(sourceId);
+        vSPString(vspString);
+        password(pwd);
+    };
+
+    /** @brief Method to initiate the offload of dump
+     *  @param[in] uri - URI to offload dump.
+     */
+    void initiateOffload(std::string uri);
+
+    /** @brief Method to update an existing dump entry
+     *  @param[in] timeStamp - Dump creation timestamp
+     *  @param[in] dumpSize - Dump size in bytes.
+     *  @param[in] sourceId - The id of dump in the origin.
+     */
+    void update(uint64_t timeStamp, uint64_t dumpSize, uint32_t sourceId)
+    {
+        sourceDumpId(sourceId);
+        elapsed(timeStamp);
+        size(dumpSize);
+        // TODO: Handled dump failure case with
+        // #bm-openbmc/2808
+        status(OperationStatus::Completed);
+        completedTime(timeStamp);
+    }
+};
+
+} // namespace resource
+} // namespace dump
+} // namespace phosphor
diff --git a/meson.build b/meson.build
index 93300e9..66ffdee 100644
--- a/meson.build
+++ b/meson.build
@@ -35,6 +35,9 @@
 conf_data.set_quoted('SYSTEM_DUMP_OBJPATH', get_option('SYSTEM_DUMP_OBJPATH'),
                       description : 'The system Dump manager Dbus path'
                     )
+conf_data.set_quoted('RESOURCE_DUMP_OBJPATH', get_option('RESOURCE_DUMP_OBJPATH'),
+                      description : 'The resource Dump manager Dbus path'
+                    )
 conf_data.set_quoted('CORE_FILE_DIR', get_option('CORE_FILE_DIR'),
                       description : 'Directory where core dumps are placed'
                     )
@@ -44,6 +47,9 @@
 conf_data.set_quoted('SYSTEM_DUMP_OBJ_ENTRY', get_option('SYSTEM_DUMP_OBJ_ENTRY'),
                       description : 'The system dump entry DBus object path'
                     )
+conf_data.set_quoted('RESOURCE_DUMP_OBJ_ENTRY', get_option('RESOURCE_DUMP_OBJ_ENTRY'),
+                      description : 'The resource dump entry DBus object path'
+                    )
 conf_data.set_quoted('BMC_DUMP_OBJ_ENTRY', get_option('BMC_DUMP_OBJ_ENTRY'),
                       description : 'The BMC dump entry DBus object path'
                     )
diff --git a/meson_options.txt b/meson_options.txt
index ea73c7f..1f25560 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -28,6 +28,11 @@
         description : 'The system Dump manager Dbus object path'
       )
 
+option('RESOURCE_DUMP_OBJPATH', type : 'string',
+        value : '/xyz/openbmc_project/dump/resource',
+        description : 'The resource dump manager Dbus object path'
+      )
+
 option('CORE_FILE_DIR', type : 'string',
         value : '/var/lib/systemd/coredump',
         description : 'Directory where core dumps are placed'
@@ -48,6 +53,11 @@
         description : 'The system dump entry DBus object path'
       )
 
+option('RESOURCE_DUMP_OBJ_ENTRY', type : 'string',
+        value : '/xyz/openbmc_project/dump/resource/entry',
+        description : 'The resource dump entry DBus object path'
+      )
+
 option('BMC_DUMP_PATH', type : 'string',
         value : '/var/lib/phosphor-debug-collector/dumps/',
         description : 'Directory where bmc dumps are placed'