blob: e65ea63dd400092ba676366b62dd2efe975fa1df [file] [log] [blame]
William A. Kennington III52575252018-02-09 15:54:56 -08001#include "watchdog_service.hpp"
2
William A. Kennington III194375f2018-12-14 02:14:33 -08003#include <ipmid/api.h>
Patrick Venture46470a32018-09-07 19:26:25 -07004
William A. Kennington III1469f8a2018-05-15 14:40:59 -07005#include <exception>
William A. Kennington IIId5410272018-05-10 11:17:58 -07006#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -07007#include <phosphor-logging/elog.hpp>
William A. Kennington IIId5410272018-05-10 11:17:58 -07008#include <phosphor-logging/log.hpp>
William A. Kennington III52575252018-02-09 15:54:56 -08009#include <sdbusplus/bus.hpp>
10#include <sdbusplus/message.hpp>
William A. Kennington III1469f8a2018-05-15 14:40:59 -070011#include <stdexcept>
William A. Kennington III52575252018-02-09 15:54:56 -080012#include <string>
William A. Kennington IIId5410272018-05-10 11:17:58 -070013#include <xyz/openbmc_project/Common/error.hpp>
William A. Kennington IIIb638de22018-02-09 16:12:53 -080014#include <xyz/openbmc_project/State/Watchdog/server.hpp>
William A. Kennington III52575252018-02-09 15:54:56 -080015
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;
William A. Kennington III52575252018-02-09 15:54:56 -080020using sdbusplus::message::variant_ns::get;
21using sdbusplus::message::variant_ns::variant;
William A. Kennington IIId5410272018-05-10 11:17:58 -070022using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
William A. Kennington IIIb638de22018-02-09 16:12:53 -080023using sdbusplus::xyz::openbmc_project::State::server::convertForMessage;
24using sdbusplus::xyz::openbmc_project::State::server::Watchdog;
William A. Kennington III52575252018-02-09 15:54:56 -080025
26static constexpr char wd_path[] = "/xyz/openbmc_project/watchdog/host0";
27static constexpr char wd_intf[] = "xyz.openbmc_project.State.Watchdog";
28static constexpr char prop_intf[] = "org.freedesktop.DBus.Properties";
29
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070030ipmi::ServiceCache WatchdogService::wd_service(wd_intf, wd_path);
31
Patrick Venture0b02be92018-08-31 11:55:55 -070032WatchdogService::WatchdogService() : bus(ipmid_get_sd_bus_connection())
William A. Kennington III52575252018-02-09 15:54:56 -080033{
34}
35
William A. Kennington III4b017a92018-04-27 14:31:08 -070036void WatchdogService::resetTimeRemaining(bool enableWatchdog)
37{
38 bool wasValid = wd_service.isValid(bus);
Patrick Venture0b02be92018-08-31 11:55:55 -070039 auto request = wd_service.newMethodCall(bus, wd_intf, "ResetTimeRemaining");
William A. Kennington III4b017a92018-04-27 14:31:08 -070040 request.append(enableWatchdog);
41 auto response = bus.call(request);
42 if (response.is_method_error())
43 {
44 wd_service.invalidate();
45 if (wasValid)
46 {
47 // Retry the request once in case the cached service was stale
48 return resetTimeRemaining(enableWatchdog);
49 }
50 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -070051 "WatchdogService: Method error resetting time remaining",
52 entry("ENABLE_WATCHDOG=%d", !!enableWatchdog));
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);
62 auto response = bus.call(request);
63 if (response.is_method_error())
64 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -070065 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -070066 if (wasValid)
67 {
68 // Retry the request once in case the cached service was stale
69 return getProperties();
70 }
William A. Kennington IIId5410272018-05-10 11:17:58 -070071 log<level::ERR>("WatchdogService: Method error getting properties");
72 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -080073 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -070074 try
75 {
76 std::map<std::string, variant<bool, uint64_t, std::string>> properties;
77 response.read(properties);
78 Properties wd_prop;
79 wd_prop.initialized = get<bool>(properties.at("Initialized"));
80 wd_prop.enabled = get<bool>(properties.at("Enabled"));
81 wd_prop.expireAction = Watchdog::convertActionFromString(
Patrick Venture0b02be92018-08-31 11:55:55 -070082 get<std::string>(properties.at("ExpireAction")));
Yong Li118907e2019-01-11 17:36:17 +080083 wd_prop.timerUse = Watchdog::convertTimerUseFromString(
84 get<std::string>(properties.at("CurrentTimerUse")));
85
William A. Kennington III1469f8a2018-05-15 14:40:59 -070086 wd_prop.interval = get<uint64_t>(properties.at("Interval"));
87 wd_prop.timeRemaining = get<uint64_t>(properties.at("TimeRemaining"));
88 return wd_prop;
89 }
90 catch (const std::exception& e)
91 {
92 log<level::ERR>("WatchdogService: Decode error in get properties",
93 entry("ERROR=%s", e.what()),
94 entry("REPLY_SIG=%s", response.get_signature()));
95 elog<InternalFailure>();
96 }
William A. Kennington III52575252018-02-09 15:54:56 -080097
William A. Kennington III1469f8a2018-05-15 14:40:59 -070098 // Needed instead of elog<InternalFailure>() since the compiler can't
99 // deduce the that elog<>() always throws
100 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700101 "WatchdogService: Should not reach end of getProperties");
William A. Kennington III52575252018-02-09 15:54:56 -0800102}
103
104template <typename T>
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700105T WatchdogService::getProperty(const std::string& key)
106{
107 bool wasValid = wd_service.isValid(bus);
108 auto request = wd_service.newMethodCall(bus, prop_intf, "Get");
109 request.append(wd_intf, key);
110 auto response = bus.call(request);
111 if (response.is_method_error())
112 {
113 wd_service.invalidate();
114 if (wasValid)
115 {
116 // Retry the request once in case the cached service was stale
117 return getProperty<T>(key);
118 }
119 log<level::ERR>("WatchdogService: Method error getting property",
120 entry("PROPERTY=%s", key.c_str()));
121 elog<InternalFailure>();
122 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700123 try
124 {
125 variant<T> value;
126 response.read(value);
127 return get<T>(value);
128 }
129 catch (const std::exception& e)
130 {
131 log<level::ERR>("WatchdogService: Decode error in get property",
132 entry("PROPERTY=%s", key.c_str()),
133 entry("ERROR=%s", e.what()),
134 entry("REPLY_SIG=%s", response.get_signature()));
135 elog<InternalFailure>();
136 }
137
138 // Needed instead of elog<InternalFailure>() since the compiler can't
139 // deduce the that elog<>() always throws
140 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700141 "WatchdogService: Should not reach end of getProperty");
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700142}
143
144template <typename T>
William A. Kennington III52575252018-02-09 15:54:56 -0800145void WatchdogService::setProperty(const std::string& key, const T& val)
146{
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700147 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700148 auto request = wd_service.newMethodCall(bus, prop_intf, "Set");
William A. Kennington III52575252018-02-09 15:54:56 -0800149 request.append(wd_intf, key, variant<T>(val));
150 auto response = bus.call(request);
151 if (response.is_method_error())
152 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700153 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700154 if (wasValid)
155 {
156 // Retry the request once in case the cached service was stale
157 return setProperty(key, val);
158 }
William A. Kennington IIId5410272018-05-10 11:17:58 -0700159 log<level::ERR>("WatchdogService: Method error setting property",
160 entry("PROPERTY=%s", key.c_str()));
161 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -0800162 }
163}
164
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700165bool WatchdogService::getInitialized()
166{
167 return getProperty<bool>("Initialized");
168}
169
William A. Kennington IIIde14a022018-02-09 16:11:18 -0800170void WatchdogService::setInitialized(bool initialized)
171{
172 setProperty("Initialized", initialized);
173}
174
William A. Kennington III52575252018-02-09 15:54:56 -0800175void WatchdogService::setEnabled(bool enabled)
176{
177 setProperty("Enabled", enabled);
178}
179
William A. Kennington IIIb638de22018-02-09 16:12:53 -0800180void WatchdogService::setExpireAction(Action expireAction)
181{
182 setProperty("ExpireAction", convertForMessage(expireAction));
183}
184
Yong Li118907e2019-01-11 17:36:17 +0800185void WatchdogService::setTimerUse(TimerUse timerUse)
186{
187 setProperty("CurrentTimerUse", convertForMessage(timerUse));
188}
189
William A. Kennington III52575252018-02-09 15:54:56 -0800190void WatchdogService::setInterval(uint64_t interval)
191{
192 setProperty("Interval", interval);
193}
194
195void WatchdogService::setTimeRemaining(uint64_t timeRemaining)
196{
197 setProperty("TimeRemaining", timeRemaining);
198}