monitor: Use only init mode when using JSON
Fan monitor is currently split into 2 modes - 'init' which is used
right after a power on, and 'monitor', which is used later after the
fans-ready target is started. Normally, the 'init' mode just sets the
fans to functional and then exits, and the real monitoring work is done
in the 'monitor' mode.
In the future this application will need to be able to check for fan
problems as soon as it starts up after power on so that it can handle
shutting down due to missing fans. To prepare for this, move all
functionality into the init mode, and just exit immediately when called
to run in the monitor mode. Only do this when compiled to use the JSON
configuration, as this is new and I don't want to change how the
existing YAML setups work.
This also creates a new 'monitor_start_delay' entry in the JSON to say
how long to wait after startup before actually doing any sensor
monitoring, which then gives the same behavior as how the monitor mode
would delay by waiting for the fan control ready target, which itself is
started by fan control --init after a hardcoded delay. This field is
optional to preserve backwards compatibility and defaults to 0s.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I623a233f50233e734f50cd9e80139c60467518d8
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index 3b12905..525a22b 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -16,6 +16,7 @@
#include "fan.hpp"
#include "sdbusplus.hpp"
+#include "system.hpp"
#include "types.hpp"
#include "utility.hpp"
@@ -33,14 +34,21 @@
{
using namespace phosphor::logging;
+using namespace sdbusplus::bus::match;
Fan::Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
- std::unique_ptr<trust::Manager>& trust, const FanDefinition& def) :
+ std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
+ System& system) :
_bus(bus),
_name(std::get<fanNameField>(def)),
_deviation(std::get<fanDeviationField>(def)),
_numSensorFailsForNonFunc(std::get<numSensorFailsForNonfuncField>(def)),
- _trustManager(trust)
+ _trustManager(trust),
+#ifdef MONITOR_USE_JSON
+ _monitorDelay(std::get<monitorStartDelayField>(def)),
+ _monitorTimer(event, std::bind(std::mem_fn(&Fan::startMonitor), this)),
+#endif
+ _system(system)
{
// Start from a known state of functional
updateInventory(true);
@@ -70,20 +78,39 @@
}
}
+#ifndef MONITOR_USE_JSON
// Check current tach state when entering monitor mode
if (mode != Mode::init)
{
+ _monitorReady = true;
+
// The TachSensors will now have already read the input
// and target values, so check them.
tachChanged();
}
+#else
+ // If it used the JSON config, then it also will do all the work
+ // out of fan-monitor-init, after _monitorDelay.
+ _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
+
+#endif
+}
+
+void Fan::startMonitor()
+{
+ _monitorReady = true;
+
+ tachChanged();
}
void Fan::tachChanged()
{
- for (auto& s : _sensors)
+ if (_monitorReady)
{
- tachChanged(*s);
+ for (auto& s : _sensors)
+ {
+ tachChanged(*s);
+ }
}
}
diff --git a/monitor/fan.hpp b/monitor/fan.hpp
index 603be10..537d8fd 100644
--- a/monitor/fan.hpp
+++ b/monitor/fan.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "config.h"
+
#include "tach_sensor.hpp"
#include "trust_manager.hpp"
#include "types.hpp"
@@ -17,6 +19,8 @@
namespace monitor
{
+class System;
+
/**
* @class InvalidSensorError
*
@@ -83,9 +87,11 @@
* @param event - event loop reference
* @param trust - the tach trust manager
* @param def - the fan definition structure
+ * @param system - Reference to the system object
*/
Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
- std::unique_ptr<trust::Manager>& trust, const FanDefinition& def);
+ std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
+ System& system);
/**
* @brief Callback function for when an input sensor changes
@@ -157,6 +163,12 @@
void updateInventory(bool functional);
/**
+ * @brief Called by _monitorTimer to start fan monitoring some
+ * amount of time after startup.
+ */
+ void startMonitor();
+
+ /**
* @brief the dbus object
*/
sdbusplus::bus::bus& _bus;
@@ -199,6 +211,29 @@
* The tach trust manager object
*/
std::unique_ptr<trust::Manager>& _trustManager;
+
+#ifdef MONITOR_USE_JSON
+ /**
+ * @brief The number of seconds to wait after startup until
+ * fan sensors should checked against their targets.
+ */
+ size_t _monitorDelay;
+
+ /**
+ * @brief Expires after _monitorDelay to start fan monitoring.
+ */
+ sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer;
+#endif
+
+ /**
+ * @brief Set to true when monitoring can start.
+ */
+ bool _monitorReady = false;
+
+ /**
+ * @brief Reference to the System object
+ */
+ System& _system;
};
} // namespace monitor
diff --git a/monitor/gen-fan-monitor-defs.py b/monitor/gen-fan-monitor-defs.py
index 6793169..43b0bb9 100755
--- a/monitor/gen-fan-monitor-defs.py
+++ b/monitor/gen-fan-monitor-defs.py
@@ -54,6 +54,7 @@
${fan_data['allowed_out_of_range_time']},
${fan_data['deviation']},
${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
+ 0, // Monitor start delay - not used in YAML configs
std::vector<SensorDefinition>{
%for sensor in fan_data['sensors']:
<%
diff --git a/monitor/json_parser.cpp b/monitor/json_parser.cpp
index 227530f..51df226 100644
--- a/monitor/json_parser.cpp
+++ b/monitor/json_parser.cpp
@@ -191,6 +191,13 @@
funcDelay = fan["functional_delay"].get<size_t>();
}
+ // Monitor start delay is optional and defaults to 0
+ size_t monitorDelay = 0;
+ if (fan.contains("monitor_start_delay"))
+ {
+ monitorDelay = fan["monitor_start_delay"].get<size_t>();
+ }
+
// Handle optional conditions
auto cond = std::optional<Condition>();
if (fan.contains("condition"))
@@ -221,13 +228,12 @@
entry("JSON_DUMP=%s", fan["condition"].dump().c_str()));
}
}
-
fanDefs.emplace_back(
std::tuple(fan["inventory"].get<std::string>(), funcDelay,
fan["allowed_out_of_range_time"].get<size_t>(),
fan["deviation"].get<size_t>(),
fan["num_sensors_nonfunc_for_fan_nonfunc"].get<size_t>(),
- sensorDefs, cond));
+ monitorDelay, sensorDefs, cond));
}
return fanDefs;
diff --git a/monitor/main.cpp b/monitor/main.cpp
index 04c4cf9..93a5e1d 100644
--- a/monitor/main.cpp
+++ b/monitor/main.cpp
@@ -54,6 +54,16 @@
return 1;
}
+ // If using JSON, then everything is handled in a single
+ // step - the init step. Hopefully these can eventually be
+ // reduced into a single invocation.
+#ifdef MONITOR_USE_JSON
+ if (mode == Mode::monitor)
+ {
+ return 0;
+ }
+#endif
+
// Attach the event object to the bus object so we can
// handle both sd_events (for the timers) and dbus signals.
bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
@@ -69,11 +79,13 @@
std::placeholders::_2));
#endif
+#ifndef MONITOR_USE_JSON
if (mode == Mode::init)
{
// Fans were initialized to be functional, exit
return 0;
}
+#endif
return event.loop();
}
diff --git a/monitor/system.cpp b/monitor/system.cpp
index 632b0b2..9b93999 100644
--- a/monitor/system.cpp
+++ b/monitor/system.cpp
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "config.h"
-
#include "system.hpp"
#include "fan.hpp"
@@ -118,7 +116,7 @@
}
}
_fans.emplace_back(
- std::make_unique<Fan>(_mode, _bus, _event, _trust, fanDef));
+ std::make_unique<Fan>(_mode, _bus, _event, _trust, fanDef, *this));
}
}
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index 01baada..5e85ba7 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -83,8 +83,10 @@
setFunctional(true);
// Load in current Target and Input values when entering monitor mode
+#ifndef MONITOR_USE_JSON
if (mode != Mode::init)
{
+#endif
try
{
// Use getProperty directly to allow a missing sensor object
@@ -122,7 +124,9 @@
_bus, match.c_str(),
[this](auto& msg) { this->handleTargetChange(msg); });
}
+#ifndef MONITOR_USE_JSON
}
+#endif
}
std::string TachSensor::getMatchString(const std::string& interface)
diff --git a/monitor/types.hpp b/monitor/types.hpp
index 59dcb30..9f69adf 100644
--- a/monitor/types.hpp
+++ b/monitor/types.hpp
@@ -106,11 +106,12 @@
constexpr auto timeoutField = 2;
constexpr auto fanDeviationField = 3;
constexpr auto numSensorFailsForNonfuncField = 4;
-constexpr auto sensorListField = 5;
-constexpr auto conditionField = 6;
+constexpr auto monitorStartDelayField = 5;
+constexpr auto sensorListField = 6;
+constexpr auto conditionField = 7;
using FanDefinition =
- std::tuple<std::string, size_t, size_t, size_t, size_t,
+ std::tuple<std::string, size_t, size_t, size_t, size_t, size_t,
std::vector<SensorDefinition>, std::optional<Condition>>;
} // namespace monitor