blob: f9de91dbe2d9397310ea99dada0b171da57bd65d [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
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050030const std::set<std::string> Manager::managedProperties = {PROPERTY_TIME_MODE,
31 PROPERTY_TIME_OWNER};
Lei YU415b9642017-02-09 11:37:26 +080032
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050033Manager::Manager(sdbusplus::bus::bus& bus) : bus(bus)
Lei YU415b9642017-02-09 11:37:26 +080034{
Lei YU710d49b2017-08-01 17:10:17 +080035 using namespace sdbusplus::bus::match::rules;
Lei YUdebe1d82017-10-13 13:21:37 +080036 hostStateChangeMatch =
37 std::make_unique<decltype(hostStateChangeMatch)::element_type>(
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050038 bus, propertiesChanged(settings.hostState, settings::hostStateIntf),
39 std::bind(std::mem_fn(&Manager::onHostStateChanged), this,
40 std::placeholders::_1));
Lei YU710d49b2017-08-01 17:10:17 +080041 settingsMatches.emplace_back(
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050042 bus, propertiesChanged(settings.timeOwner, settings::timeOwnerIntf),
43 std::bind(std::mem_fn(&Manager::onSettingsChanged), this,
44 std::placeholders::_1));
Lei YU710d49b2017-08-01 17:10:17 +080045 settingsMatches.emplace_back(
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050046 bus, propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
47 std::bind(std::mem_fn(&Manager::onSettingsChanged), this,
48 std::placeholders::_1));
Lei YU710d49b2017-08-01 17:10:17 +080049
Lei YUc6fe8692017-02-23 15:12:07 +080050 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080051
52 // Restore settings from persistent storage
53 restoreSettings();
54
55 // Check the settings daemon to process the new settings
Lei YU710d49b2017-08-01 17:10:17 +080056 auto mode = getSetting(settings.timeSyncMethod.c_str(),
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050057 settings::timeSyncIntf, PROPERTY_TIME_MODE);
58 auto owner = getSetting(settings.timeOwner.c_str(), settings::timeOwnerIntf,
Lei YU710d49b2017-08-01 17:10:17 +080059 PROPERTY_TIME_OWNER);
60
61 onPropertyChanged(PROPERTY_TIME_MODE, mode);
62 onPropertyChanged(PROPERTY_TIME_OWNER, owner);
Lei YU415b9642017-02-09 11:37:26 +080063}
64
65void Manager::addListener(PropertyChangeListner* listener)
66{
67 // Notify listener about the initial value
68 listener->onModeChanged(timeMode);
69 listener->onOwnerChanged(timeOwner);
70
71 listeners.insert(listener);
72}
73
Lei YU7f4fca52017-02-23 15:15:51 +080074void Manager::restoreSettings()
75{
76 auto mode = utils::readData<std::string>(modeFile);
77 if (!mode.empty())
78 {
Lei YUddd54422017-04-18 16:38:44 +080079 timeMode = utils::strToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +080080 }
81 auto owner = utils::readData<std::string>(ownerFile);
82 if (!owner.empty())
83 {
Lei YUddd54422017-04-18 16:38:44 +080084 timeOwner = utils::strToOwner(owner);
Lei YU7f4fca52017-02-23 15:15:51 +080085 }
86}
87
Lei YUc6fe8692017-02-23 15:12:07 +080088void Manager::checkHostOn()
89{
Lei YUdebe1d82017-10-13 13:21:37 +080090 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050091 auto hostService = utils::getService(bus, settings.hostState.c_str(),
Lei YUdebe1d82017-10-13 13:21:37 +080092 settings::hostStateIntf);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050093 auto stateStr = utils::getProperty<std::string>(
94 bus, hostService.c_str(), settings.hostState.c_str(),
95 settings::hostStateIntf, HOST_CURRENT_STATE);
Lei YUdebe1d82017-10-13 13:21:37 +080096 auto state = Host::convertHostStateFromString(stateStr);
97 hostOn = (state == Host::HostState::Running);
Lei YUa7417132017-02-23 15:24:05 +080098}
Lei YUc6fe8692017-02-23 15:12:07 +080099
Lei YU415b9642017-02-09 11:37:26 +0800100void Manager::onPropertyChanged(const std::string& key,
101 const std::string& value)
102{
Lei YU7f4fca52017-02-23 15:15:51 +0800103 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800104 {
Lei YU7f4fca52017-02-23 15:15:51 +0800105 // If host is on, set the values as requested time mode/owner.
Gunnar Mills7f25c532017-10-25 20:45:28 -0500106 // And when host becomes off, notify the listeners.
Lei YU7f4fca52017-02-23 15:15:51 +0800107 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800108 }
Lei YU7f4fca52017-02-23 15:15:51 +0800109 else
Lei YU415b9642017-02-09 11:37:26 +0800110 {
Gunnar Mills7f25c532017-10-25 20:45:28 -0500111 // If host is off, notify listeners
Lei YU7f4fca52017-02-23 15:15:51 +0800112 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800113 {
Lei YU7f4fca52017-02-23 15:15:51 +0800114 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800115 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800116 }
117 else if (key == PROPERTY_TIME_OWNER)
118 {
119 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800120 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800121 }
122 }
123}
124
Lei YU710d49b2017-08-01 17:10:17 +0800125int Manager::onSettingsChanged(sdbusplus::message::message& msg)
126{
127 using Interface = std::string;
128 using Property = std::string;
129 using Value = std::string;
130 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
131
132 Interface interface;
133 Properties properties;
134
135 msg.read(interface, properties);
136
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500137 for (const auto& p : properties)
Lei YU710d49b2017-08-01 17:10:17 +0800138 {
William A. Kennington III1f1d8e02018-11-06 16:06:34 -0800139 onPropertyChanged(
140 p.first,
141 sdbusplus::message::variant_ns::get<std::string>(p.second));
Lei YU710d49b2017-08-01 17:10:17 +0800142 }
143
144 return 0;
145}
146
Lei YU7f4fca52017-02-23 15:15:51 +0800147void Manager::setPropertyAsRequested(const std::string& key,
148 const std::string& value)
149{
150 if (key == PROPERTY_TIME_MODE)
151 {
152 setRequestedMode(value);
153 }
154 else if (key == PROPERTY_TIME_OWNER)
155 {
156 setRequestedOwner(value);
157 }
158 else
159 {
160 // The key shall be already the supported one
Lei YU86d80412017-07-12 13:12:12 +0800161 using InvalidArgumentError =
162 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
163 using namespace xyz::openbmc_project::Common;
164 elog<InvalidArgumentError>(
165 InvalidArgument::ARGUMENT_NAME(key.c_str()),
166 InvalidArgument::ARGUMENT_VALUE(value.c_str()));
Lei YU7f4fca52017-02-23 15:15:51 +0800167 }
168}
169
170void Manager::setRequestedMode(const std::string& mode)
171{
172 requestedMode = mode;
173}
174
175void Manager::setRequestedOwner(const std::string& owner)
176{
177 requestedOwner = owner;
178}
179
Lei YUa7417132017-02-23 15:24:05 +0800180void Manager::updateNtpSetting(const std::string& value)
181{
Lei YU710d49b2017-08-01 17:10:17 +0800182 bool isNtp =
183 (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500184 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE, SYSTEMD_TIME_PATH,
185 SYSTEMD_TIME_INTERFACE, METHOD_SET_NTP);
Lei YUa7417132017-02-23 15:24:05 +0800186 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
187 // 'false' meaning no policy-kit
188
Lei YU89efe6e2018-07-24 10:38:01 +0800189 try
Lei YUa7417132017-02-23 15:24:05 +0800190 {
Lei YU89efe6e2018-07-24 10:38:01 +0800191 bus.call_noreply(method);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500192 log<level::INFO>("Updated NTP setting", entry("ENABLED=%d", isNtp));
Lei YUa7417132017-02-23 15:24:05 +0800193 }
Lei YU89efe6e2018-07-24 10:38:01 +0800194 catch (const sdbusplus::exception::SdBusError& ex)
Lei YUa7417132017-02-23 15:24:05 +0800195 {
Lei YU89efe6e2018-07-24 10:38:01 +0800196 log<level::ERR>("Failed to update NTP setting",
197 entry("ERR=%s", ex.what()));
Lei YUa7417132017-02-23 15:24:05 +0800198 }
199}
200
Lei YUdebe1d82017-10-13 13:21:37 +0800201void Manager::onHostStateChanged(sdbusplus::message::message& msg)
Lei YUc6fe8692017-02-23 15:12:07 +0800202{
Lei YUdebe1d82017-10-13 13:21:37 +0800203 using Interface = std::string;
204 using Property = std::string;
205 using Value = std::string;
206 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
207 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
208
209 Interface interface;
210 Properties properties;
211
212 msg.read(interface, properties);
213
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500214 for (const auto& p : properties)
Lei YUdebe1d82017-10-13 13:21:37 +0800215 {
216 if (p.first == HOST_CURRENT_STATE)
217 {
William A. Kennington III1f1d8e02018-11-06 16:06:34 -0800218 auto state = Host::convertHostStateFromString(
219 sdbusplus::message::variant_ns::get<std::string>(p.second));
Lei YUdebe1d82017-10-13 13:21:37 +0800220 onHostState(state == Host::HostState::Running);
221 break;
222 }
223 }
224}
225
226void Manager::onHostState(bool on)
227{
228 hostOn = on;
Lei YU7f4fca52017-02-23 15:15:51 +0800229 if (hostOn)
230 {
Lei YUdebe1d82017-10-13 13:21:37 +0800231 log<level::INFO>("Changing time settings is *deferred* now");
Lei YU7f4fca52017-02-23 15:15:51 +0800232 return;
233 }
Lei YUdebe1d82017-10-13 13:21:37 +0800234 log<level::INFO>("Changing time settings allowed now");
Lei YU7f4fca52017-02-23 15:15:51 +0800235 if (!requestedMode.empty())
236 {
Lei YUa5003ce2017-02-24 15:35:25 +0800237 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800238 {
Lei YUa5003ce2017-02-24 15:35:25 +0800239 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800240 }
241 setRequestedMode({}); // Clear requested mode
242 }
243 if (!requestedOwner.empty())
244 {
Lei YUa5003ce2017-02-24 15:35:25 +0800245 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800246 {
Lei YUa5003ce2017-02-24 15:35:25 +0800247 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800248 }
249 setRequestedOwner({}); // Clear requested owner
250 }
Lei YUc6fe8692017-02-23 15:12:07 +0800251}
252
Lei YUa5003ce2017-02-24 15:35:25 +0800253bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800254{
Lei YUddd54422017-04-18 16:38:44 +0800255 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800256 if (newMode != timeMode)
257 {
258 log<level::INFO>("Time mode is changed",
259 entry("MODE=%s", mode.c_str()));
260 timeMode = newMode;
261 utils::writeData(modeFile, mode);
262 return true;
263 }
264 else
265 {
266 return false;
267 }
Lei YU415b9642017-02-09 11:37:26 +0800268}
269
Lei YUa5003ce2017-02-24 15:35:25 +0800270bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800271{
Lei YUddd54422017-04-18 16:38:44 +0800272 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800273 if (newOwner != timeOwner)
274 {
275 log<level::INFO>("Time owner is changed",
276 entry("OWNER=%s", owner.c_str()));
277 timeOwner = newOwner;
278 utils::writeData(ownerFile, owner);
279 return true;
280 }
281 else
282 {
283 return false;
284 }
285}
286
287void Manager::onTimeModeChanged(const std::string& mode)
288{
289 for (const auto listener : listeners)
290 {
291 listener->onModeChanged(timeMode);
292 }
293 // When time_mode is updated, update the NTP setting
294 updateNtpSetting(mode);
295}
296
297void Manager::onTimeOwnerChanged()
298{
299 for (const auto& listener : listeners)
300 {
301 listener->onOwnerChanged(timeOwner);
302 }
Lei YU415b9642017-02-09 11:37:26 +0800303}
304
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500305std::string Manager::getSetting(const char* path, const char* interface,
Lei YU710d49b2017-08-01 17:10:17 +0800306 const char* setting) const
307{
308 std::string settingManager = utils::getService(bus, path, interface);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500309 return utils::getProperty<std::string>(bus, settingManager.c_str(), path,
310 interface, setting);
Lei YU710d49b2017-08-01 17:10:17 +0800311}
312
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500313} // namespace time
314} // namespace phosphor