summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/openpower-pels/data_interface.cpp123
-rw-r--r--extensions/openpower-pels/data_interface.hpp155
-rw-r--r--extensions/openpower-pels/entry_points.cpp6
-rw-r--r--extensions/openpower-pels/manager.hpp13
-rw-r--r--extensions/openpower-pels/openpower-pels.mk1
-rw-r--r--test/openpower-pels/Makefile.include1
-rw-r--r--test/openpower-pels/pel_manager_test.cpp4
7 files changed, 298 insertions, 5 deletions
diff --git a/extensions/openpower-pels/data_interface.cpp b/extensions/openpower-pels/data_interface.cpp
new file mode 100644
index 0000000..0b7604b
--- /dev/null
+++ b/extensions/openpower-pels/data_interface.cpp
@@ -0,0 +1,123 @@
+#include "data_interface.hpp"
+
+namespace openpower
+{
+namespace pels
+{
+
+namespace service_name
+{
+constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
+} // namespace service_name
+
+namespace object_path
+{
+constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper";
+constexpr auto systemInv = "/xyz/openbmc_project/inventory/system";
+} // namespace object_path
+
+namespace interface
+{
+constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
+constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
+constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
+} // namespace interface
+
+DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus)
+{
+ readMTMS();
+}
+
+void DataInterface::readMTMS()
+{
+ // If this runs when the inventory service isn't running, it will get the
+ // value whenever it starts via the propertiesChanged callback.
+ try
+ {
+ auto inventoryService =
+ getService(object_path::systemInv, interface::invAsset);
+
+ if (!inventoryService.empty())
+ {
+ auto properties = getAllProperties(
+ inventoryService, object_path::systemInv, interface::invAsset);
+
+ _machineTypeModel = std::get<std::string>(properties["Model"]);
+
+ _machineSerialNumber =
+ std::get<std::string>(properties["SerialNumber"]);
+ }
+ }
+ catch (std::exception& e)
+ {
+ // Inventory must not be running at this moment.
+ }
+
+ // Keep up to date by watching for the propertiesChanged signal.
+ _sysInventoryPropMatch = std::make_unique<sdbusplus::bus::match_t>(
+ _bus,
+ sdbusplus::bus::match::rules::propertiesChanged(object_path::systemInv,
+ interface::invAsset),
+ std::bind(std::mem_fn(&DataInterface::sysAssetPropChanged), this,
+ std::placeholders::_1));
+}
+
+void DataInterface::sysAssetPropChanged(sdbusplus::message::message& msg)
+{
+ DBusInterface interface;
+ DBusPropertyMap properties;
+
+ msg.read(interface, properties);
+
+ auto model = properties.find("Model");
+ if (model != properties.end())
+ {
+ _machineTypeModel = std::get<std::string>(model->second);
+ }
+
+ auto sn = properties.find("SerialNumber");
+ if (sn != properties.end())
+ {
+ _machineSerialNumber = std::get<std::string>(sn->second);
+ }
+}
+
+DBusPropertyMap DataInterface::getAllProperties(const std::string& service,
+ const std::string& objectPath,
+ const std::string& interface)
+{
+ DBusPropertyMap properties;
+
+ auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
+ interface::dbusProperty, "GetAll");
+ method.append(interface);
+ auto reply = _bus.call(method);
+
+ reply.read(properties);
+
+ return properties;
+}
+
+DBusService DataInterface::getService(const std::string& objectPath,
+ const std::string& interface)
+{
+ auto method = _bus.new_method_call(service_name::objectMapper,
+ object_path::objectMapper,
+ interface::objectMapper, "GetObject");
+
+ method.append(objectPath, std::vector<std::string>({interface}));
+
+ auto reply = _bus.call(method);
+
+ std::map<DBusService, DBusInterfaceList> response;
+ reply.read(response);
+
+ if (!response.empty())
+ {
+ return response.begin()->first;
+ }
+
+ return std::string{};
+}
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/data_interface.hpp b/extensions/openpower-pels/data_interface.hpp
new file mode 100644
index 0000000..34bb173
--- /dev/null
+++ b/extensions/openpower-pels/data_interface.hpp
@@ -0,0 +1,155 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+
+namespace openpower
+{
+namespace pels
+{
+
+using DBusValue = sdbusplus::message::variant<std::string>;
+using DBusProperty = std::string;
+using DBusInterface = std::string;
+using DBusService = std::string;
+using DBusPath = std::string;
+using DBusInterfaceList = std::vector<DBusInterface>;
+using DBusPropertyMap = std::map<DBusProperty, DBusValue>;
+
+/**
+ * @class DataInterface
+ *
+ * An abstract interface class for gathering data about the system
+ * for use in PELs. Implemented this way to facilitate mocking.
+ */
+class DataInterfaceBase
+{
+ public:
+ DataInterfaceBase() = default;
+ virtual ~DataInterfaceBase() = default;
+ DataInterfaceBase(const DataInterfaceBase&) = default;
+ DataInterfaceBase& operator=(const DataInterfaceBase&) = default;
+ DataInterfaceBase(DataInterfaceBase&&) = default;
+ DataInterfaceBase& operator=(DataInterfaceBase&&) = default;
+
+ /**
+ * @brief Pure virtual for returning the MTM
+ *
+ * @return string - The machine Type/Model string
+ */
+ virtual std::string getMachineTypeModel() const = 0;
+
+ /**
+ * @brief Pure virtual for returning the machine SN
+ *
+ * @return string - The machine serial number
+ */
+ virtual std::string getMachineSerialNumber() const = 0;
+};
+
+/**
+ * @class DataInterface
+ *
+ * Concrete implementation of DataInterfaceBase.
+ */
+class DataInterface : public DataInterfaceBase
+{
+ public:
+ DataInterface() = delete;
+ ~DataInterface() = default;
+ DataInterface(const DataInterface&) = default;
+ DataInterface& operator=(const DataInterface&) = default;
+ DataInterface(DataInterface&&) = default;
+ DataInterface& operator=(DataInterface&&) = default;
+
+ /**
+ * @brief Constructor
+ *
+ * @param[in] bus - The sdbusplus bus object
+ */
+ explicit DataInterface(sdbusplus::bus::bus& bus);
+
+ /**
+ * @brief Returns the machine type/model value
+ *
+ * @return string - The machine Type/Model string
+ */
+ std::string getMachineTypeModel() const override
+ {
+ return _machineTypeModel;
+ }
+
+ /**
+ * @brief Returns the machine SN
+ *
+ * @return string - The machine serial number
+ */
+ std::string getMachineSerialNumber() const override
+ {
+ return _machineSerialNumber;
+ }
+
+ private:
+ /**
+ * @brief Reads the machine type/model and SN from D-Bus.
+ *
+ * Looks for them on the 'system' inventory object, and also
+ * places a properties changed watch on them to obtain any changes
+ * (or read them for the first time if the inventory isn't ready
+ * when this function runs.)
+ */
+ void readMTMS();
+
+ /**
+ * @brief Finds the D-Bus service name that hosts the
+ * passed in path and interface.
+ *
+ * @param[in] objectPath - The D-Bus object path
+ * @param[in] interface - The D-Bus interface
+ */
+ DBusService getService(const std::string& objectPath,
+ const std::string& interface);
+ /**
+ * @brief Wrapper for the 'GetAll' properties method call
+ *
+ * @param[in] service - The D-Bus service to call it on
+ * @param[in] objectPath - The D-Bus object path
+ * @param[in] interface - The interface to get the props on
+ *
+ * @return DBusPropertyMap - The property results
+ */
+ DBusPropertyMap getAllProperties(const std::string& service,
+ const std::string& objectPath,
+ const std::string& interface);
+
+ /**
+ * @brief The properties changed callback for the Asset iface
+ * on the system inventory object.
+ *
+ * @param[in] msg - The sdbusplus message of the signal
+ */
+ void sysAssetPropChanged(sdbusplus::message::message& msg);
+
+ /**
+ * @brief The machine type-model. Always kept up to date
+ */
+ std::string _machineTypeModel;
+
+ /**
+ * @brief The machine serial number. Always kept up to date
+ */
+ std::string _machineSerialNumber;
+
+ /**
+ * @brief The match object for the system path's properties
+ */
+ std::unique_ptr<sdbusplus::bus::match_t> _sysInventoryPropMatch;
+
+ /**
+ * @brief The sdbusplus bus object for making D-Bus calls.
+ */
+ sdbusplus::bus::bus& _bus;
+};
+
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/entry_points.cpp b/extensions/openpower-pels/entry_points.cpp
index 5adeb40..59a93c1 100644
--- a/extensions/openpower-pels/entry_points.cpp
+++ b/extensions/openpower-pels/entry_points.cpp
@@ -1,3 +1,4 @@
+#include "data_interface.hpp"
#include "elog_entry.hpp"
#include "extensions.hpp"
#include "manager.hpp"
@@ -15,7 +16,10 @@ DISABLE_LOG_ENTRY_CAPS();
void pelStartup(internal::Manager& logManager)
{
- manager = std::make_unique<Manager>(logManager);
+ std::unique_ptr<DataInterfaceBase> dataIface =
+ std::make_unique<DataInterface>(logManager.getBus());
+
+ manager = std::make_unique<Manager>(logManager, std::move(dataIface));
}
REGISTER_EXTENSION_FUNCTION(pelStartup);
diff --git a/extensions/openpower-pels/manager.hpp b/extensions/openpower-pels/manager.hpp
index 3134f23..49ac8bf 100644
--- a/extensions/openpower-pels/manager.hpp
+++ b/extensions/openpower-pels/manager.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "elog_entry.hpp"
+#include "data_interface.hpp"
#include "log_manager.hpp"
#include "paths.hpp"
#include "repository.hpp"
@@ -30,8 +30,10 @@ class Manager
*
* @param[in] logManager - internal::Manager object
*/
- explicit Manager(internal::Manager& logManager) :
- _logManager(logManager), _repo(getPELRepoPath())
+ explicit Manager(phosphor::logging::internal::Manager& logManager,
+ std::unique_ptr<DataInterfaceBase>&& dataIface) :
+ _logManager(logManager),
+ _repo(getPELRepoPath()), _dataIface(std::move(dataIface))
{
}
@@ -104,6 +106,11 @@ class Manager
* @brief The PEL repository object
*/
Repository _repo;
+
+ /**
+ * @brief The API the PEL sections use to gather data
+ */
+ std::unique_ptr<DataInterfaceBase> _dataIface;
};
} // namespace pels
diff --git a/extensions/openpower-pels/openpower-pels.mk b/extensions/openpower-pels/openpower-pels.mk
index 6a58db8..21eb719 100644
--- a/extensions/openpower-pels/openpower-pels.mk
+++ b/extensions/openpower-pels/openpower-pels.mk
@@ -1,5 +1,6 @@
phosphor_log_manager_SOURCES += \
extensions/openpower-pels/bcd_time.cpp \
+ extensions/openpower-pels/data_interface.cpp \
extensions/openpower-pels/entry_points.cpp \
extensions/openpower-pels/log_id.cpp \
extensions/openpower-pels/manager.cpp \
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index 51f3ecc..124970d 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -101,6 +101,7 @@ pel_manager_test_CXXFLAGS = $(test_cxxflags)
pel_manager_test_LDADD = \
$(test_ldadd) \
$(pel_objects) \
+ $(top_builddir)/extensions/openpower-pels/data_interface.o \
$(top_builddir)/extensions/openpower-pels/manager.o \
$(top_builddir)/extensions/openpower-pels/repository.o
pel_manager_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/pel_manager_test.cpp b/test/openpower-pels/pel_manager_test.cpp
index 9d788c9..0a82141 100644
--- a/test/openpower-pels/pel_manager_test.cpp
+++ b/test/openpower-pels/pel_manager_test.cpp
@@ -27,8 +27,10 @@ TEST_F(ManagerTest, TestCreateWithPEL)
{
auto bus = sdbusplus::bus::new_default();
phosphor::logging::internal::Manager logManager(bus, "logging_path");
+ std::unique_ptr<DataInterfaceBase> dataIface =
+ std::make_unique<DataInterface>(bus);
- openpower::pels::Manager manager{logManager};
+ openpower::pels::Manager manager{logManager, std::move(dataIface)};
// Create a PEL, write it to a file, and pass that filename into
// the create function.
OpenPOWER on IntegriCloud