#include "watchdog_service.hpp" #include #include #include #include #include #include #include #include #include #include #include using phosphor::logging::elog; using phosphor::logging::entry; using phosphor::logging::level; using phosphor::logging::log; using sdbusplus::common::xyz::openbmc_project::state::convertForMessage; using sdbusplus::error::xyz::openbmc_project::common::InternalFailure; using sdbusplus::server::xyz::openbmc_project::state::Watchdog; static constexpr char wd_path[] = "/xyz/openbmc_project/watchdog/host0"; static constexpr char wd_intf[] = "xyz.openbmc_project.State.Watchdog"; static constexpr char prop_intf[] = "org.freedesktop.DBus.Properties"; ipmi::ServiceCache WatchdogService::wd_service(wd_intf, wd_path); WatchdogService::WatchdogService() : bus(ipmid_get_sd_bus_connection()) {} void WatchdogService::resetTimeRemaining(bool enableWatchdog) { bool wasValid = wd_service.isValid(bus); auto request = wd_service.newMethodCall(bus, wd_intf, "ResetTimeRemaining"); request.append(enableWatchdog); try { auto response = bus.call(request); } catch (const std::exception& e) { wd_service.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale return resetTimeRemaining(enableWatchdog); } log( "WatchdogService: Method error resetting time remaining", entry("ENABLE_WATCHDOG=%d", !!enableWatchdog), entry("ERROR=%s", e.what())); elog(); } } WatchdogService::Properties WatchdogService::getProperties() { bool wasValid = wd_service.isValid(bus); auto request = wd_service.newMethodCall(bus, prop_intf, "GetAll"); request.append(wd_intf); std::map> properties; try { auto response = bus.call(request); response.read(properties); } catch (const std::exception& e) { wd_service.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale return getProperties(); } log("WatchdogService: Method error getting properties", entry("ERROR=%s", e.what())); elog(); } try { Properties wd_prop; wd_prop.initialized = std::get(properties.at("Initialized")); wd_prop.enabled = std::get(properties.at("Enabled")); wd_prop.expireAction = Watchdog::convertActionFromString( std::get(properties.at("ExpireAction"))); wd_prop.timerUse = Watchdog::convertTimerUseFromString( std::get(properties.at("CurrentTimerUse"))); wd_prop.expiredTimerUse = Watchdog::convertTimerUseFromString( std::get(properties.at("ExpiredTimerUse"))); wd_prop.interval = std::get(properties.at("Interval")); wd_prop.timeRemaining = std::get(properties.at("TimeRemaining")); return wd_prop; } catch (const std::exception& e) { log("WatchdogService: Decode error in get properties", entry("ERROR=%s", e.what())); elog(); } // Needed instead of elog() since the compiler can't // deduce the that elog<>() always throws throw std::runtime_error( "WatchdogService: Should not reach end of getProperties"); } template T WatchdogService::getProperty(const std::string& key) { bool wasValid = wd_service.isValid(bus); auto request = wd_service.newMethodCall(bus, prop_intf, "Get"); request.append(wd_intf, key); try { auto response = bus.call(request); std::variant value; response.read(value); return std::get(value); } catch (const std::exception& e) { wd_service.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale return getProperty(key); } log("WatchdogService: Method error getting property", entry("PROPERTY=%s", key.c_str()), entry("ERROR=%s", e.what())); elog(); } // Needed instead of elog() since the compiler can't // deduce the that elog<>() always throws throw std::runtime_error( "WatchdogService: Should not reach end of getProperty"); } template void WatchdogService::setProperty(const std::string& key, const T& val) { bool wasValid = wd_service.isValid(bus); auto request = wd_service.newMethodCall(bus, prop_intf, "Set"); request.append(wd_intf, key, std::variant(val)); try { auto response = bus.call(request); } catch (const std::exception& e) { wd_service.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale setProperty(key, val); return; } log("WatchdogService: Method error setting property", entry("PROPERTY=%s", key.c_str()), entry("ERROR=%s", e.what())); elog(); } } bool WatchdogService::getInitialized() { return getProperty("Initialized"); } void WatchdogService::setInitialized(bool initialized) { setProperty("Initialized", initialized); } void WatchdogService::setEnabled(bool enabled) { setProperty("Enabled", enabled); } void WatchdogService::setLogTimeout(bool LogTimeout) { setProperty("LogTimeout", LogTimeout); } void WatchdogService::setExpireAction(Action expireAction) { setProperty("ExpireAction", convertForMessage(expireAction)); } void WatchdogService::setTimerUse(TimerUse timerUse) { setProperty("CurrentTimerUse", convertForMessage(timerUse)); } void WatchdogService::setExpiredTimerUse(TimerUse timerUse) { setProperty("ExpiredTimerUse", convertForMessage(timerUse)); } void WatchdogService::setInterval(uint64_t interval) { setProperty("Interval", interval); }