blob: 92a7a3c8fc70a11c9eac80025f9d9aa57e9199c6 [file] [log] [blame]
Lei YU415b9642017-02-09 11:37:26 +08001#include "manager.hpp"
Gunnar Millsab4cc6a2018-09-14 14:42:39 -05002
Lei YU7f4fca52017-02-23 15:15:51 +08003#include "utils.hpp"
Lei YU415b9642017-02-09 11:37:26 +08004
Lei YU86d80412017-07-12 13:12:12 +08005#include <phosphor-logging/elog-errors.hpp>
Gunnar Millsab4cc6a2018-09-14 14:42:39 -05006#include <phosphor-logging/elog.hpp>
Lei YU415b9642017-02-09 11:37:26 +08007#include <phosphor-logging/log.hpp>
Lei YU86d80412017-07-12 13:12:12 +08008#include <xyz/openbmc_project/Common/error.hpp>
Lei YUdebe1d82017-10-13 13:21:37 +08009#include <xyz/openbmc_project/State/Host/server.hpp>
Lei YU415b9642017-02-09 11:37:26 +080010
11namespace rules = sdbusplus::bus::match::rules;
12
13namespace // anonymous
14{
Lei YUdebe1d82017-10-13 13:21:37 +080015constexpr auto HOST_CURRENT_STATE = "CurrentHostState";
Lei YUa7417132017-02-23 15:24:05 +080016
17constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
18constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
Lei YUdd8e9e42017-04-19 17:46:58 +080019constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
Lei YUa7417132017-02-23 15:24:05 +080020constexpr auto METHOD_SET_NTP = "SetNTP";
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050021} // namespace
Lei YU415b9642017-02-09 11:37:26 +080022
23namespace phosphor
24{
25namespace time
26{
27
28using namespace phosphor::logging;
29
George Liu3c2f4492020-04-12 11:35:57 +080030const std::set<std::string> Manager::managedProperties = {PROPERTY_TIME_MODE};
Lei YU415b9642017-02-09 11:37:26 +080031
Brad Bishop4e845392018-12-18 18:13:12 -050032Manager::Manager(sdbusplus::bus::bus& bus) : bus(bus), settings(bus)
Lei YU415b9642017-02-09 11:37:26 +080033{
Lei YU710d49b2017-08-01 17:10:17 +080034 using namespace sdbusplus::bus::match::rules;
Lei YUdebe1d82017-10-13 13:21:37 +080035 hostStateChangeMatch =
36 std::make_unique<decltype(hostStateChangeMatch)::element_type>(
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050037 bus, propertiesChanged(settings.hostState, settings::hostStateIntf),
38 std::bind(std::mem_fn(&Manager::onHostStateChanged), this,
39 std::placeholders::_1));
Lei YU710d49b2017-08-01 17:10:17 +080040 settingsMatches.emplace_back(
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050041 bus, propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
42 std::bind(std::mem_fn(&Manager::onSettingsChanged), this,
43 std::placeholders::_1));
Lei YU710d49b2017-08-01 17:10:17 +080044
Lei YUc6fe8692017-02-23 15:12:07 +080045 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080046
47 // Restore settings from persistent storage
48 restoreSettings();
49
50 // Check the settings daemon to process the new settings
Lei YU710d49b2017-08-01 17:10:17 +080051 auto mode = getSetting(settings.timeSyncMethod.c_str(),
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050052 settings::timeSyncIntf, PROPERTY_TIME_MODE);
Lei YU710d49b2017-08-01 17:10:17 +080053
54 onPropertyChanged(PROPERTY_TIME_MODE, mode);
Lei YU415b9642017-02-09 11:37:26 +080055}
56
57void Manager::addListener(PropertyChangeListner* listener)
58{
59 // Notify listener about the initial value
60 listener->onModeChanged(timeMode);
Lei YU415b9642017-02-09 11:37:26 +080061
62 listeners.insert(listener);
63}
64
Lei YU7f4fca52017-02-23 15:15:51 +080065void Manager::restoreSettings()
66{
67 auto mode = utils::readData<std::string>(modeFile);
68 if (!mode.empty())
69 {
Lei YUddd54422017-04-18 16:38:44 +080070 timeMode = utils::strToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +080071 }
Lei YU7f4fca52017-02-23 15:15:51 +080072}
73
Lei YUc6fe8692017-02-23 15:12:07 +080074void Manager::checkHostOn()
75{
Lei YUdebe1d82017-10-13 13:21:37 +080076 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050077 auto hostService = utils::getService(bus, settings.hostState.c_str(),
Lei YUdebe1d82017-10-13 13:21:37 +080078 settings::hostStateIntf);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050079 auto stateStr = utils::getProperty<std::string>(
80 bus, hostService.c_str(), settings.hostState.c_str(),
81 settings::hostStateIntf, HOST_CURRENT_STATE);
Lei YUdebe1d82017-10-13 13:21:37 +080082 auto state = Host::convertHostStateFromString(stateStr);
83 hostOn = (state == Host::HostState::Running);
Lei YUa7417132017-02-23 15:24:05 +080084}
Lei YUc6fe8692017-02-23 15:12:07 +080085
Lei YU415b9642017-02-09 11:37:26 +080086void Manager::onPropertyChanged(const std::string& key,
87 const std::string& value)
88{
Lei YU7f4fca52017-02-23 15:15:51 +080089 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +080090 {
George Liu3c2f4492020-04-12 11:35:57 +080091 // If host is on, set the values as requested time mode.
Gunnar Mills7f25c532017-10-25 20:45:28 -050092 // And when host becomes off, notify the listeners.
Lei YU7f4fca52017-02-23 15:15:51 +080093 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +080094 }
Lei YU7f4fca52017-02-23 15:15:51 +080095 else
Lei YU415b9642017-02-09 11:37:26 +080096 {
Gunnar Mills7f25c532017-10-25 20:45:28 -050097 // If host is off, notify listeners
Lei YU7f4fca52017-02-23 15:15:51 +080098 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +080099 {
Lei YU7f4fca52017-02-23 15:15:51 +0800100 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800101 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800102 }
Lei YU415b9642017-02-09 11:37:26 +0800103 }
104}
105
Lei YU710d49b2017-08-01 17:10:17 +0800106int Manager::onSettingsChanged(sdbusplus::message::message& msg)
107{
108 using Interface = std::string;
109 using Property = std::string;
110 using Value = std::string;
Patrick Williamsc09ac3f2020-05-13 18:01:29 -0500111 using Properties = std::map<Property, std::variant<Value>>;
Lei YU710d49b2017-08-01 17:10:17 +0800112
113 Interface interface;
114 Properties properties;
115
116 msg.read(interface, properties);
117
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500118 for (const auto& p : properties)
Lei YU710d49b2017-08-01 17:10:17 +0800119 {
Patrick Williams5b746c72020-05-13 11:49:35 -0500120 onPropertyChanged(p.first, std::get<std::string>(p.second));
Lei YU710d49b2017-08-01 17:10:17 +0800121 }
122
123 return 0;
124}
125
Lei YU7f4fca52017-02-23 15:15:51 +0800126void Manager::setPropertyAsRequested(const std::string& key,
127 const std::string& value)
128{
129 if (key == PROPERTY_TIME_MODE)
130 {
131 setRequestedMode(value);
132 }
Lei YU7f4fca52017-02-23 15:15:51 +0800133 else
134 {
135 // The key shall be already the supported one
Lei YU86d80412017-07-12 13:12:12 +0800136 using InvalidArgumentError =
137 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
138 using namespace xyz::openbmc_project::Common;
139 elog<InvalidArgumentError>(
140 InvalidArgument::ARGUMENT_NAME(key.c_str()),
141 InvalidArgument::ARGUMENT_VALUE(value.c_str()));
Lei YU7f4fca52017-02-23 15:15:51 +0800142 }
143}
144
145void Manager::setRequestedMode(const std::string& mode)
146{
147 requestedMode = mode;
148}
149
Lei YUa7417132017-02-23 15:24:05 +0800150void Manager::updateNtpSetting(const std::string& value)
151{
Lei YU710d49b2017-08-01 17:10:17 +0800152 bool isNtp =
153 (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500154 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE, SYSTEMD_TIME_PATH,
155 SYSTEMD_TIME_INTERFACE, METHOD_SET_NTP);
Lei YUa7417132017-02-23 15:24:05 +0800156 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
157 // 'false' meaning no policy-kit
158
Lei YU89efe6e2018-07-24 10:38:01 +0800159 try
Lei YUa7417132017-02-23 15:24:05 +0800160 {
Lei YU89efe6e2018-07-24 10:38:01 +0800161 bus.call_noreply(method);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500162 log<level::INFO>("Updated NTP setting", entry("ENABLED=%d", isNtp));
Lei YUa7417132017-02-23 15:24:05 +0800163 }
Lei YU89efe6e2018-07-24 10:38:01 +0800164 catch (const sdbusplus::exception::SdBusError& ex)
Lei YUa7417132017-02-23 15:24:05 +0800165 {
Lei YU89efe6e2018-07-24 10:38:01 +0800166 log<level::ERR>("Failed to update NTP setting",
167 entry("ERR=%s", ex.what()));
Lei YUa7417132017-02-23 15:24:05 +0800168 }
169}
170
Lei YUdebe1d82017-10-13 13:21:37 +0800171void Manager::onHostStateChanged(sdbusplus::message::message& msg)
Lei YUc6fe8692017-02-23 15:12:07 +0800172{
Lei YUdebe1d82017-10-13 13:21:37 +0800173 using Interface = std::string;
174 using Property = std::string;
175 using Value = std::string;
Patrick Williamsc09ac3f2020-05-13 18:01:29 -0500176 using Properties = std::map<Property, std::variant<Value>>;
Lei YUdebe1d82017-10-13 13:21:37 +0800177 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
178
179 Interface interface;
180 Properties properties;
181
182 msg.read(interface, properties);
183
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500184 for (const auto& p : properties)
Lei YUdebe1d82017-10-13 13:21:37 +0800185 {
186 if (p.first == HOST_CURRENT_STATE)
187 {
William A. Kennington III1f1d8e02018-11-06 16:06:34 -0800188 auto state = Host::convertHostStateFromString(
Patrick Williams5b746c72020-05-13 11:49:35 -0500189 std::get<std::string>(p.second));
Lei YUdebe1d82017-10-13 13:21:37 +0800190 onHostState(state == Host::HostState::Running);
191 break;
192 }
193 }
194}
195
196void Manager::onHostState(bool on)
197{
198 hostOn = on;
Lei YU7f4fca52017-02-23 15:15:51 +0800199 if (hostOn)
200 {
Lei YUdebe1d82017-10-13 13:21:37 +0800201 log<level::INFO>("Changing time settings is *deferred* now");
Lei YU7f4fca52017-02-23 15:15:51 +0800202 return;
203 }
Lei YUdebe1d82017-10-13 13:21:37 +0800204 log<level::INFO>("Changing time settings allowed now");
Lei YU7f4fca52017-02-23 15:15:51 +0800205 if (!requestedMode.empty())
206 {
Lei YUa5003ce2017-02-24 15:35:25 +0800207 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800208 {
Lei YUa5003ce2017-02-24 15:35:25 +0800209 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800210 }
211 setRequestedMode({}); // Clear requested mode
212 }
Lei YUc6fe8692017-02-23 15:12:07 +0800213}
214
Lei YUa5003ce2017-02-24 15:35:25 +0800215bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800216{
Lei YUddd54422017-04-18 16:38:44 +0800217 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800218 if (newMode != timeMode)
219 {
220 log<level::INFO>("Time mode is changed",
221 entry("MODE=%s", mode.c_str()));
222 timeMode = newMode;
223 utils::writeData(modeFile, mode);
224 return true;
225 }
226 else
227 {
228 return false;
229 }
Lei YU415b9642017-02-09 11:37:26 +0800230}
231
Lei YUa5003ce2017-02-24 15:35:25 +0800232void Manager::onTimeModeChanged(const std::string& mode)
233{
234 for (const auto listener : listeners)
235 {
236 listener->onModeChanged(timeMode);
237 }
238 // When time_mode is updated, update the NTP setting
239 updateNtpSetting(mode);
240}
241
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500242std::string Manager::getSetting(const char* path, const char* interface,
Lei YU710d49b2017-08-01 17:10:17 +0800243 const char* setting) const
244{
245 std::string settingManager = utils::getService(bus, path, interface);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500246 return utils::getProperty<std::string>(bus, settingManager.c_str(), path,
247 interface, setting);
Lei YU710d49b2017-08-01 17:10:17 +0800248}
249
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500250} // namespace time
251} // namespace phosphor