blob: 769a70d705a436e3d4e23ede0e02cfd18ad57424 [file] [log] [blame]
William A. Kennington III52575252018-02-09 15:54:56 -08001#include "watchdog_service.hpp"
2
Patrick Venture46470a32018-09-07 19:26:25 -07003#include <host-ipmid/ipmid-api.h>
4
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")));
William A. Kennington III1469f8a2018-05-15 14:40:59 -070083 wd_prop.interval = get<uint64_t>(properties.at("Interval"));
84 wd_prop.timeRemaining = get<uint64_t>(properties.at("TimeRemaining"));
85 return wd_prop;
86 }
87 catch (const std::exception& e)
88 {
89 log<level::ERR>("WatchdogService: Decode error in get properties",
90 entry("ERROR=%s", e.what()),
91 entry("REPLY_SIG=%s", response.get_signature()));
92 elog<InternalFailure>();
93 }
William A. Kennington III52575252018-02-09 15:54:56 -080094
William A. Kennington III1469f8a2018-05-15 14:40:59 -070095 // Needed instead of elog<InternalFailure>() since the compiler can't
96 // deduce the that elog<>() always throws
97 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -070098 "WatchdogService: Should not reach end of getProperties");
William A. Kennington III52575252018-02-09 15:54:56 -080099}
100
101template <typename T>
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700102T WatchdogService::getProperty(const std::string& key)
103{
104 bool wasValid = wd_service.isValid(bus);
105 auto request = wd_service.newMethodCall(bus, prop_intf, "Get");
106 request.append(wd_intf, key);
107 auto response = bus.call(request);
108 if (response.is_method_error())
109 {
110 wd_service.invalidate();
111 if (wasValid)
112 {
113 // Retry the request once in case the cached service was stale
114 return getProperty<T>(key);
115 }
116 log<level::ERR>("WatchdogService: Method error getting property",
117 entry("PROPERTY=%s", key.c_str()));
118 elog<InternalFailure>();
119 }
William A. Kennington III1469f8a2018-05-15 14:40:59 -0700120 try
121 {
122 variant<T> value;
123 response.read(value);
124 return get<T>(value);
125 }
126 catch (const std::exception& e)
127 {
128 log<level::ERR>("WatchdogService: Decode error in get property",
129 entry("PROPERTY=%s", key.c_str()),
130 entry("ERROR=%s", e.what()),
131 entry("REPLY_SIG=%s", response.get_signature()));
132 elog<InternalFailure>();
133 }
134
135 // Needed instead of elog<InternalFailure>() since the compiler can't
136 // deduce the that elog<>() always throws
137 throw std::runtime_error(
Patrick Venture0b02be92018-08-31 11:55:55 -0700138 "WatchdogService: Should not reach end of getProperty");
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700139}
140
141template <typename T>
William A. Kennington III52575252018-02-09 15:54:56 -0800142void WatchdogService::setProperty(const std::string& key, const T& val)
143{
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700144 bool wasValid = wd_service.isValid(bus);
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700145 auto request = wd_service.newMethodCall(bus, prop_intf, "Set");
William A. Kennington III52575252018-02-09 15:54:56 -0800146 request.append(wd_intf, key, variant<T>(val));
147 auto response = bus.call(request);
148 if (response.is_method_error())
149 {
William A. Kennington III25bc7ac2018-03-15 11:48:41 -0700150 wd_service.invalidate();
William A. Kennington IIIe1628492018-05-11 16:17:28 -0700151 if (wasValid)
152 {
153 // Retry the request once in case the cached service was stale
154 return setProperty(key, val);
155 }
William A. Kennington IIId5410272018-05-10 11:17:58 -0700156 log<level::ERR>("WatchdogService: Method error setting property",
157 entry("PROPERTY=%s", key.c_str()));
158 elog<InternalFailure>();
William A. Kennington III52575252018-02-09 15:54:56 -0800159 }
160}
161
William A. Kennington III2ecf5122018-04-27 14:31:51 -0700162bool WatchdogService::getInitialized()
163{
164 return getProperty<bool>("Initialized");
165}
166
William A. Kennington IIIde14a022018-02-09 16:11:18 -0800167void WatchdogService::setInitialized(bool initialized)
168{
169 setProperty("Initialized", initialized);
170}
171
William A. Kennington III52575252018-02-09 15:54:56 -0800172void WatchdogService::setEnabled(bool enabled)
173{
174 setProperty("Enabled", enabled);
175}
176
William A. Kennington IIIb638de22018-02-09 16:12:53 -0800177void WatchdogService::setExpireAction(Action expireAction)
178{
179 setProperty("ExpireAction", convertForMessage(expireAction));
180}
181
William A. Kennington III52575252018-02-09 15:54:56 -0800182void WatchdogService::setInterval(uint64_t interval)
183{
184 setProperty("Interval", interval);
185}
186
187void WatchdogService::setTimeRemaining(uint64_t timeRemaining)
188{
189 setProperty("TimeRemaining", timeRemaining);
190}