blob: 284964dee2e00c408d49dc4b0c5e29fcb8b6a380 [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 III52575252018-02-09 15:54:56 -080019using sdbusplus::message::variant_ns::get;
20using sdbusplus::message::variant_ns::variant;
William A. Kennington IIId5410272018-05-10 11:17:58 -070021using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
William A. Kennington IIIb638de22018-02-09 16:12:53 -080022using sdbusplus::xyz::openbmc_project::State::server::convertForMessage;
23using sdbusplus::xyz::openbmc_project::State::server::Watchdog;
William A. Kennington III52575252018-02-09 15:54:56 -080024
25static constexpr char wd_path[] = "/xyz/openbmc_project/watchdog/host0";
26static constexpr char wd_intf[] = "xyz.openbmc_project.State.Watchdog";
27static constexpr char prop_intf[] = "org.freedesktop.DBus.Properties";
28
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070029ipmi::ServiceCache WatchdogService::wd_service(wd_intf, wd_path);
30
Patrick Venture0b02be92018-08-31 11:55:55 -070031WatchdogService::WatchdogService() : bus(ipmid_get_sd_bus_connection())
William A. Kennington III52575252018-02-09 15:54:56 -080032{
33}
34
William A. Kennington III4b017a92018-04-27 14:31:08 -070035void WatchdogService::resetTimeRemaining(bool enableWatchdog)
36{
37 bool wasValid = wd_service.isValid(bus);
Patrick Venture0b02be92018-08-31 11:55:55 -070038 auto request = wd_service.newMethodCall(bus, wd_intf, "ResetTimeRemaining");
William A. Kennington III4b017a92018-04-27 14:31:08 -070039 request.append(enableWatchdog);
40 auto response = bus.call(request);
41 if (response.is_method_error())
42 {
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",
51 entry("ENABLE_WATCHDOG=%d", !!enableWatchdog));
William A. Kennington III4b017a92018-04-27 14:31:08 -070052 elog<InternalFailure>();
53 }
54}
55
William A. Kennington III52575252018-02-09 15:54:56 -080056WatchdogService::Properties WatchdogService::getProperties()
57{
William A. Kennington IIIe1628492018-05-11 16:17:28 -070058 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070059 auto request = wd_service.newMethodCall(bus, prop_intf, "GetAll");
William A. Kennington III52575252018-02-09 15:54:56 -080060 request.append(wd_intf);
61 auto response = bus.call(request);
62 if (response.is_method_error())
63 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070064 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -070065 if (wasValid)
66 {
67 // Retry the request once in case the cached service was stale
68 return getProperties();
69 }
William A. Kennington IIId5410272018-05-10 11:17:58 -070070 log<level::ERR>("WatchdogService: Method error getting properties");
71 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -080072 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -070073 try
74 {
75 std::map<std::string, variant<bool, uint64_t, std::string>> properties;
76 response.read(properties);
77 Properties wd_prop;
78 wd_prop.initialized = get<bool>(properties.at("Initialized"));
79 wd_prop.enabled = get<bool>(properties.at("Enabled"));
80 wd_prop.expireAction = Watchdog::convertActionFromString(
Patrick Venture0b02be92018-08-31 11:55:55 -070081 get<std::string>(properties.at("ExpireAction")));
Yong Li118907e2019-01-11 17:36:17 +080082 wd_prop.timerUse = Watchdog::convertTimerUseFromString(
83 get<std::string>(properties.at("CurrentTimerUse")));
84
William A. Kennington III1469f8a2018-05-15 14:40:59 -070085 wd_prop.interval = get<uint64_t>(properties.at("Interval"));
86 wd_prop.timeRemaining = get<uint64_t>(properties.at("TimeRemaining"));
87 return wd_prop;
88 }
89 catch (const std::exception& e)
90 {
91 log<level::ERR>("WatchdogService: Decode error in get properties",
92 entry("ERROR=%s", e.what()),
93 entry("REPLY_SIG=%s", response.get_signature()));
94 elog<InternalFailure>();
95 }
William A. Kennington III52575252018-02-09 15:54:56 -080096
William A. Kennington III1469f8a2018-05-15 14:40:59 -070097 // Needed instead of elog<InternalFailure>() since the compiler can't
98 // deduce the that elog<>() always throws
99 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700100 "WatchdogService: Should not reach end of getProperties");
William A. Kennington III52575252018-02-09 15:54:56 -0800101}
102
103template <typename T>
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700104T WatchdogService::getProperty(const std::string& key)
105{
106 bool wasValid = wd_service.isValid(bus);
107 auto request = wd_service.newMethodCall(bus, prop_intf, "Get");
108 request.append(wd_intf, key);
109 auto response = bus.call(request);
110 if (response.is_method_error())
111 {
112 wd_service.invalidate();
113 if (wasValid)
114 {
115 // Retry the request once in case the cached service was stale
116 return getProperty<T>(key);
117 }
118 log<level::ERR>("WatchdogService: Method error getting property",
119 entry("PROPERTY=%s", key.c_str()));
120 elog<InternalFailure>();
121 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700122 try
123 {
124 variant<T> value;
125 response.read(value);
126 return get<T>(value);
127 }
128 catch (const std::exception& e)
129 {
130 log<level::ERR>("WatchdogService: Decode error in get property",
131 entry("PROPERTY=%s", key.c_str()),
132 entry("ERROR=%s", e.what()),
133 entry("REPLY_SIG=%s", response.get_signature()));
134 elog<InternalFailure>();
135 }
136
137 // Needed instead of elog<InternalFailure>() since the compiler can't
138 // deduce the that elog<>() always throws
139 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700140 "WatchdogService: Should not reach end of getProperty");
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700141}
142
143template <typename T>
William A. Kennington III52575252018-02-09 15:54:56 -0800144void WatchdogService::setProperty(const std::string& key, const T& val)
145{
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700146 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700147 auto request = wd_service.newMethodCall(bus, prop_intf, "Set");
William A. Kennington III52575252018-02-09 15:54:56 -0800148 request.append(wd_intf, key, variant<T>(val));
149 auto response = bus.call(request);
150 if (response.is_method_error())
151 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700152 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700153 if (wasValid)
154 {
155 // Retry the request once in case the cached service was stale
156 return setProperty(key, val);
157 }
William A. Kennington IIId5410272018-05-10 11:17:58 -0700158 log<level::ERR>("WatchdogService: Method error setting property",
159 entry("PROPERTY=%s", key.c_str()));
160 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -0800161 }
162}
163
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700164bool WatchdogService::getInitialized()
165{
166 return getProperty<bool>("Initialized");
167}
168
William A. Kennington IIIde14a022018-02-09 16:11:18 -0800169void WatchdogService::setInitialized(bool initialized)
170{
171 setProperty("Initialized", initialized);
172}
173
William A. Kennington III52575252018-02-09 15:54:56 -0800174void WatchdogService::setEnabled(bool enabled)
175{
176 setProperty("Enabled", enabled);
177}
178
William A. Kennington IIIb638de22018-02-09 16:12:53 -0800179void WatchdogService::setExpireAction(Action expireAction)
180{
181 setProperty("ExpireAction", convertForMessage(expireAction));
182}
183
Yong Li118907e2019-01-11 17:36:17 +0800184void WatchdogService::setTimerUse(TimerUse timerUse)
185{
186 setProperty("CurrentTimerUse", convertForMessage(timerUse));
187}
188
William A. Kennington III52575252018-02-09 15:54:56 -0800189void WatchdogService::setInterval(uint64_t interval)
190{
191 setProperty("Interval", interval);
192}
193
194void WatchdogService::setTimeRemaining(uint64_t timeRemaining)
195{
196 setProperty("TimeRemaining", timeRemaining);
197}