Add power_state implementation
Added power_state implementation for multi host platform
specific shutdown interfaces like hard shutdown or soft
shutdown interfaces.
Getting the current host state of all the hosts and set
power_state values based on the hosts current host state.
TESTED : Verified the Shutdown alarms trigged and platform
specific actions done in Facebook YosemiteV2 platform.
Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
Change-Id: I5e38bb9f28b7840c9de10082905b31deb8ffc4ff
diff --git a/configure.ac b/configure.ac
index 2cc5221..f2be82d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -97,6 +97,21 @@
AM_CONDITIONAL([WANT_MONITOR], [test "x$enable_monitor" != "xno"])
AM_CONDITIONAL([WANT_SENSOR_MONITOR], [test "x$enable_sensor_monitor" == "xyes"])
+
+AC_ARG_ENABLE([host-state],
+ AS_HELP_STRING([--enable-host-state], [Enable host state]))
+
+AM_CONDITIONAL([WANT_HOST_STATE], [test "x$enable_host_state" == "xyes"])
+
+AM_COND_IF([WANT_HOST_STATE],
+ [
+ AM_CONDITIONAL(HOST_STATE_ENABLED, true)
+ ],
+ [
+ AM_CONDITIONAL(HOST_STATE_ENABLED, false)
+ ]
+)
+
# Package specific checks.
AS_IF([test "x$enable_presence" != "xno"], [
# Use runtime(json) config, otherwise default to compile time(yaml) config
diff --git a/power_state.hpp b/power_state.hpp
index dc74707..ad8a0d5 100644
--- a/power_state.hpp
+++ b/power_state.hpp
@@ -5,9 +5,13 @@
#include <fmt/format.h>
#include <phosphor-logging/log.hpp>
+#include <xyz/openbmc_project/State/Host/server.hpp>
#include <functional>
+using HostState =
+ sdbusplus::xyz::openbmc_project::State::server::Host::HostState;
+
namespace phosphor::fan
{
@@ -221,4 +225,149 @@
sdbusplus::bus::match::match _match;
};
+/**
+ * @class HostPowerState
+ *
+ * This class implements the PowerState API by looking at the 'powerState'
+ * property on the phosphor virtual sensor interface.
+ */
+class HostPowerState : public PowerState
+{
+ public:
+ virtual ~HostPowerState() = default;
+ HostPowerState(const HostPowerState&) = delete;
+ HostPowerState& operator=(const HostPowerState&) = delete;
+ HostPowerState(HostPowerState&&) = delete;
+ HostPowerState& operator=(HostPowerState&&) = delete;
+
+ HostPowerState() :
+ PowerState(),
+ _match(_bus,
+ sdbusplus::bus::match::rules::propertiesChangedNamespace(
+ _hostStatePath, _hostStateInterface),
+ [this](auto& msg) { this->hostStateChanged(msg); })
+ {
+ readHostState();
+ }
+
+ /**
+ * @brief Constructor
+ *
+ * @param[in] bus - The D-Bus bus connection object
+ * @param[in] callback - The function that should be run when
+ * the power state changes
+ */
+ HostPowerState(sdbusplus::bus::bus& bus, StateChangeFunc func) :
+ PowerState(bus, func),
+ _match(_bus,
+ sdbusplus::bus::match::rules::propertiesChangedNamespace(
+ _hostStatePath, _hostStateInterface),
+ [this](auto& msg) { this->hostStateChanged(msg); })
+ {
+ readHostState();
+ }
+
+ /**
+ * @brief PropertiesChanged callback for the CurrentHostState property.
+ *
+ * Will call the registered callback function if necessary.
+ *
+ * @param[in] msg - The payload of the propertiesChanged signal
+ */
+ void hostStateChanged(sdbusplus::message::message& msg)
+ {
+ std::string interface;
+ std::map<std::string, std::variant<std::string>> properties;
+ std::vector<HostState> hostPowerStates;
+
+ msg.read(interface, properties);
+
+ auto hostStateProp = properties.find(_hostStateProperty);
+ if (hostStateProp != properties.end())
+ {
+ auto currentHostState =
+ sdbusplus::message::convert_from_string<HostState>(
+ std::get<std::string>(hostStateProp->second));
+
+ if (!currentHostState)
+ {
+ throw sdbusplus::exception::InvalidEnumString();
+ }
+ HostState hostState = *currentHostState;
+
+ hostPowerStates.emplace_back(hostState);
+ setHostPowerState(hostPowerStates);
+ }
+ }
+
+ private:
+ void setHostPowerState(std::vector<HostState>& hostPowerStates)
+ {
+ bool powerStateflag = false;
+ for (const auto& powerState : hostPowerStates)
+ {
+ if (powerState == HostState::Standby ||
+ powerState == HostState::Running ||
+ powerState == HostState::TransitioningToRunning ||
+ powerState == HostState::Quiesced ||
+ powerState == HostState::DiagnosticMode)
+ {
+ powerStateflag = true;
+ break;
+ }
+ }
+ setPowerState(powerStateflag);
+ }
+
+ /**
+ * @brief Reads the CurrentHostState property from D-Bus and saves it.
+ */
+ void readHostState()
+ {
+
+ std::string hostStatePath;
+ std::string hostStateService;
+ std::string hostService = "xyz.openbmc_project.State.Host";
+ std::vector<HostState> hostPowerStates;
+
+ int32_t depth = 0;
+ const std::string path = "/";
+
+ auto mapperResponse = util::SDBusPlus::getSubTreeRaw(
+ _bus, path, _hostStateInterface, depth);
+
+ for (const auto& path : mapperResponse)
+ {
+ for (const auto& service : path.second)
+ {
+ hostStateService = service.first;
+
+ if (hostStateService.find(hostService) != std::string::npos)
+ {
+ hostStatePath = path.first;
+
+ auto currentHostState =
+ util::SDBusPlus::getProperty<HostState>(
+ hostStateService, hostStatePath,
+ _hostStateInterface, _hostStateProperty);
+
+ hostPowerStates.emplace_back(currentHostState);
+ }
+ }
+ }
+ setHostPowerState(hostPowerStates);
+ }
+
+ const std::string _hostStatePath{"/xyz/openbmc_project/state"};
+
+ /** @brief D-Bus interface constant */
+ const std::string _hostStateInterface{"xyz.openbmc_project.State.Host"};
+
+ /** @brief D-Bus property constant */
+ const std::string _hostStateProperty{"CurrentHostState"};
+
+ /** @brief The propertiesChanged match */
+ sdbusplus::bus::match::match _match;
+};
+
} // namespace phosphor::fan
diff --git a/sensor-monitor/Makefile.am b/sensor-monitor/Makefile.am
index 313c59f..16333ab 100644
--- a/sensor-monitor/Makefile.am
+++ b/sensor-monitor/Makefile.am
@@ -26,3 +26,8 @@
$(PHOSPHOR_LOGGING_CFLAGS) \
${PHOSPHOR_DBUS_INTERFACES_CFLAGS} \
-flto
+
+if HOST_STATE_ENABLED
+ENABLE_HOST_STATE = 1
+sensor_monitor_CXXFLAGS+=-DENABLE_HOST_STATE
+endif
diff --git a/sensor-monitor/main.cpp b/sensor-monitor/main.cpp
index 8f1cc56..fc9967f 100644
--- a/sensor-monitor/main.cpp
+++ b/sensor-monitor/main.cpp
@@ -28,8 +28,13 @@
auto bus = sdbusplus::bus::new_default();
bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
+#ifdef ENABLE_HOST_STATE
+ std::shared_ptr<phosphor::fan::PowerState> powerState =
+ std::make_shared<phosphor::fan::HostPowerState>();
+#else
std::shared_ptr<phosphor::fan::PowerState> powerState =
std::make_shared<phosphor::fan::PGoodState>();
+#endif
ShutdownAlarmMonitor shutdownMonitor{bus, event, powerState};