blob: 22227cce257c30722b7e1a956d01f54cfe9eeeba [file] [log] [blame]
William A. Kennington III52575252018-02-09 15:54:56 -08001#include "watchdog_service.hpp"
2
Vernon Mauerye08fbff2019-04-03 09:19:34 -07003#include <ipmid/api.hpp>
William A. Kennington IIId5410272018-05-10 11:17:58 -07004#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -07005#include <phosphor-logging/elog.hpp>
William A. Kennington IIId5410272018-05-10 11:17:58 -07006#include <phosphor-logging/log.hpp>
William A. Kennington III52575252018-02-09 15:54:56 -08007#include <sdbusplus/bus.hpp>
8#include <sdbusplus/message.hpp>
William A. Kennington IIId5410272018-05-10 11:17:58 -07009#include <xyz/openbmc_project/Common/error.hpp>
William A. Kennington IIIb638de22018-02-09 16:12:53 -080010#include <xyz/openbmc_project/State/Watchdog/server.hpp>
William A. Kennington III52575252018-02-09 15:54:56 -080011
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050012#include <exception>
13#include <stdexcept>
14#include <string>
15
William A. Kennington IIId5410272018-05-10 11:17:58 -070016using phosphor::logging::elog;
Patrick Venture0b02be92018-08-31 11:55:55 -070017using phosphor::logging::entry;
William A. Kennington IIId5410272018-05-10 11:17:58 -070018using phosphor::logging::level;
19using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -070020using sdbusplus::common::xyz::openbmc_project::state::convertForMessage;
21using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
22using sdbusplus::server::xyz::openbmc_project::state::Watchdog;
William A. Kennington III52575252018-02-09 15:54:56 -080023
24static constexpr char wd_path[] = "/xyz/openbmc_project/watchdog/host0";
25static constexpr char wd_intf[] = "xyz.openbmc_project.State.Watchdog";
26static constexpr char prop_intf[] = "org.freedesktop.DBus.Properties";
27
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070028ipmi::ServiceCache WatchdogService::wd_service(wd_intf, wd_path);
29
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050030WatchdogService::WatchdogService() : bus(ipmid_get_sd_bus_connection()) {}
William A. Kennington III52575252018-02-09 15:54:56 -080031
William A. Kennington III4b017a92018-04-27 14:31:08 -070032void WatchdogService::resetTimeRemaining(bool enableWatchdog)
33{
34 bool wasValid = wd_service.isValid(bus);
Patrick Venture0b02be92018-08-31 11:55:55 -070035 auto request = wd_service.newMethodCall(bus, wd_intf, "ResetTimeRemaining");
William A. Kennington III4b017a92018-04-27 14:31:08 -070036 request.append(enableWatchdog);
George Liu3e3cc352023-07-26 15:59:31 +080037 try
38 {
39 auto response = bus.call(request);
40 }
41 catch (const std::exception& e)
William A. Kennington III4b017a92018-04-27 14:31:08 -070042 {
43 wd_service.invalidate();
44 if (wasValid)
45 {
46 // Retry the request once in case the cached service was stale
47 return resetTimeRemaining(enableWatchdog);
48 }
49 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -070050 "WatchdogService: Method error resetting time remaining",
George Liu3e3cc352023-07-26 15:59:31 +080051 entry("ENABLE_WATCHDOG=%d", !!enableWatchdog),
52 entry("ERROR=%s", e.what()));
William A. Kennington III4b017a92018-04-27 14:31:08 -070053 elog<InternalFailure>();
54 }
55}
56
William A. Kennington III52575252018-02-09 15:54:56 -080057WatchdogService::Properties WatchdogService::getProperties()
58{
William A. Kennington IIIe1628492018-05-11 16:17:28 -070059 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070060 auto request = wd_service.newMethodCall(bus, prop_intf, "GetAll");
William A. Kennington III52575252018-02-09 15:54:56 -080061 request.append(wd_intf);
George Liu3e3cc352023-07-26 15:59:31 +080062
63 std::map<std::string, std::variant<bool, uint64_t, std::string>> properties;
64 try
65 {
66 auto response = bus.call(request);
67 response.read(properties);
68 }
69 catch (const std::exception& e)
William A. Kennington III52575252018-02-09 15:54:56 -080070 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070071 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -070072 if (wasValid)
73 {
74 // Retry the request once in case the cached service was stale
75 return getProperties();
76 }
George Liu3e3cc352023-07-26 15:59:31 +080077 log<level::ERR>("WatchdogService: Method error getting properties",
78 entry("ERROR=%s", e.what()));
William A. Kennington IIId5410272018-05-10 11:17:58 -070079 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -080080 }
George Liu3e3cc352023-07-26 15:59:31 +080081
William A. Kennington III1469f8a2018-05-15 14:40:59 -070082 try
83 {
William A. Kennington III1469f8a2018-05-15 14:40:59 -070084 Properties wd_prop;
Vernon Maueryf442e112019-04-09 11:44:36 -070085 wd_prop.initialized = std::get<bool>(properties.at("Initialized"));
86 wd_prop.enabled = std::get<bool>(properties.at("Enabled"));
William A. Kennington III1469f8a2018-05-15 14:40:59 -070087 wd_prop.expireAction = Watchdog::convertActionFromString(
Vernon Maueryf442e112019-04-09 11:44:36 -070088 std::get<std::string>(properties.at("ExpireAction")));
Yong Li118907e2019-01-11 17:36:17 +080089 wd_prop.timerUse = Watchdog::convertTimerUseFromString(
Vernon Maueryf442e112019-04-09 11:44:36 -070090 std::get<std::string>(properties.at("CurrentTimerUse")));
Yong Li4dd71af2019-09-29 14:18:07 +080091 wd_prop.expiredTimerUse = Watchdog::convertTimerUseFromString(
92 std::get<std::string>(properties.at("ExpiredTimerUse")));
Yong Li118907e2019-01-11 17:36:17 +080093
Vernon Maueryf442e112019-04-09 11:44:36 -070094 wd_prop.interval = std::get<uint64_t>(properties.at("Interval"));
95 wd_prop.timeRemaining =
96 std::get<uint64_t>(properties.at("TimeRemaining"));
William A. Kennington III1469f8a2018-05-15 14:40:59 -070097 return wd_prop;
98 }
99 catch (const std::exception& e)
100 {
101 log<level::ERR>("WatchdogService: Decode error in get properties",
George Liu3e3cc352023-07-26 15:59:31 +0800102 entry("ERROR=%s", e.what()));
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700103 elog<InternalFailure>();
104 }
William A. Kennington III52575252018-02-09 15:54:56 -0800105
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700106 // Needed instead of elog<InternalFailure>() since the compiler can't
107 // deduce the that elog<>() always throws
108 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700109 "WatchdogService: Should not reach end of getProperties");
William A. Kennington III52575252018-02-09 15:54:56 -0800110}
111
112template <typename T>
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700113T WatchdogService::getProperty(const std::string& key)
114{
115 bool wasValid = wd_service.isValid(bus);
116 auto request = wd_service.newMethodCall(bus, prop_intf, "Get");
117 request.append(wd_intf, key);
George Liu3e3cc352023-07-26 15:59:31 +0800118 try
119 {
120 auto response = bus.call(request);
121 std::variant<T> value;
122 response.read(value);
123 return std::get<T>(value);
124 }
125 catch (const std::exception& e)
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700126 {
127 wd_service.invalidate();
128 if (wasValid)
129 {
130 // Retry the request once in case the cached service was stale
131 return getProperty<T>(key);
132 }
133 log<level::ERR>("WatchdogService: Method error getting property",
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700134 entry("PROPERTY=%s", key.c_str()),
George Liu3e3cc352023-07-26 15:59:31 +0800135 entry("ERROR=%s", e.what()));
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700136 elog<InternalFailure>();
137 }
138
139 // Needed instead of elog<InternalFailure>() since the compiler can't
140 // deduce the that elog<>() always throws
141 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700142 "WatchdogService: Should not reach end of getProperty");
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700143}
144
145template <typename T>
William A. Kennington III52575252018-02-09 15:54:56 -0800146void WatchdogService::setProperty(const std::string& key, const T& val)
147{
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700148 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700149 auto request = wd_service.newMethodCall(bus, prop_intf, "Set");
Vernon Maueryf442e112019-04-09 11:44:36 -0700150 request.append(wd_intf, key, std::variant<T>(val));
George Liu3e3cc352023-07-26 15:59:31 +0800151 try
152 {
153 auto response = bus.call(request);
154 }
155 catch (const std::exception& e)
William A. Kennington III52575252018-02-09 15:54:56 -0800156 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700157 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700158 if (wasValid)
159 {
160 // Retry the request once in case the cached service was stale
Chen,Yugang0e862fa2019-09-06 11:03:05 +0800161 setProperty(key, val);
162 return;
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700163 }
William A. Kennington IIId5410272018-05-10 11:17:58 -0700164 log<level::ERR>("WatchdogService: Method error setting property",
George Liu3e3cc352023-07-26 15:59:31 +0800165 entry("PROPERTY=%s", key.c_str()),
166 entry("ERROR=%s", e.what()));
William A. Kennington IIId5410272018-05-10 11:17:58 -0700167 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -0800168 }
169}
170
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700171bool WatchdogService::getInitialized()
172{
173 return getProperty<bool>("Initialized");
174}
175
William A. Kennington IIIde14a022018-02-09 16:11:18 -0800176void WatchdogService::setInitialized(bool initialized)
177{
178 setProperty("Initialized", initialized);
179}
180
William A. Kennington III52575252018-02-09 15:54:56 -0800181void WatchdogService::setEnabled(bool enabled)
182{
183 setProperty("Enabled", enabled);
184}
185
William A. Kennington IIIb638de22018-02-09 16:12:53 -0800186void WatchdogService::setExpireAction(Action expireAction)
187{
188 setProperty("ExpireAction", convertForMessage(expireAction));
189}
190
Yong Li118907e2019-01-11 17:36:17 +0800191void WatchdogService::setTimerUse(TimerUse timerUse)
192{
193 setProperty("CurrentTimerUse", convertForMessage(timerUse));
194}
195
Deepak Kumar Sahucfae9482019-05-20 14:58:58 +0000196void WatchdogService::setExpiredTimerUse(TimerUse timerUse)
197{
198 setProperty("ExpiredTimerUse", convertForMessage(timerUse));
199}
200
William A. Kennington III52575252018-02-09 15:54:56 -0800201void WatchdogService::setInterval(uint64_t interval)
202{
203 setProperty("Interval", interval);
204}