fault-monitor: Add OperationalStatus Functional monitoring
Currently, the default way is to update the Asserted property of
the LedManager by monitoring the `/xyz/openbmc_project/logging`
object path.
The intent behind this commit is to add another way to monitor the
`xyz.openbmc_project.State.Decorator.OperationalStatus` interface
of the Inventory D-Bus object, and check whether the Inventory
D-Bus object is associated with the LED group D-Bus object, and
then update the Asserted property of the LedManager.
Since both these methods handle the faults differently,
Only ONE of these 2 methods can be enabled and NOT both.
The first way is supported by default. To turn OFF the default way
AND turn ON this second way, Enable monitor-operational-status.
Tested:
- enable `monitor-operational-status` in bbappend file, built successfully.
- Before changing the `OperationalStatus` interface:
busctl get-property xyz.openbmc_project.Inventory.Manager
/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
xyz.openbmc_project.State.Decorator.OperationalStatus Functional
b true
busctl get-property xyz.openbmc_project.LED.GroupManager
/xyz/openbmc_project/led/groups/powersupply1_fault
xyz.openbmc_project.Led.Group Asserted
b false
busctl get-property xyz.openbmc_project.LED.Controller.front_psu
/xyz/openbmc_project/led/physical/front_psu xyz.openbmc_project.Led.Physical State
s "xyz.openbmc_project.Led.Physical.Action.Off"
- After changing the `OperationalStatus` interface:
busctl set-property xyz.openbmc_project.Inventory.
/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
xyz.openbmc_project.State.Decorator.OperationalStatus Functional b false
busctl get-property xyz.openbmc_project.Inventory.Manager
/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
xyz.openbmc_project.State.Decorator.OperationalStatus Functional
b false
(
If we have more than 1 LED Group D-Bus object:
Like: The system/chassis/motherboard/powersupply1 path contains
two sets of LEDGroup
{
"types":
{
"rType": "fru",
"fType": "fault_led_group"
},
"paths":
[
"/xyz/openbmc_project/led/groups/powersupply0_fault",
"/xyz/openbmc_project/led/groups/powersupply1_fault"
]
}
busctl get-property xyz.openbmc_project.LED.GroupManager
/xyz/openbmc_project/led/groups/powersupply0_fault xyz.openbmc_project.Led.Group Asserted
b true
)
busctl get-property xyz.openbmc_project.LED.GroupManager
/xyz/openbmc_project/led/groups/powersupply1_fault xyz.openbmc_project.Led.Group Asserted
b true
busctl get-property xyz.openbmc_project.LED.Controller.front_psu
/xyz/openbmc_project/led/physical/front_psu xyz.openbmc_project.Led.Physical State
s "xyz.openbmc_project.Led.Physical.Action.Blink"
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I36c47198168028ea2b55804cf66d0285847afbd4
diff --git a/configure.ac b/configure.ac
index 4a50e38..f76cdb7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,14 @@
AC_DEFINE([LED_USE_JSON],[],[Enable JSON configuration.])
)
+# enable OperationalStatus monitor
+AC_ARG_ENABLE([monitor-operational-status],
+ AS_HELP_STRING([--enable-monitor-operational-status], [Enable OperationalStatus monitor.]))
+AM_CONDITIONAL([WANTS_OPERATIONAL_STATUS], [test "x$enable_monitor_operational_status" == "xyes"])
+AS_IF([test "x$enable_monitor_operational_status" == "xyes"],
+ AC_DEFINE([MONITOR_OPERATIONAL_STATUS],[],[Enable OperationalStatus monitor.])
+)
+
# enable lamp test configuration
AC_ARG_ENABLE([use-lamp-test],
AS_HELP_STRING([--enable-use-lamp-test], [Enable lamp test configuration.]))
diff --git a/fault-monitor/Makefile.am b/fault-monitor/Makefile.am
index eae105c..7ae4263 100644
--- a/fault-monitor/Makefile.am
+++ b/fault-monitor/Makefile.am
@@ -1,16 +1,28 @@
AM_DEFAULT_SOURCE_EXT = .cpp
AM_CPPFLAGS = -I$(top_srcdir)
+if WANTS_OPERATIONAL_STATUS
+noinst_HEADERS = operational-status-monitor.hpp
+else
noinst_HEADERS = fru-fault-monitor.hpp
+endif
bin_PROGRAMS = phosphor-fru-fault-monitor
phosphor_fru_fault_monitor_SOURCES = \
- fru-fault-monitor.cpp \
monitor-main.cpp \
xyz/openbmc_project/Led/Mapper/error.cpp \
xyz/openbmc_project/Led/Fru/Monitor/error.cpp
+if WANTS_OPERATIONAL_STATUS
+phosphor_fru_fault_monitor_SOURCES += \
+ ../utils.cpp \
+ operational-status-monitor.cpp
+else
+phosphor_fru_fault_monitor_SOURCES += \
+ fru-fault-monitor.cpp
+endif
+
BUILT_SOURCES = xyz/openbmc_project/Led/Mapper/error.hpp \
xyz/openbmc_project/Led/Mapper/error.cpp \
xyz/openbmc_project/Led/Fru/Monitor/error.hpp \
diff --git a/fault-monitor/monitor-main.cpp b/fault-monitor/monitor-main.cpp
index 0b4a5fb..f4e2182 100644
--- a/fault-monitor/monitor-main.cpp
+++ b/fault-monitor/monitor-main.cpp
@@ -1,11 +1,21 @@
+#include "config.h"
+
+#ifdef MONITOR_OPERATIONAL_STATUS
+#include "operational-status-monitor.hpp"
+#else
#include "fru-fault-monitor.hpp"
+#endif
int main(void)
{
/** @brief Dbus constructs used by Fault Monitor */
sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
+#ifdef MONITOR_OPERATIONAL_STATUS
+ phosphor::led::Operational::status::monitor::Monitor monitor(bus);
+#else
phosphor::led::fru::fault::monitor::Add monitor(bus);
+#endif
/** @brief Wait for client requests */
while (true)
{
diff --git a/fault-monitor/operational-status-monitor.cpp b/fault-monitor/operational-status-monitor.cpp
new file mode 100644
index 0000000..7a6595f
--- /dev/null
+++ b/fault-monitor/operational-status-monitor.cpp
@@ -0,0 +1,113 @@
+#include "operational-status-monitor.hpp"
+
+#include <phosphor-logging/elog.hpp>
+
+namespace phosphor
+{
+namespace led
+{
+namespace Operational
+{
+namespace status
+{
+namespace monitor
+{
+using namespace phosphor::logging;
+
+void Monitor::matchHandler(sdbusplus::message::message& msg)
+{
+ // Get the ObjectPath of the `xyz.openbmc_project.Inventory.Manager`
+ // service
+ std::string invObjectPath = msg.get_path();
+
+ // Get all the properties of
+ // "xyz.openbmc_project.State.Decorator.OperationalStatus" interface
+ std::string interfaceName{};
+ std::map<std::string, std::variant<bool>> properties;
+ msg.read(interfaceName, properties);
+
+ const auto it = properties.find("Functional");
+ if (it != properties.end())
+ {
+ const bool* value = std::get_if<bool>(&it->second);
+ if (!value)
+ {
+ log<level::ERR>("Faild to get the Functional property",
+ entry("INVENTORY_PATH=%s", invObjectPath.c_str()));
+ return;
+ }
+
+ // See if the Inventory D-Bus object has an association with LED groups
+ // D-Bus object.
+ auto ledGroupPath = getLedGroupPaths(invObjectPath);
+ if (ledGroupPath.empty())
+ {
+ log<level::INFO>("The inventory D-Bus object is not associated "
+ "with the LED group D-Bus object.",
+ entry("INVENTORY_PATH=%s", invObjectPath.c_str()));
+ return;
+ }
+
+ // Update the Asserted property by the Functional property value.
+ updateAssertedProperty(ledGroupPath, *value);
+ }
+}
+
+const std::vector<std::string>
+ Monitor::getLedGroupPaths(const std::string& inventoryPath) const
+{
+ // Get endpoints from the rType
+ std::string faultLedAssociation = inventoryPath + "/fault_led_group";
+
+ // endpoint contains the vector of strings, where each string is a Inventory
+ // D-Bus object that this, associated with this LED Group D-Bus object
+ // pointed to by fru_fault
+ PropertyValue endpoint{};
+
+ try
+ {
+ endpoint = dBusHandler.getProperty(faultLedAssociation,
+ "xyz.openbmc_project.Association",
+ "endpoints");
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Failed to get endpoints property",
+ entry("ERROR=%s", e.what()),
+ entry("PATH=%s", faultLedAssociation.c_str()));
+
+ return {};
+ }
+
+ auto& endpoints = std::get<std::vector<std::string>>(endpoint);
+
+ return endpoints;
+}
+
+void Monitor::updateAssertedProperty(
+ const std::vector<std::string>& ledGroupPaths, bool value)
+{
+ for (const auto& path : ledGroupPaths)
+ {
+ try
+ {
+ // Call "Group Asserted --> true" if the value of Functional is
+ // false Call "Group Asserted --> false" if the value of Functional
+ // is true
+ PropertyValue assertedValue{!value};
+ dBusHandler.setProperty(path, "xyz.openbmc_project.Led.Group",
+ "Asserted", assertedValue);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Failed to set Asserted property",
+ entry("ERROR=%s", e.what()),
+ entry("PATH=%s", path.c_str()));
+ }
+ }
+}
+} // namespace monitor
+} // namespace status
+} // namespace Operational
+} // namespace led
+} // namespace phosphor
diff --git a/fault-monitor/operational-status-monitor.hpp b/fault-monitor/operational-status-monitor.hpp
new file mode 100644
index 0000000..ccf65a5
--- /dev/null
+++ b/fault-monitor/operational-status-monitor.hpp
@@ -0,0 +1,99 @@
+#pragma once
+
+#include "../utils.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server.hpp>
+
+namespace phosphor
+{
+namespace led
+{
+namespace Operational
+{
+namespace status
+{
+namespace monitor
+{
+using namespace phosphor::led::utils;
+
+/** @class Monitor
+ * @brief Implementation of LED handling during the change of the Functional
+ * property of the OperationalStatus interface
+ *
+ * @details This implements methods for watching OperationalStatus interface of
+ * Inventory D-Bus object and then assert corresponding LED Group
+ * D-Bus objects.
+ */
+class Monitor
+{
+ public:
+ Monitor() = delete;
+ ~Monitor() = default;
+ Monitor(const Monitor&) = delete;
+ Monitor& operator=(const Monitor&) = delete;
+ Monitor(Monitor&&) = default;
+ Monitor& operator=(Monitor&&) = default;
+
+ /** @brief Add a watch for OperationalStatus.
+ *
+ * @param[in] bus - D-Bus object
+ */
+ Monitor(sdbusplus::bus::bus& bus) :
+ bus(bus),
+ matchSignal(bus,
+ "type='signal',member='PropertiesChanged', "
+ "interface='org.freedesktop.DBus.Properties', "
+ "sender='xyz.openbmc_project.Inventory.Manager', "
+ "arg0namespace='xyz.openbmc_project.State.Decorator."
+ "OperationalStatus'",
+ std::bind(std::mem_fn(&Monitor::matchHandler), this,
+ std::placeholders::_1))
+
+ {}
+
+ private:
+ /** @brief sdbusplus D-Bus connection. */
+ sdbusplus::bus::bus& bus;
+
+ /** @brief sdbusplus signal matches for Monitor */
+ sdbusplus::bus::match_t matchSignal;
+
+ /** DBusHandler class handles the D-Bus operations */
+ DBusHandler dBusHandler;
+
+ /**
+ * @brief Callback handler that gets invoked when the PropertiesChanged
+ * signal is caught by this app. Message is scanned for Inventory
+ * D-Bus object path and if OperationalStatus::Functional is changed,
+ * then corresponding LED Group D-Bus object is called to assert.
+ *
+ * @param[in] msg - The D-Bus message contents
+ */
+ void matchHandler(sdbusplus::message::message& msg);
+
+ /**
+ * @brief From the Inventory D-Bus object, obtains the associated LED group
+ * D-Bus object, where the association name is "fault_led_group"
+ *
+ * @param[in] inventoryPath - Inventory D-Bus object path
+ *
+ * @return std::vector<std::string> - Vector of LED Group D-Bus object paths
+ */
+ const std::vector<std::string>
+ getLedGroupPaths(const std::string& inventoryPath) const;
+
+ /**
+ * @brief Update the Asserted property of the LED Group Manager.
+ *
+ * @param[in] ledGroupPaths - LED Group D-Bus object Paths
+ * @param[in] value - The Asserted property value, True / False
+ */
+ void updateAssertedProperty(const std::vector<std::string>& ledGroupPaths,
+ bool value);
+};
+} // namespace monitor
+} // namespace status
+} // namespace Operational
+} // namespace led
+} // namespace phosphor