blob: 3534e899036092b38c984022d00cab834e5e32fa [file] [log] [blame]
William A. Kennington III52575252018-02-09 15:54:56 -08001#include "watchdog_service.hpp"
2
William A. Kennington III1469f8a2018-05-15 14:40:59 -07003#include <exception>
Vernon Mauerye08fbff2019-04-03 09:19:34 -07004#include <ipmid/api.hpp>
William A. Kennington IIId5410272018-05-10 11:17:58 -07005#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -07006#include <phosphor-logging/elog.hpp>
William A. Kennington IIId5410272018-05-10 11:17:58 -07007#include <phosphor-logging/log.hpp>
William A. Kennington III52575252018-02-09 15:54:56 -08008#include <sdbusplus/bus.hpp>
9#include <sdbusplus/message.hpp>
William A. Kennington III1469f8a2018-05-15 14:40:59 -070010#include <stdexcept>
William A. Kennington III52575252018-02-09 15:54:56 -080011#include <string>
William A. Kennington IIId5410272018-05-10 11:17:58 -070012#include <xyz/openbmc_project/Common/error.hpp>
William A. Kennington IIIb638de22018-02-09 16:12:53 -080013#include <xyz/openbmc_project/State/Watchdog/server.hpp>
William A. Kennington III52575252018-02-09 15:54:56 -080014
William A. Kennington IIId5410272018-05-10 11:17:58 -070015using phosphor::logging::elog;
Patrick Venture0b02be92018-08-31 11:55:55 -070016using phosphor::logging::entry;
William A. Kennington IIId5410272018-05-10 11:17:58 -070017using phosphor::logging::level;
18using phosphor::logging::log;
William A. Kennington IIId5410272018-05-10 11:17:58 -070019using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
William A. Kennington IIIb638de22018-02-09 16:12:53 -080020using sdbusplus::xyz::openbmc_project::State::server::convertForMessage;
21using sdbusplus::xyz::openbmc_project::State::server::Watchdog;
William A. Kennington III52575252018-02-09 15:54:56 -080022
23static constexpr char wd_path[] = "/xyz/openbmc_project/watchdog/host0";
24static constexpr char wd_intf[] = "xyz.openbmc_project.State.Watchdog";
25static constexpr char prop_intf[] = "org.freedesktop.DBus.Properties";
26
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070027ipmi::ServiceCache WatchdogService::wd_service(wd_intf, wd_path);
28
Patrick Venture0b02be92018-08-31 11:55:55 -070029WatchdogService::WatchdogService() : bus(ipmid_get_sd_bus_connection())
William A. Kennington III52575252018-02-09 15:54:56 -080030{
31}
32
William A. Kennington III4b017a92018-04-27 14:31:08 -070033void WatchdogService::resetTimeRemaining(bool enableWatchdog)
34{
35 bool wasValid = wd_service.isValid(bus);
Patrick Venture0b02be92018-08-31 11:55:55 -070036 auto request = wd_service.newMethodCall(bus, wd_intf, "ResetTimeRemaining");
William A. Kennington III4b017a92018-04-27 14:31:08 -070037 request.append(enableWatchdog);
38 auto response = bus.call(request);
39 if (response.is_method_error())
40 {
41 wd_service.invalidate();
42 if (wasValid)
43 {
44 // Retry the request once in case the cached service was stale
45 return resetTimeRemaining(enableWatchdog);
46 }
47 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -070048 "WatchdogService: Method error resetting time remaining",
49 entry("ENABLE_WATCHDOG=%d", !!enableWatchdog));
William A. Kennington III4b017a92018-04-27 14:31:08 -070050 elog<InternalFailure>();
51 }
52}
53
William A. Kennington III52575252018-02-09 15:54:56 -080054WatchdogService::Properties WatchdogService::getProperties()
55{
William A. Kennington IIIe1628492018-05-11 16:17:28 -070056 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070057 auto request = wd_service.newMethodCall(bus, prop_intf, "GetAll");
William A. Kennington III52575252018-02-09 15:54:56 -080058 request.append(wd_intf);
59 auto response = bus.call(request);
60 if (response.is_method_error())
61 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070062 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -070063 if (wasValid)
64 {
65 // Retry the request once in case the cached service was stale
66 return getProperties();
67 }
William A. Kennington IIId5410272018-05-10 11:17:58 -070068 log<level::ERR>("WatchdogService: Method error getting properties");
69 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -080070 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -070071 try
72 {
Vernon Maueryf442e112019-04-09 11:44:36 -070073 std::map<std::string, std::variant<bool, uint64_t, std::string>>
74 properties;
William A. Kennington III1469f8a2018-05-15 14:40:59 -070075 response.read(properties);
76 Properties wd_prop;
Vernon Maueryf442e112019-04-09 11:44:36 -070077 wd_prop.initialized = std::get<bool>(properties.at("Initialized"));
78 wd_prop.enabled = std::get<bool>(properties.at("Enabled"));
William A. Kennington III1469f8a2018-05-15 14:40:59 -070079 wd_prop.expireAction = Watchdog::convertActionFromString(
Vernon Maueryf442e112019-04-09 11:44:36 -070080 std::get<std::string>(properties.at("ExpireAction")));
Yong Li118907e2019-01-11 17:36:17 +080081 wd_prop.timerUse = Watchdog::convertTimerUseFromString(
Vernon Maueryf442e112019-04-09 11:44:36 -070082 std::get<std::string>(properties.at("CurrentTimerUse")));
Yong Li4dd71af2019-09-29 14:18:07 +080083 wd_prop.expiredTimerUse = Watchdog::convertTimerUseFromString(
84 std::get<std::string>(properties.at("ExpiredTimerUse")));
Yong Li118907e2019-01-11 17:36:17 +080085
Vernon Maueryf442e112019-04-09 11:44:36 -070086 wd_prop.interval = std::get<uint64_t>(properties.at("Interval"));
87 wd_prop.timeRemaining =
88 std::get<uint64_t>(properties.at("TimeRemaining"));
William A. Kennington III1469f8a2018-05-15 14:40:59 -070089 return wd_prop;
90 }
91 catch (const std::exception& e)
92 {
93 log<level::ERR>("WatchdogService: Decode error in get properties",
94 entry("ERROR=%s", e.what()),
95 entry("REPLY_SIG=%s", response.get_signature()));
96 elog<InternalFailure>();
97 }
William A. Kennington III52575252018-02-09 15:54:56 -080098
William A. Kennington III1469f8a2018-05-15 14:40:59 -070099 // Needed instead of elog<InternalFailure>() since the compiler can't
100 // deduce the that elog<>() always throws
101 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700102 "WatchdogService: Should not reach end of getProperties");
William A. Kennington III52575252018-02-09 15:54:56 -0800103}
104
105template <typename T>
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700106T WatchdogService::getProperty(const std::string& key)
107{
108 bool wasValid = wd_service.isValid(bus);
109 auto request = wd_service.newMethodCall(bus, prop_intf, "Get");
110 request.append(wd_intf, key);
111 auto response = bus.call(request);
112 if (response.is_method_error())
113 {
114 wd_service.invalidate();
115 if (wasValid)
116 {
117 // Retry the request once in case the cached service was stale
118 return getProperty<T>(key);
119 }
120 log<level::ERR>("WatchdogService: Method error getting property",
121 entry("PROPERTY=%s", key.c_str()));
122 elog<InternalFailure>();
123 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700124 try
125 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700126 std::variant<T> value;
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700127 response.read(value);
Vernon Maueryf442e112019-04-09 11:44:36 -0700128 return std::get<T>(value);
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700129 }
130 catch (const std::exception& e)
131 {
132 log<level::ERR>("WatchdogService: Decode error in get property",
133 entry("PROPERTY=%s", key.c_str()),
134 entry("ERROR=%s", e.what()),
135 entry("REPLY_SIG=%s", response.get_signature()));
136 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));
William A. Kennington III52575252018-02-09 15:54:56 -0800151 auto response = bus.call(request);
152 if (response.is_method_error())
153 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700154 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700155 if (wasValid)
156 {
157 // Retry the request once in case the cached service was stale
Chen,Yugang0e862fa2019-09-06 11:03:05 +0800158 setProperty(key, val);
159 return;
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700160 }
William A. Kennington IIId5410272018-05-10 11:17:58 -0700161 log<level::ERR>("WatchdogService: Method error setting property",
162 entry("PROPERTY=%s", key.c_str()));
163 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -0800164 }
165}
166
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700167bool WatchdogService::getInitialized()
168{
169 return getProperty<bool>("Initialized");
170}
171
William A. Kennington IIIde14a022018-02-09 16:11:18 -0800172void WatchdogService::setInitialized(bool initialized)
173{
174 setProperty("Initialized", initialized);
175}
176
William A. Kennington III52575252018-02-09 15:54:56 -0800177void WatchdogService::setEnabled(bool enabled)
178{
179 setProperty("Enabled", enabled);
180}
181
William A. Kennington IIIb638de22018-02-09 16:12:53 -0800182void WatchdogService::setExpireAction(Action expireAction)
183{
184 setProperty("ExpireAction", convertForMessage(expireAction));
185}
186
Yong Li118907e2019-01-11 17:36:17 +0800187void WatchdogService::setTimerUse(TimerUse timerUse)
188{
189 setProperty("CurrentTimerUse", convertForMessage(timerUse));
190}
191
Deepak Kumar Sahucfae9482019-05-20 14:58:58 +0000192void WatchdogService::setExpiredTimerUse(TimerUse timerUse)
193{
194 setProperty("ExpiredTimerUse", convertForMessage(timerUse));
195}
196
William A. Kennington III52575252018-02-09 15:54:56 -0800197void WatchdogService::setInterval(uint64_t interval)
198{
199 setProperty("Interval", interval);
200}