watchdog: Support multiple timeout actions
This change adds the infrastructure to support having different actions
map to different systemd targets being started when the watchdog
expires. Right now this maintains compatability with the current
--target argument and populates all of the watchdog actions, except for
None, with the same target. A follow up patch will implement setting
independent targets for each action.
Change-Id: I0f0601f9e94d488650f20a9cebfc7c967007d78c
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/mainapp.cpp b/mainapp.cpp
index 5819fb4..6cc3fdf 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -22,9 +22,12 @@
#include "argument.hpp"
#include "watchdog.hpp"
+using phosphor::watchdog::ArgumentParser;
+using phosphor::watchdog::Watchdog;
+
static void exitWithError(const char* err, char** argv)
{
- phosphor::watchdog::ArgumentParser::usage(argv);
+ ArgumentParser::usage(argv);
std::cerr << "ERROR: " << err << "\n";
exit(EXIT_FAILURE);
}
@@ -35,7 +38,7 @@
using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
Error::InternalFailure;
// Read arguments.
- auto options = phosphor::watchdog::ArgumentParser(argc, argv);
+ auto options = ArgumentParser(argc, argv);
// Parse out continue argument.
auto continueParam = (options)["continue"];
@@ -78,7 +81,13 @@
{
exitWithError("Multiple targets specified.", argv);
}
- auto target = targetParam.back();
+ std::map<Watchdog::Action, Watchdog::TargetName> actionTargets;
+ if (!targetParam.empty()) {
+ auto target = targetParam.back();
+ actionTargets[Watchdog::Action::HardReset] = target;
+ actionTargets[Watchdog::Action::PowerOff] = target;
+ actionTargets[Watchdog::Action::PowerCycle] = target;
+ }
sd_event* event = nullptr;
auto r = sd_event_default(&event);
@@ -102,8 +111,7 @@
try
{
// Create a watchdog object
- phosphor::watchdog::Watchdog watchdog(bus, path.c_str(),
- eventP, std::move(target));
+ Watchdog watchdog(bus, path.c_str(), eventP, std::move(actionTargets));
// Claim the bus
bus.request_name(service.c_str());
diff --git a/watchdog.cpp b/watchdog.cpp
index d0dc7f0..c948d27 100644
--- a/watchdog.cpp
+++ b/watchdog.cpp
@@ -97,18 +97,27 @@
// Optional callback function on timer expiration
void Watchdog::timeOutHandler()
{
- if (!target.empty())
- {
- auto method = bus.new_method_call(SYSTEMD_SERVICE,
- SYSTEMD_ROOT,
- SYSTEMD_INTERFACE,
- "StartUnit");
- method.append(target);
- method.append("replace");
+ auto action = expireAction();
+ auto target = actionTargets.find(action);
- bus.call_noreply(method);
+ if (target == actionTargets.end())
+ {
+ log<level::INFO>("watchdog: Timed out with no target",
+ entry("ACTION=%s", convertForMessage(action).c_str()));
+ return;
}
- return;
+
+ auto method = bus.new_method_call(SYSTEMD_SERVICE,
+ SYSTEMD_ROOT,
+ SYSTEMD_INTERFACE,
+ "StartUnit");
+ method.append(target->second);
+ method.append("replace");
+
+ log<level::INFO>("watchdog: Timed out",
+ entry("ACTION=%s", convertForMessage(action).c_str()),
+ entry("TARGET=%s", target->second.c_str()));
+ bus.call_noreply(method);
}
} // namespace watchdog
diff --git a/watchdog.hpp b/watchdog.hpp
index f9657ac..757029c 100644
--- a/watchdog.hpp
+++ b/watchdog.hpp
@@ -27,20 +27,25 @@
Watchdog(Watchdog&&) = delete;
Watchdog& operator=(Watchdog &&) = delete;
+ /** @brief Type used to hold the name of a systemd target.
+ */
+ using TargetName = std::string;
+
/** @brief Constructs the Watchdog object
*
- * @param[in] bus - DBus bus to attach to.
- * @param[in] objPath - Object path to attach to.
- * @param[in] event - reference to sd_event unique pointer
- * @param[in] target - systemd target to be called into on timeout
+ * @param[in] bus - DBus bus to attach to.
+ * @param[in] objPath - Object path to attach to.
+ * @param[in] event - reference to sd_event unique pointer
+ * @param[in] actionTargets - map of systemd targets called on timeout
*/
Watchdog(sdbusplus::bus::bus& bus,
const char* objPath,
EventPtr& event,
- std::string&& target = std::string()) :
+ std::map<Action, TargetName>&& actionTargets =
+ std::map<Action, TargetName>()) :
WatchdogInherits(bus, objPath),
bus(bus),
- target(std::move(target)),
+ actionTargets(std::move(actionTargets)),
timer(event, std::bind(&Watchdog::timeOutHandler, this))
{
// Nothing
@@ -92,8 +97,8 @@
/** @brief sdbusplus handle */
sdbusplus::bus::bus& bus;
- /** @brief Systemd unit to be started when the timer expires */
- std::string target;
+ /** @brief Map of systemd units to be started when the timer expires */
+ std::map<Action, TargetName> actionTargets;
/** @brief Contained timer object */
Timer timer;