summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2019-09-11 12:36:07 -0500
committerMatt Spinler <spinler@us.ibm.com>2019-09-27 14:26:15 -0500
commitc8705e2bfcc7582fb7dc89ac1598489712c006f3 (patch)
treeee5feecbbd9379d23f9d5f17e51bd8ea721bbff6 /extensions/openpower-pels
parentb666433986470ba76ed7357ea026db39ad0b404b (diff)
downloadphosphor-logging-c8705e2bfcc7582fb7dc89ac1598489712c006f3.tar.gz
phosphor-logging-c8705e2bfcc7582fb7dc89ac1598489712c006f3.zip
PEL: Interface to collect system data
There are PEL fields that contain information that must be obtained from various places throughout the BMC, such as the machine type/model/SN from VPD, a few types of codes levels, etc. Create a DataInterface class that will provide the APIs for collecting this information. It has an abstract base class so that its functions can be mocked to return specific data in test cases. This commit provides APIs to read and present the machine type-model and machine serial number. These will be used in the FailingMTM and ExtendedUserHeader PEL sections. Signed-off-by: Matt Spinler <spinler@us.ibm.com> Change-Id: Iec41fea8d9510ba711475154f019bd59f0028d2e
Diffstat (limited to 'extensions/openpower-pels')
-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
5 files changed, 294 insertions, 4 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 \
OpenPOWER on IntegriCloud