diff options
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | log_manager.cpp | 148 | ||||
-rw-r--r-- | log_manager.hpp | 70 | ||||
-rw-r--r-- | log_manager_main.cpp | 22 | ||||
-rw-r--r-- | xyz.openbmc_project.Logging.Internal.Manager.cpp | 91 | ||||
-rw-r--r-- | xyz/openbmc_project/Logging/Internal/Manager/server.hpp | 81 |
7 files changed, 313 insertions, 113 deletions
diff --git a/Makefile.am b/Makefile.am index ac50cc9..f96d2cf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,12 @@ nodist_include_HEADERS = elog-gen.hpp bin_PROGRAMS = logging-test logging_test_SOURCES = logging_test.cpp +sbin_PROGRAMS = phosphor-log-manager +phosphor_log_manager_SOURCES = \ + xyz.openbmc_project.Logging.Internal.Manager.cpp \ + log_manager.cpp \ + log_manager_main.cpp + # Be sure to build elog-gen.hpp before compiling BUILT_SOURCES = elog-gen.hpp @@ -15,6 +21,7 @@ CLEANFILES=elog-gen.hpp # systemd required for journal interfaces logging_test_LDFLAGS = $(SYSTEMD_LIBS) +phosphor_log_manager_LDFLAGS = $(SYSTEMD_LIBS) ELOG_YAML ?= xyz/openbmc_project/Example/Elog.errors.yaml ELOG_MAKO ?= elog-gen-template.mako.hpp diff --git a/configure.ac b/configure.ac index 7f8a446..8ed1a3b 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,9 @@ PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221]) AC_CHECK_HEADER(systemd/sd-journal.h, ,[AC_MSG_ERROR([Could not find \ systemd/sd-journal.h...systemd developement package required])]) +AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find \ +systemd/sd-bus.h...systemd developement package required])]) + # Check/set gtest specific functions. AX_PTHREAD([GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=1"],[GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=0"]) @@ -43,6 +46,8 @@ AS_IF([test "x$enable_oe_sdk" == "xyes"], AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags]) ) +AC_DEFINE(BUSNAME, "xyz.openbmc_project.Logging.Internal.Manager", [The DBus busname to own.]) +AC_DEFINE(OBJ, "/xyz/openbmc_project/Logging/Internal", [The DBus object path.]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile test/Makefile]) -AC_OUTPUT
\ No newline at end of file +AC_OUTPUT diff --git a/log_manager.cpp b/log_manager.cpp index 21e99a8..a3e49e9 100644 --- a/log_manager.cpp +++ b/log_manager.cpp @@ -7,65 +7,38 @@ #include <systemd/sd-bus.h> #include <systemd/sd-journal.h> #include "log.hpp" +#include "log_manager.hpp" -using namespace phosphor; +namespace phosphor +{ +namespace logging +{ -/* - * @fn commit() - * @brief Create an error/event log based on specified id and metadata variable - * names that includes the journal message and the metadata values. - */ -auto commit(sd_bus_message *msg, void *userdata, sd_bus_error *error) +void Manager::commit(uint64_t transactionId, std::string errMsg) { // TODO Change /tmp path to a permanent location on flash constexpr const auto path = "/tmp/elog"; constexpr const auto msgIdStr = "_PID"; - // Read PID - int rc = -1; - char *msgId = nullptr; - rc = sd_bus_message_read(msg, "s", &msgId); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to read msg id", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - return sd_bus_reply_method_return(msg, "i", rc); - } - // Create log file std::string filename{}; filename.append(path); // TODO Create error logs in their own separate dir once permanent location - // on flash is determined. Ex: ../msgId/1 - filename.append(msgId); + // on flash is determined. Ex: ../transactionId/1 std::ofstream efile; efile.open(filename); efile << "{" << std::endl; - // Read metadata variables passed as array of strings and store in vector - // TODO Read required metadata fields from header file instead - rc = sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY, "s"); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to read metadata vars", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - return sd_bus_reply_method_return(msg, nullptr); - } - const char* metaVar = nullptr; + //const char* metaVar = nullptr; std::vector<const char*> metaList; - while ((rc = sd_bus_message_read_basic(msg, 's', &metaVar)) > 0) - { - metaList.push_back(metaVar); - } - sd_bus_message_exit_container(msg); sd_journal *j = nullptr; - rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); if (rc < 0) { logging::log<logging::level::ERR>("Failed to open journal", logging::entry("DESCRIPTION=%s", strerror(-rc))); - return sd_bus_reply_method_return(msg, nullptr); + return; } // Read the journal from the end to get the most recent entry first. @@ -83,12 +56,16 @@ auto commit(sd_bus_message *msg, void *userdata, sd_bus_error *error) continue; } std::string result(data); - if (result.find(msgId) == std::string::npos) +// TODO String msgid is now an int transaction id. This piece will be +// uncommented and reworked with the upcoming change to read the metadata +// fields from the header file. +#if 0 + if (result.find(msgid) == std::string::npos) { // Match not found, continue to next journal entry continue; } - +#endif // Match found, write to file // TODO This is a draft format based on the redfish event logs written // in json, the final openbmc format is to be determined @@ -128,87 +105,34 @@ auto commit(sd_bus_message *msg, void *userdata, sd_bus_error *error) efile << "}" << std::endl; efile.close(); - return sd_bus_reply_method_return(msg, nullptr); + return; } -constexpr sdbusplus::vtable::vtable_t log_vtable[] = +Manager::Manager(sdbusplus::bus::bus &&bus, + const char* busname, + const char* obj) : + details::ServerObject<details::ManagerIface>(bus, obj), + _bus(std::move(bus)), + _manager(sdbusplus::server::manager::manager(_bus, obj)) { - sdbusplus::vtable::start(), - sdbusplus::vtable::method("Commit", "sas", "", commit), - sdbusplus::vtable::end() -}; + _bus.request_name(busname); +} -int main(int argc, char *argv[]) +void Manager::run() noexcept { - constexpr const auto dbusLogObj = "/xyz/openbmc_project/Logging"; - constexpr const auto dbusLogName = "xyz.openbmc_project.Logging"; - int rc = -1; - sd_bus *bus = nullptr; - - rc = sd_bus_open_system(&bus); - if (rc < 0) + while(true) { - logging::log<logging::level::ERR>("Failed to open system bus", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - goto cleanup; - } - - rc = sd_bus_add_object_manager(bus, nullptr, dbusLogObj); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to add object mgr", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - goto cleanup; - } - - rc = sd_bus_add_object_vtable(bus, - nullptr, - dbusLogObj, - dbusLogName, - log_vtable, - nullptr); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to add vtable", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - goto cleanup; - } - - rc = sd_bus_request_name(bus, dbusLogName, 0); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to acquire service name", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - } - else - { - for(;;) + try { - rc = sd_bus_process(bus, nullptr); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to connect to bus", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - break; - } - if (rc > 0) - { - continue; - } - - rc = sd_bus_wait(bus, (uint64_t) - 1); - if (rc < 0) - { - logging::log<logging::level::ERR>("Failed to wait on bus", - logging::entry("DESCRIPTION=%s", strerror(-rc))); - break; - } + _bus.process_discard(); + _bus.wait(); + } + catch (std::exception &e) + { + std::cerr << e.what() << std::endl; } } - -cleanup: - sd_bus_unref(bus); - - return rc; } +} // namespace logging +} // namepsace phosphor diff --git a/log_manager.hpp b/log_manager.hpp new file mode 100644 index 0000000..2b4281d --- /dev/null +++ b/log_manager.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include <sdbusplus/server.hpp> +#include "xyz/openbmc_project/Logging/Internal/Manager/server.hpp" + +namespace phosphor +{ +namespace logging +{ +namespace details +{ + +template <typename T> +using ServerObject = typename sdbusplus::server::object::object<T>; + +using ManagerIface = + sdbusplus::xyz::openbmc_project::Logging::Internal::server::Manager; + +} // namespace details + +/** @class Manager + * @brief OpenBMC logging manager implementation. + * @details A concrete implementation for the + * xyz.openbmc_project.Logging.Internal.Manager DBus API. + */ +class Manager final : + public details::ServerObject<details::ManagerIface> +{ + public: + Manager() = delete; + Manager(const Manager&) = delete; + Manager& operator=(const Manager&) = delete; + Manager(Manager&&) = default; + Manager& operator=(Manager&&) = default; + ~Manager() = default; + + /** @brief Constructor for the Log Manager object + * @param[in] bus - DBus bus to attach to. + * @param[in] busname - Name of DBus bus to own. + * @param[in] obj - Object path to attach to. + */ + Manager(sdbusplus::bus::bus&& bus, + const char* busname, + const char* obj); + + /** @brief Start processing DBus messages. */ + void run() noexcept; + + /* + * @fn commit() + * @brief sd_bus Commit method implementation callback. + * @details Create an error/event log based on transaction id and + * error message. + * @param[in] transactionId - Unique identifier of the journal entries + * to be committed. + * @param[in] errMsg - The error exception message associated with the + * error log to be committed. + */ + void commit(uint64_t transactionId, std::string errMsg) override; + + private: + /** @brief Persistent sdbusplus DBus bus connection. */ + sdbusplus::bus::bus _bus; + + /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */ + sdbusplus::server::manager::manager _manager; +}; + +} // namespace logging +} // namespace phosphor diff --git a/log_manager_main.cpp b/log_manager_main.cpp new file mode 100644 index 0000000..21c13ae --- /dev/null +++ b/log_manager_main.cpp @@ -0,0 +1,22 @@ +#include "config.h" +#include "log_manager.hpp" +#include <sdbusplus/bus.hpp> +#include <cstdlib> +#include <iostream> +#include <exception> + +int main(int argc, char *argv[]) +{ + try { + auto manager = phosphor::logging::Manager( + sdbusplus::bus::new_system(), + BUSNAME, + OBJ); + manager.run(); + exit(EXIT_SUCCESS); + } + catch (const std::exception &e) { + std::cerr << e.what() << std::endl; + } + exit(EXIT_FAILURE); +} diff --git a/xyz.openbmc_project.Logging.Internal.Manager.cpp b/xyz.openbmc_project.Logging.Internal.Manager.cpp new file mode 100644 index 0000000..2afdb6d --- /dev/null +++ b/xyz.openbmc_project.Logging.Internal.Manager.cpp @@ -0,0 +1,91 @@ +#include <algorithm> +#include <sdbusplus/server.hpp> +#include <sdbusplus/exception.hpp> +#include <xyz/openbmc_project/Logging/Internal/Manager/server.hpp> + + +namespace sdbusplus +{ +namespace xyz +{ +namespace openbmc_project +{ +namespace Logging +{ +namespace Internal +{ +namespace server +{ + +Manager::Manager(bus::bus& bus, const char* path) + : _xyz_openbmc_project_Logging_Internal_Manager_interface( + bus, path, _interface, _vtable, this) +{ +} + + +int Manager::_callback_Commit( + sd_bus_message* msg, void* context, sd_bus_error* error) +{ + using sdbusplus::server::binding::details::convertForMessage; + + try + { + auto m = message::message(sd_bus_message_ref(msg)); + + uint64_t transactionId{}; + std::string errMsg{}; + + m.read(transactionId, errMsg); + + auto o = static_cast<Manager*>(context); + o->commit(transactionId, errMsg); + + auto reply = m.new_method_return(); + // No data to append on reply. + + reply.method_return(); + } + catch(sdbusplus::internal_exception_t& e) + { + sd_bus_error_set_const(error, e.name(), e.description()); + return -EINVAL; + } + + return true; +} + +namespace details +{ +namespace Manager +{ +static const auto _param_Commit = + utility::tuple_to_array(message::types::type_id< + uint64_t, std::string>()); +static const auto _return_Commit = + utility::tuple_to_array(std::make_tuple('\0')); +} +} + + + + +const vtable::vtable_t Manager::_vtable[] = { + vtable::start(), + + vtable::method("Commit", + details::Manager::_param_Commit + .data(), + details::Manager::_return_Commit + .data(), + _callback_Commit), + vtable::end() +}; + +} // namespace server +} // namespace Internal +} // namespace Logging +} // namespace openbmc_project +} // namespace xyz +} // namespace sdbusplus + diff --git a/xyz/openbmc_project/Logging/Internal/Manager/server.hpp b/xyz/openbmc_project/Logging/Internal/Manager/server.hpp new file mode 100644 index 0000000..3bec2a9 --- /dev/null +++ b/xyz/openbmc_project/Logging/Internal/Manager/server.hpp @@ -0,0 +1,81 @@ +#pragma once +#include <tuple> +#include <systemd/sd-bus.h> +#include <sdbusplus/server.hpp> + +namespace sdbusplus +{ +namespace xyz +{ +namespace openbmc_project +{ +namespace Logging +{ +namespace Internal +{ +namespace server +{ + +class Manager +{ + public: + /* Define all of the basic class operations: + * Not allowed: + * - Default constructor to avoid nullptrs. + * - Copy operations due to internal unique_ptr. + * Allowed: + * - Move operations. + * - Destructor. + */ + Manager() = delete; + Manager(const Manager&) = delete; + Manager& operator=(const Manager&) = delete; + Manager(Manager&&) = default; + Manager& operator=(Manager&&) = default; + 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(bus::bus& bus, const char* path); + + + + /** @brief Implementation for Commit + * Write the requested error/event entry with its associated metadata fields to flash. + * + * @param[in] transactionId - The unique identifier of the journal entry(ies) to be committed. + * @param[in] errMsg - The error exception message associated with the error event log to be committed. + */ + virtual void commit( + uint64_t transactionId, + std::string errMsg) = 0; + + + + + private: + + /** @brief sd-bus callback for Commit + */ + static int _callback_Commit( + sd_bus_message*, void*, sd_bus_error*); + + + static constexpr auto _interface = "xyz.openbmc_project.Logging.Internal.Manager"; + static const vtable::vtable_t _vtable[]; + sdbusplus::server::interface::interface + _xyz_openbmc_project_Logging_Internal_Manager_interface; + + +}; + + +} // namespace server +} // namespace Internal +} // namespace Logging +} // namespace openbmc_project +} // namespace xyz +} // namespace sdbusplus + |