monitor: Read fan state from dbus inventory upon starting
tach sensors previously defaulted to functional. Now they default to the
inventory state. For counter-based sensors, nonfunctional state forces
the count to exceed the threshold.
Fan's functional state now depends on the number of functional sensors.
test plan:
1) power-off chassis, stop phosphor-fan-monitor service
2) use busctl to make a fan's tach sensor nonfunctional
3) start fan-monitor
4) verify the fan's state == nonfunctional
5) poweron chassis, verify that fan-monitor updates _sensor_ to
functional
6) fan should remain nonfunctional
7) set Fan to non-present, then to present again (simulate
replacement)
8) observe the fans functional state is now true in inventory
Signed-off-by: Mike Capps <mikepcapps@gmail.com>
Change-Id: I0a109a1d85390c0201f8a54942efcd2fb21a2b65
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index 342b07b..b3cc2a0 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -64,10 +64,6 @@
_fanMissingErrorDelay(std::get<fanMissingErrDelayField>(def)),
_setFuncOnPresent(std::get<funcOnPresentField>(def))
{
- // Start from a known state of functional (even if
- // _numSensorFailsForNonFunc is 0)
- updateInventory(true);
-
// Setup tach sensors for monitoring
auto& sensors = std::get<sensorListField>(def);
for (auto& s : sensors)
@@ -84,6 +80,12 @@
_trustManager->registerSensor(_sensors.back());
}
+ bool functionalState =
+ (_numSensorFailsForNonFunc == 0) ||
+ (countNonFunctionalSensors() < _numSensorFailsForNonFunc);
+
+ updateInventory(functionalState);
+
#ifndef MONITOR_USE_JSON
// Check current tach state when entering monitor mode
if (mode != Mode::init)
@@ -337,7 +339,7 @@
return target;
}
-size_t Fan::countNonFunctionalSensors()
+size_t Fan::countNonFunctionalSensors() const
{
return std::count_if(_sensors.begin(), _sensors.end(),
[](const auto& s) { return !s->functional(); });
diff --git a/monitor/fan.hpp b/monitor/fan.hpp
index a932db2..713a1a1 100644
--- a/monitor/fan.hpp
+++ b/monitor/fan.hpp
@@ -196,7 +196,7 @@
/**
* @brief Returns the number sensors that are nonfunctional
*/
- size_t countNonFunctionalSensors();
+ size_t countNonFunctionalSensors() const;
/**
* @brief Updates the Functional property in the inventory
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index f110722..cc35c97 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -82,8 +82,39 @@
_timer(event, std::bind(&Fan::updateState, &fan, std::ref(*this))),
_errorDelay(errorDelay), _countInterval(countInterval)
{
- // Start from a known state of functional
- setFunctional(true);
+ // Query functional state from inventory
+ // TODO - phosphor-fan-presence/issues/25
+ auto service = util::SDBusPlus::getService(
+ _bus, util::INVENTORY_PATH + _invName, util::OPERATIONAL_STATUS_INTF);
+
+ try
+ {
+ if (!service.empty())
+ {
+ _functional = util::SDBusPlus::getProperty<bool>(
+ service, util::INVENTORY_PATH + _invName,
+ util::OPERATIONAL_STATUS_INTF, util::FUNCTIONAL_PROPERTY);
+ }
+ else
+ {
+ // default to functional when service not up. Error handling done
+ // later
+ _functional = true;
+ updateInventory(_functional);
+ }
+ }
+ catch (util::DBusError& e)
+ {
+ log<level::DEBUG>(e.what());
+ _functional = true;
+ updateInventory(_functional);
+ }
+
+ if (!_functional && MethodMode::count == _method)
+ {
+ // force continual nonfunctional state
+ _counter = _threshold;
+ }
// Load in current Target and Input values when entering monitor mode
#ifndef MONITOR_USE_JSON
diff --git a/sdbusplus.hpp b/sdbusplus.hpp
index 1f2839f..73af8b0 100644
--- a/sdbusplus.hpp
+++ b/sdbusplus.hpp
@@ -253,20 +253,27 @@
return mapperResp;
}
- /** @brief Get service from the mapper. */
- static auto getService(sdbusplus::bus::bus& bus, const std::string& path,
- const std::string& interface)
+ /** @brief Get service from the mapper without checking response. */
+ static auto getServiceRaw(sdbusplus::bus::bus& bus, const std::string& path,
+ const std::string& interface)
{
using namespace std::literals::string_literals;
using GetObject = std::map<std::string, std::vector<std::string>>;
+ return callMethodAndRead<GetObject>(
+ bus, "xyz.openbmc_project.ObjectMapper"s,
+ "/xyz/openbmc_project/object_mapper"s,
+ "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path,
+ GetObject::mapped_type{interface});
+ }
+
+ /** @brief Get service from the mapper. */
+ static auto getService(sdbusplus::bus::bus& bus, const std::string& path,
+ const std::string& interface)
+ {
try
{
- auto mapperResp = callMethodAndRead<GetObject>(
- bus, "xyz.openbmc_project.ObjectMapper"s,
- "/xyz/openbmc_project/object_mapper"s,
- "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path,
- GetObject::mapped_type{interface});
+ auto mapperResp = getServiceRaw(bus, path, interface);
if (mapperResp.empty())
{