Implementation of create interface.
Both the external and internal Dump managers define "Create"
interfaces. This commit implements these.
Change-Id: If857ec6ea7267fd72e9b420e6b44fa68b6abab66
Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 30d5a88..72401e1 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,7 +3,10 @@
# Build these headers, don't install them
noinst_HEADERS = \
dump_entry.hpp \
- dump_watch.hpp
+ dump_watch.hpp \
+ dump_internal.hpp \
+ dump_manager.hpp \
+ dump_utils.hpp
nobase_nodist_include_HEADERS = \
xyz/openbmc_project/Dump/Monitor/error.hpp \
@@ -16,7 +19,9 @@
phosphor_dump_manager_SOURCES = \
dump_manager_main.cpp \
dump_entry.cpp \
- xyz/openbmc_project/Dump/Internal/Create/server.cpp
+ dump_manager.cpp \
+ xyz/openbmc_project/Dump/Internal/Create/server.cpp \
+ xyz/openbmc_project/Dump/Monitor/error.cpp
phosphor_dump_monitor_SOURCES = \
dump_watch_main.cpp \
@@ -35,7 +40,8 @@
phosphor_dump_manager_LDADD = \
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
$(SDBUSPLUS_LIBS) \
- $(PHOSPHOR_LOGGING_LIBS)
+ $(PHOSPHOR_LOGGING_LIBS) \
+ -lstdc++fs
phosphor_dump_monitor_LDADD = \
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
diff --git a/configure.ac b/configure.ac
index 985624c..0807a82 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,5 +51,19 @@
AS_IF([test "x$CORE_FILE_DIR" == "x"], [CORE_FILE_DIR="/var/lib/systemd/coredump"])
AC_DEFINE_UNQUOTED([CORE_FILE_DIR], ["$CORE_FILE_DIR"], [Directory where core dumps are placed])
+AC_ARG_VAR(OBJ_INTERNAL, [Internal Dump manager Dbus object path])
+AS_IF([test "x$OBJ_INTERNAL" == "x"], [OBJ_INTERNAL="/xyz/openbmc_project/dump/internal/manager"])
+AC_DEFINE_UNQUOTED([OBJ_INTERNAL], ["$OBJ_INTERNAL"], [Internal Dump manager Dbus object path])
+
+AC_ARG_VAR(OBJ_ENTRY, [The dump entry DBus object path.])
+AS_IF([test "x$OBJ_ENTRY" == "x"], [OBJ_ENTRY="/xyz/openbmc_project/dump/entry"])
+AC_DEFINE_UNQUOTED([OBJ_ENTRY], ["$OBJ_ENTRY"], [The dump entry DBus object path])
+
+# TODO openbmc/openbmc#1795
+# Change the path to Dump Partition path.
+AC_ARG_VAR(BMC_DUMP_FILE_DIR, [Directory where bmc dumps are placed])
+AS_IF([test "x$BMC_DUMP_FILE_DIR" == "x"], [BMC_DUMP_FILE_DIR="/tmp"])
+AC_DEFINE_UNQUOTED([BMC_DUMP_FILE_DIR], ["$BMC_DUMP_FILE_DIR"], [Directory where bmc dumps are placed])
+
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/dump_entry.cpp b/dump_entry.cpp
index 75c1358..373d8e4 100644
--- a/dump_entry.cpp
+++ b/dump_entry.cpp
@@ -1,17 +1,25 @@
#include "dump_entry.hpp"
+#include "dump_manager.hpp"
+
+#include <phosphor-logging/log.hpp>
namespace phosphor
{
namespace dump
{
-Entry::Entry(sdbusplus::bus::bus& bus, const char* obj): EntryIfaces(bus, obj)
-{
-}
-
+using namespace phosphor::logging;
void Entry::delete_()
{
+ //Delete Dump file from Permanent location
+ if (!fs::remove(file))
+ {
+ log<level::INFO>("Dump file doesn't exist.",
+ entry("Name=%s", file.c_str()));
+ }
+ // Remove Dump entry D-bus object
+ parent.erase(id);
}
} // namespace dump
diff --git a/dump_entry.hpp b/dump_entry.hpp
index d276f0d..2942704 100644
--- a/dump_entry.hpp
+++ b/dump_entry.hpp
@@ -1,6 +1,10 @@
#pragma once
+#include <experimental/filesystem>
+
+#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
+
#include "xyz/openbmc_project/Dump/Entry/server.hpp"
#include "xyz/openbmc_project/Object/Delete/server.hpp"
#include "xyz/openbmc_project/Time/EpochTime/server.hpp"
@@ -18,6 +22,10 @@
sdbusplus::xyz::openbmc_project::Object::server::Delete,
sdbusplus::xyz::openbmc_project::Time::server::EpochTime>;
+namespace fs = std::experimental::filesystem;
+
+class Manager;
+
/** @class Entry
* @brief OpenBMC Dump Entry implementation.
* @details A concrete implementation for the
@@ -31,18 +39,49 @@
Entry& operator=(const Entry&) = delete;
Entry(Entry&&) = delete;
Entry& operator=(Entry&&) = delete;
- virtual ~Entry() = default;
+ ~Entry() = default;
/** @brief Constructor for the Dump Entry Object
* @param[in] bus - Bus to attach to.
- * @param[in] obj - Object path 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] fileSize - Dump file size in bytes.
+ * @param[in] file - Dump file name.
+ * @param[in] parent - The dump entry's parent.
*/
- Entry(sdbusplus::bus::bus& bus, const char* obj);
+ Entry(sdbusplus::bus::bus& bus,
+ const std::string& objPath,
+ uint32_t dumpId,
+ uint64_t timeStamp,
+ uint64_t fileSize,
+ const fs::path& file,
+ Manager& parent):
+ EntryIfaces(bus, objPath.c_str(), true),
+ file(file),
+ parent(parent),
+ id(dumpId)
+ {
+ size(fileSize);
+ elapsed(timeStamp);
+ // Emit deferred signal.
+ this->emit_object_added();
+ };
/** @brief Delete this d-bus object.
*/
void delete_() override ;
+ private:
+ /** @Dump file name */
+ fs::path file;
+
+ /** @brief This entry's parent */
+ Manager& parent;
+
+ /** @brief This entry's id */
+ uint32_t id;
};
} // namespace dump
diff --git a/dump_internal.hpp b/dump_internal.hpp
new file mode 100644
index 0000000..0688b78
--- /dev/null
+++ b/dump_internal.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+
+#include "xyz/openbmc_project/Dump/Internal/Create/server.hpp"
+
+namespace phosphor
+{
+namespace dump
+{
+namespace internal
+{
+
+using CreateIface = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Dump::Internal::server::Create>;
+
+/** @class Manager
+ * @brief Implementation for the
+ * xyz.openbmc_project.Dump.Internal.Create DBus API.
+ */
+class Manager : public CreateIface
+{
+ public:
+ Manager() = delete;
+ Manager(const Manager&) = delete;
+ 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.
+ */
+ Manager(sdbusplus::bus::bus& bus, const char* path) :
+ CreateIface(bus, path) {};
+
+ /** @brief Implementation for Create
+ * Create BMC Dump based on the Dump type.
+ *
+ * @param[in] type - Type of the Dump.
+ * @param[in] fullPaths - List of absolute paths to the files
+ * to be included as part of Dump package.
+ */
+ void create(
+ Type type,
+ std::vector<std::string> fullPaths) override;
+
+};
+
+} // namespace internal
+} // namespace dump
+} // namespace phosphor
diff --git a/dump_manager.cpp b/dump_manager.cpp
new file mode 100644
index 0000000..d0376a5
--- /dev/null
+++ b/dump_manager.cpp
@@ -0,0 +1,116 @@
+#include <unistd.h>
+
+#include <phosphor-logging/elog-errors.hpp>
+
+#include "dump_manager.hpp"
+#include "dump_internal.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+#include "config.h"
+
+namespace phosphor
+{
+namespace dump
+{
+
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+using namespace phosphor::logging;
+
+namespace internal
+{
+
+void Manager::create(
+ Type type,
+ std::vector<std::string> fullPaths)
+{
+ // TODO openbmc/openbmc#1795
+ // Add implementaion of internal create function.
+}
+
+} //namepsace internal
+
+uint32_t Manager::createDump()
+{
+ std::vector<std::string> paths;
+
+ return captureDump(Type::UserRequested, paths);
+}
+
+uint32_t Manager::captureDump(
+ Type type,
+ const std::vector<std::string>& fullPaths)
+{
+ pid_t pid = fork();
+
+ // TODO openbmc/openbmc#1795
+ // Add Dump location info.
+ if (pid == 0)
+ {
+ execl("/usr/bin/ffdc", "ffdc", nullptr);
+
+ //ffdc script execution is failed.
+ auto error = errno;
+ log<level::ERR>("Error occurred during ffdc function execution",
+ entry("ERRNO=%d", error));
+ elog<InternalFailure>();
+ }
+ else if (pid > 0)
+ {
+ auto rc = sd_event_add_child(eventLoop.get(),
+ nullptr,
+ pid,
+ WEXITED | WSTOPPED,
+ callback,
+ nullptr);
+ if (0 > rc)
+ {
+ // Failed to add to event loop
+ log<level::ERR>("Error occurred during the sd_event_add_child call",
+ entry("rc=%d", rc));
+ elog<InternalFailure>();
+ }
+ }
+ else
+ {
+ auto error = errno;
+ log<level::ERR>("Error occurred during fork",
+ entry("ERRNO=%d", error));
+ elog<InternalFailure>();
+ }
+
+ return ++lastEntryId;
+}
+
+void Manager::createEntry(const fs::path& file)
+{
+ // TODO openbmc/openbmc#1795
+ // Get Dump ID and Epoch time from Dump file name.
+ // Validate the Dump file name.
+ auto id = lastEntryId;
+
+ //Get Epoch time.
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch()).count();
+
+ // Entry Object path.
+ auto objPath = fs::path(OBJ_ENTRY) / std::to_string(id);
+
+ auto size = fs::file_size(file);
+
+ entries.insert(std::make_pair(id,
+ std::make_unique<Entry>(
+ bus,
+ objPath.c_str(),
+ id,
+ ms,
+ size,
+ file,
+ *this)));
+}
+
+void Manager::erase(uint32_t entryId)
+{
+ entries.erase(entryId);
+}
+
+} //namespace dump
+} //namespace phosphor
diff --git a/dump_manager.hpp b/dump_manager.hpp
new file mode 100644
index 0000000..3bbcf3e
--- /dev/null
+++ b/dump_manager.hpp
@@ -0,0 +1,130 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/Dump/Create/server.hpp>
+#include <experimental/filesystem>
+
+#include "xyz/openbmc_project/Dump/Internal/Create/server.hpp"
+#include "dump_entry.hpp"
+
+namespace phosphor
+{
+namespace dump
+{
+namespace internal
+{
+
+class Manager;
+
+} // namespace internal
+
+namespace fs = std::experimental::filesystem;
+using Type =
+ sdbusplus::xyz::openbmc_project::Dump::Internal::server::Create::Type;
+
+using CreateIface = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Dump::server::Create>;
+
+/* Need a custom deleter for freeing up sd_event */
+struct EventDeleter
+{
+ void operator()(sd_event* event) const
+ {
+ event = sd_event_unref(event);
+ }
+};
+using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
+
+/** @class Manager
+ * @brief OpenBMC Dump manager implementation.
+ * @details A concrete implementation for the
+ * xyz.openbmc_project.Dump.Create DBus API.
+ */
+class Manager : public CreateIface
+{
+ friend class internal::Manager;
+ friend class Entry;
+
+ 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] event - Dump manager sd_event loop.
+ * @param[in] path - Path to attach at.
+ */
+ Manager(sdbusplus::bus::bus& bus,
+ const EventPtr& event, const char* path) :
+ CreateIface(bus, path),
+ bus(bus),
+ eventLoop(event.get()),
+ lastEntryId(0)
+ {}
+
+ /** @brief Implementation for CreateDump
+ * Method to create Dump.
+ *
+ * @return id - The Dump entry id number.
+ */
+ uint32_t createDump() override;
+
+ private:
+ /** @brief Create Dump entry d-bus object
+ * @param[in] fullPath - Full path of the Dump file name
+ */
+ void createEntry(const fs::path& fullPath);
+
+ /** @brief Capture BMC Dump based on the Dump type.
+ * @param[in] type - Type of the Dump.
+ * @param[in] fullPaths - List of absolute paths to the files
+ * to be included as part of Dump package.
+ * @return id - The Dump entry id number.
+ */
+ uint32_t captureDump(
+ Type type,
+ const std::vector<std::string>& fullPaths);
+
+ /** @brief Erase specified entry d-bus object
+ *
+ * @param[in] entryId - unique identifier of the entry
+ */
+ void erase(uint32_t entryId);
+
+ /** @brief sd_event_add_child callback
+ *
+ * @param[in] s - event source
+ * @param[in] si - signal info
+ * @param[in] userdata - pointer to Watch object
+ *
+ * @returns 0 on success, -1 on fail
+ */
+ static int callback(sd_event_source* s,
+ const siginfo_t* si,
+ void* userdata)
+ {
+ //No specific action required in
+ //the sd_event_add_child callback.
+ return 0;
+ }
+
+ /** @brief sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+
+ /** @brief sdbusplus Dump event loop */
+ EventPtr eventLoop;
+
+ /** @brief Dump Entry dbus objects map based on entry id */
+ std::map<uint32_t, std::unique_ptr<Entry>> entries;
+
+ /** @brief Id of the last Dump entry */
+ uint32_t lastEntryId;
+};
+
+} // namespace dump
+} // namespace phosphor
diff --git a/dump_manager_main.cpp b/dump_manager_main.cpp
index 39398e7..cd1d83b 100644
--- a/dump_manager_main.cpp
+++ b/dump_manager_main.cpp
@@ -1,20 +1,51 @@
-#include <sdbusplus/bus.hpp>
-#include <sdbusplus/server/manager.hpp>
-#include "config.h"
+#include <phosphor-logging/elog-errors.hpp>
-int main(int argc, char *argv[])
+#include "xyz/openbmc_project/Common/error.hpp"
+#include "config.h"
+#include "dump_manager.hpp"
+#include "dump_internal.hpp"
+
+int main(int argc, char* argv[])
{
auto bus = sdbusplus::bus::new_default();
+ using namespace phosphor::logging;
+ using InternalFailure =
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+ sd_event* event = nullptr;
+ auto rc = sd_event_default(&event);
+ if (rc < 0)
+ {
+ log<level::ERR>("Error occurred during the sd_event_default",
+ entry("rc=%d", rc));
+ report<InternalFailure>();
+ return rc;
+ }
+ phosphor::dump::EventPtr eventP{event};
+ event = nullptr;
// Add sdbusplus ObjectManager for the 'root' path of the DUMP manager.
sdbusplus::server::manager::manager objManager(bus, DUMP_OBJPATH);
-
bus.request_name(DUMP_BUSNAME);
- while(true)
+ try
{
- bus.process_discard();
- bus.wait();
+ phosphor::dump::Manager manager(bus, eventP, DUMP_OBJPATH);
+ phosphor::dump::internal::Manager mgr(bus, OBJ_INTERNAL);
+ bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
+ auto rc = sd_event_loop(eventP.get());
+ if (rc < 0)
+ {
+ log<level::ERR>("Error occurred during the sd_event_loop",
+ entry("rc=%d", rc));
+ elog<InternalFailure>();
+ }
+ }
+
+ catch (InternalFailure& e)
+ {
+ commit<InternalFailure>();
+ return -1;
}
return 0;
diff --git a/dump_utils.hpp b/dump_utils.hpp
new file mode 100644
index 0000000..a71458c
--- /dev/null
+++ b/dump_utils.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+namespace phosphor
+{
+namespace dump
+{
+
+/** @struct CustomFd
+ *
+ * RAII wrapper for file descriptor.
+ */
+struct CustomFd
+{
+ private:
+ /** @brief File descriptor */
+ int fd = -1;
+
+ public:
+ CustomFd() = delete;
+ CustomFd(const CustomFd&) = delete;
+ CustomFd& operator=(const CustomFd&) = delete;
+ CustomFd(CustomFd&&) = delete;
+ CustomFd& operator=(CustomFd&&) = delete;
+
+ /** @brief Saves File descriptor and uses it to do file operation
+ *
+ * @param[in] fd - File descriptor
+ */
+ CustomFd(int fd) : fd(fd) {}
+
+ ~CustomFd()
+ {
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ }
+
+ int operator()() const
+ {
+ return fd;
+ }
+};
+
+} // namespace dump
+} // namespace phosphor
diff --git a/dump_watch.cpp b/dump_watch.cpp
index 6208466..12a6c73 100644
--- a/dump_watch.cpp
+++ b/dump_watch.cpp
@@ -1,33 +1,17 @@
-#include <stdexcept>
-#include <cstddef>
-#include <cstring>
-#include <string>
-#include <vector>
#include <sys/inotify.h>
-#include <unistd.h>
+#include <experimental/filesystem>
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Dump/Monitor/error.hpp>
+
#include "config.h"
#include "dump_watch.hpp"
-#include <experimental/filesystem>
-#include <phosphor-logging/log.hpp>
-#include <phosphor-logging/elog.hpp>
-#include <phosphor-logging/elog-errors.hpp>
#include "elog-errors.hpp"
-#include <xyz/openbmc_project/Dump/Monitor/error.hpp>
#include "xyz/openbmc_project/Common/error.hpp"
namespace phosphor
{
namespace dump
{
-
-CustomFd::~CustomFd()
-{
- if (fd >= 0)
- {
- close(fd);
- }
-}
-
namespace inotify
{
diff --git a/dump_watch.hpp b/dump_watch.hpp
index 3f7bceb..fdd301c 100644
--- a/dump_watch.hpp
+++ b/dump_watch.hpp
@@ -1,47 +1,16 @@
#pragma once
-#include <map>
-#include <memory>
#include <systemd/sd-event.h>
#include <unistd.h>
+#include "dump_utils.hpp"
namespace phosphor
{
namespace dump
{
-
-/** @struct CustomFd
- *
- * RAII wrapper for file descriptor.
- */
-struct CustomFd
-{
- private:
- /** @brief File descriptor */
- int fd = -1;
-
- public:
- CustomFd(const CustomFd&) = delete;
- CustomFd& operator=(const CustomFd&) = delete;
- CustomFd(CustomFd&&) = delete;
- CustomFd& operator=(CustomFd&&) = delete;
-
- /** @brief Saves File descriptor and uses it to do file operation
- *
- * @param[in] fd - File descriptor
- */
- CustomFd(int fd) : fd(fd) {}
-
- ~CustomFd();
-
- int operator()() const
- {
- return fd;
- }
-};
-
namespace inotify
{
+
/** @class Watch
*
* @brief Adds inotify watch on core file directories.
diff --git a/dump_watch_main.cpp b/dump_watch_main.cpp
index 6c7d98b..d061ae1 100644
--- a/dump_watch_main.cpp
+++ b/dump_watch_main.cpp
@@ -1,11 +1,11 @@
-#include <exception>
#include "dump_watch.hpp"
+#include "elog-errors.hpp"
+#include "xyz/openbmc_project/Dump/Monitor/error.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
-#include "elog-errors.hpp"
-#include <xyz/openbmc_project/Dump/Monitor/error.hpp>
-#include "xyz/openbmc_project/Common/error.hpp"
int main(int argc, char* argv[])
{
diff --git a/xyz/openbmc_project/Dump/Internal/Create.interface.yaml b/xyz/openbmc_project/Dump/Internal/Create.interface.yaml
index 4d3150b..46f2bce 100644
--- a/xyz/openbmc_project/Dump/Internal/Create.interface.yaml
+++ b/xyz/openbmc_project/Dump/Internal/Create.interface.yaml
@@ -29,6 +29,8 @@
- name: ApplicationCored
description: >
Dump triggered due to application core.
-
+ - name: UserRequested
+ description: >
+ Dump triggered by the user.
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4