#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 auto wdPath = "/xyz/openbmc_project/watchdog/host0"; static constexpr auto propIntf = "org.freedesktop.DBus.Properties"; ipmi::ServiceCache WatchdogService::wdService(Watchdog::interface, wdPath); WatchdogService::WatchdogService() : bus(ipmid_get_sd_bus_connection()) {} void WatchdogService::resetTimeRemaining(bool enableWatchdog) { bool wasValid = wdService.isValid(bus); auto request = wdService.newMethodCall(bus, Watchdog::interface, "ResetTimeRemaining"); request.append(enableWatchdog); try { auto response = bus.call(request); } catch (const std::exception& e) { wdService.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale return resetTimeRemaining(enableWatchdog); } lg2::error("WatchdogService: Method error resetting time remaining, " "ENABLE_WATCHDOG: {ENABLE_WATCHDOG}, ERROR: {ERROR}", "ENABLE_WATCHDOG", enableWatchdog, "ERROR", e); elog(); } } WatchdogService::Properties WatchdogService::getProperties() { bool wasValid = wdService.isValid(bus); auto request = wdService.newMethodCall(bus, propIntf, "GetAll"); request.append(Watchdog::interface); std::map> properties; try { auto response = bus.call(request); response.read(properties); } catch (const std::exception& e) { wdService.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale return getProperties(); } lg2::error("WatchdogService: Method error getting properties: {ERROR}", "ERROR", e); elog(); } try { Properties wdProp; wdProp.initialized = std::get(properties.at("Initialized")); wdProp.enabled = std::get(properties.at("Enabled")); wdProp.expireAction = Watchdog::convertActionFromString( std::get(properties.at("ExpireAction"))); wdProp.timerUse = Watchdog::convertTimerUseFromString( std::get(properties.at("CurrentTimerUse"))); wdProp.expiredTimerUse = Watchdog::convertTimerUseFromString( std::get(properties.at("ExpiredTimerUse"))); wdProp.interval = std::get(properties.at("Interval")); wdProp.timeRemaining = std::get(properties.at("TimeRemaining")); return wdProp; } catch (const std::exception& e) { lg2::error("WatchdogService: Decode error in get properties: {ERROR}", "ERROR", e); 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 = wdService.isValid(bus); auto request = wdService.newMethodCall(bus, propIntf, "Get"); request.append(Watchdog::interface, key); try { auto response = bus.call(request); auto value = response.unpack>(); return std::get(value); } catch (const std::exception& e) { wdService.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale return getProperty(key); } lg2::error("WatchdogService: Method error getting {PROPERTY}: {ERROR}", "PROPERTY", key, "ERROR", e); 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 = wdService.isValid(bus); auto request = wdService.newMethodCall(bus, propIntf, "Set"); request.append(Watchdog::interface, key, std::variant(val)); try { auto response = bus.call(request); } catch (const std::exception& e) { wdService.invalidate(); if (wasValid) { // Retry the request once in case the cached service was stale setProperty(key, val); return; } lg2::error("WatchdogService: Method error setting {PROPERTY}: {ERROR}", "PROPERTY", key, "ERROR", e); 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); }