blob: 8d3d955c2ed086f83d8f30f039d902daa8365067 [file] [log] [blame]
Lei YU415b9642017-02-09 11:37:26 +08001#include "manager.hpp"
Lei YU7f4fca52017-02-23 15:15:51 +08002#include "utils.hpp"
Lei YU415b9642017-02-09 11:37:26 +08003
Lei YU86d80412017-07-12 13:12:12 +08004#include <phosphor-logging/elog.hpp>
5#include <phosphor-logging/elog-errors.hpp>
Lei YU415b9642017-02-09 11:37:26 +08006#include <phosphor-logging/log.hpp>
Lei YU86d80412017-07-12 13:12:12 +08007#include <xyz/openbmc_project/Common/error.hpp>
Lei YUdebe1d82017-10-13 13:21:37 +08008#include <xyz/openbmc_project/State/Host/server.hpp>
Lei YU415b9642017-02-09 11:37:26 +08009
10namespace rules = sdbusplus::bus::match::rules;
11
12namespace // anonymous
13{
Lei YUdebe1d82017-10-13 13:21:37 +080014constexpr auto HOST_CURRENT_STATE = "CurrentHostState";
Lei YUa7417132017-02-23 15:24:05 +080015
16constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
17constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
Lei YUdd8e9e42017-04-19 17:46:58 +080018constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
Lei YUa7417132017-02-23 15:24:05 +080019constexpr auto METHOD_SET_NTP = "SetNTP";
Lei YU415b9642017-02-09 11:37:26 +080020}
21
22namespace phosphor
23{
24namespace time
25{
26
27using namespace phosphor::logging;
28
29const std::set<std::string>
30Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
31
Lei YU415b9642017-02-09 11:37:26 +080032Manager::Manager(sdbusplus::bus::bus& bus)
Lei YUdebe1d82017-10-13 13:21:37 +080033 : 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>(
38 bus,
39 propertiesChanged(settings.hostState, settings::hostStateIntf),
40 std::bind(std::mem_fn(&Manager::onHostStateChanged),
41 this, std::placeholders::_1));
Lei YU710d49b2017-08-01 17:10:17 +080042 settingsMatches.emplace_back(
43 bus,
44 propertiesChanged(settings.timeOwner, settings::timeOwnerIntf),
45 std::bind(std::mem_fn(&Manager::onSettingsChanged),
46 this, std::placeholders::_1));
47 settingsMatches.emplace_back(
48 bus,
49 propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
50 std::bind(std::mem_fn(&Manager::onSettingsChanged),
51 this, std::placeholders::_1));
52
Lei YUc6fe8692017-02-23 15:12:07 +080053 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080054
55 // Restore settings from persistent storage
56 restoreSettings();
57
58 // Check the settings daemon to process the new settings
Lei YU710d49b2017-08-01 17:10:17 +080059 auto mode = getSetting(settings.timeSyncMethod.c_str(),
60 settings::timeSyncIntf,
61 PROPERTY_TIME_MODE);
62 auto owner = getSetting(settings.timeOwner.c_str(),
63 settings::timeOwnerIntf,
64 PROPERTY_TIME_OWNER);
65
66 onPropertyChanged(PROPERTY_TIME_MODE, mode);
67 onPropertyChanged(PROPERTY_TIME_OWNER, owner);
Lei YU415b9642017-02-09 11:37:26 +080068}
69
70void Manager::addListener(PropertyChangeListner* listener)
71{
72 // Notify listener about the initial value
73 listener->onModeChanged(timeMode);
74 listener->onOwnerChanged(timeOwner);
75
76 listeners.insert(listener);
77}
78
Lei YU7f4fca52017-02-23 15:15:51 +080079void Manager::restoreSettings()
80{
81 auto mode = utils::readData<std::string>(modeFile);
82 if (!mode.empty())
83 {
Lei YUddd54422017-04-18 16:38:44 +080084 timeMode = utils::strToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +080085 }
86 auto owner = utils::readData<std::string>(ownerFile);
87 if (!owner.empty())
88 {
Lei YUddd54422017-04-18 16:38:44 +080089 timeOwner = utils::strToOwner(owner);
Lei YU7f4fca52017-02-23 15:15:51 +080090 }
91}
92
Lei YUc6fe8692017-02-23 15:12:07 +080093void Manager::checkHostOn()
94{
Lei YUdebe1d82017-10-13 13:21:37 +080095 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
96 auto hostService = utils::getService(bus,
97 settings.hostState.c_str(),
98 settings::hostStateIntf);
99 auto stateStr = utils::getProperty<std::string>(bus,
100 hostService.c_str(),
101 settings.hostState.c_str(),
102 settings::hostStateIntf,
103 HOST_CURRENT_STATE);
104 auto state = Host::convertHostStateFromString(stateStr);
105 hostOn = (state == Host::HostState::Running);
Lei YUa7417132017-02-23 15:24:05 +0800106}
Lei YUc6fe8692017-02-23 15:12:07 +0800107
Lei YU415b9642017-02-09 11:37:26 +0800108void Manager::onPropertyChanged(const std::string& key,
109 const std::string& value)
110{
Lei YU7f4fca52017-02-23 15:15:51 +0800111 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800112 {
Lei YU7f4fca52017-02-23 15:15:51 +0800113 // If host is on, set the values as requested time mode/owner.
Gunnar Mills7f25c532017-10-25 20:45:28 -0500114 // And when host becomes off, notify the listeners.
Lei YU7f4fca52017-02-23 15:15:51 +0800115 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800116 }
Lei YU7f4fca52017-02-23 15:15:51 +0800117 else
Lei YU415b9642017-02-09 11:37:26 +0800118 {
Gunnar Mills7f25c532017-10-25 20:45:28 -0500119 // If host is off, notify listeners
Lei YU7f4fca52017-02-23 15:15:51 +0800120 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800121 {
Lei YU7f4fca52017-02-23 15:15:51 +0800122 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800123 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800124 }
125 else if (key == PROPERTY_TIME_OWNER)
126 {
127 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800128 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800129 }
130 }
131}
132
Lei YU710d49b2017-08-01 17:10:17 +0800133int Manager::onSettingsChanged(sdbusplus::message::message& msg)
134{
135 using Interface = std::string;
136 using Property = std::string;
137 using Value = std::string;
138 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
139
140 Interface interface;
141 Properties properties;
142
143 msg.read(interface, properties);
144
145 for(const auto& p : properties)
146 {
147 onPropertyChanged(p.first, p.second.get<std::string>());
148 }
149
150 return 0;
151}
152
Lei YU7f4fca52017-02-23 15:15:51 +0800153void Manager::setPropertyAsRequested(const std::string& key,
154 const std::string& value)
155{
156 if (key == PROPERTY_TIME_MODE)
157 {
158 setRequestedMode(value);
159 }
160 else if (key == PROPERTY_TIME_OWNER)
161 {
162 setRequestedOwner(value);
163 }
164 else
165 {
166 // The key shall be already the supported one
Lei YU86d80412017-07-12 13:12:12 +0800167 using InvalidArgumentError =
168 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
169 using namespace xyz::openbmc_project::Common;
170 elog<InvalidArgumentError>(
171 InvalidArgument::ARGUMENT_NAME(key.c_str()),
172 InvalidArgument::ARGUMENT_VALUE(value.c_str()));
Lei YU7f4fca52017-02-23 15:15:51 +0800173 }
174}
175
176void Manager::setRequestedMode(const std::string& mode)
177{
178 requestedMode = mode;
179}
180
181void Manager::setRequestedOwner(const std::string& owner)
182{
183 requestedOwner = owner;
184}
185
Lei YUa7417132017-02-23 15:24:05 +0800186void Manager::updateNtpSetting(const std::string& value)
187{
Lei YU710d49b2017-08-01 17:10:17 +0800188 bool isNtp =
189 (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
Lei YUa7417132017-02-23 15:24:05 +0800190 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
191 SYSTEMD_TIME_PATH,
192 SYSTEMD_TIME_INTERFACE,
193 METHOD_SET_NTP);
194 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
195 // 'false' meaning no policy-kit
196
Lei YU89efe6e2018-07-24 10:38:01 +0800197 try
Lei YUa7417132017-02-23 15:24:05 +0800198 {
Lei YU89efe6e2018-07-24 10:38:01 +0800199 bus.call_noreply(method);
Lei YUa7417132017-02-23 15:24:05 +0800200 log<level::INFO>("Updated NTP setting",
Lei YU89efe6e2018-07-24 10:38:01 +0800201 entry("ENABLED=%d", isNtp));
Lei YUa7417132017-02-23 15:24:05 +0800202 }
Lei YU89efe6e2018-07-24 10:38:01 +0800203 catch (const sdbusplus::exception::SdBusError& ex)
Lei YUa7417132017-02-23 15:24:05 +0800204 {
Lei YU89efe6e2018-07-24 10:38:01 +0800205 log<level::ERR>("Failed to update NTP setting",
206 entry("ERR=%s", ex.what()));
Lei YUa7417132017-02-23 15:24:05 +0800207 }
208}
209
Lei YUdebe1d82017-10-13 13:21:37 +0800210void Manager::onHostStateChanged(sdbusplus::message::message& msg)
Lei YUc6fe8692017-02-23 15:12:07 +0800211{
Lei YUdebe1d82017-10-13 13:21:37 +0800212 using Interface = std::string;
213 using Property = std::string;
214 using Value = std::string;
215 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
216 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
217
218 Interface interface;
219 Properties properties;
220
221 msg.read(interface, properties);
222
223 for(const auto& p : properties)
224 {
225 if (p.first == HOST_CURRENT_STATE)
226 {
227 auto state = Host::convertHostStateFromString(p.second.get<std::string>());
228 onHostState(state == Host::HostState::Running);
229 break;
230 }
231 }
232}
233
234void Manager::onHostState(bool on)
235{
236 hostOn = on;
Lei YU7f4fca52017-02-23 15:15:51 +0800237 if (hostOn)
238 {
Lei YUdebe1d82017-10-13 13:21:37 +0800239 log<level::INFO>("Changing time settings is *deferred* now");
Lei YU7f4fca52017-02-23 15:15:51 +0800240 return;
241 }
Lei YUdebe1d82017-10-13 13:21:37 +0800242 log<level::INFO>("Changing time settings allowed now");
Lei YU7f4fca52017-02-23 15:15:51 +0800243 if (!requestedMode.empty())
244 {
Lei YUa5003ce2017-02-24 15:35:25 +0800245 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800246 {
Lei YUa5003ce2017-02-24 15:35:25 +0800247 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800248 }
249 setRequestedMode({}); // Clear requested mode
250 }
251 if (!requestedOwner.empty())
252 {
Lei YUa5003ce2017-02-24 15:35:25 +0800253 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800254 {
Lei YUa5003ce2017-02-24 15:35:25 +0800255 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800256 }
257 setRequestedOwner({}); // Clear requested owner
258 }
Lei YUc6fe8692017-02-23 15:12:07 +0800259}
260
Lei YUa5003ce2017-02-24 15:35:25 +0800261bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800262{
Lei YUddd54422017-04-18 16:38:44 +0800263 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800264 if (newMode != timeMode)
265 {
266 log<level::INFO>("Time mode is changed",
267 entry("MODE=%s", mode.c_str()));
268 timeMode = newMode;
269 utils::writeData(modeFile, mode);
270 return true;
271 }
272 else
273 {
274 return false;
275 }
Lei YU415b9642017-02-09 11:37:26 +0800276}
277
Lei YUa5003ce2017-02-24 15:35:25 +0800278bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800279{
Lei YUddd54422017-04-18 16:38:44 +0800280 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800281 if (newOwner != timeOwner)
282 {
283 log<level::INFO>("Time owner is changed",
284 entry("OWNER=%s", owner.c_str()));
285 timeOwner = newOwner;
286 utils::writeData(ownerFile, owner);
287 return true;
288 }
289 else
290 {
291 return false;
292 }
293}
294
295void Manager::onTimeModeChanged(const std::string& mode)
296{
297 for (const auto listener : listeners)
298 {
299 listener->onModeChanged(timeMode);
300 }
301 // When time_mode is updated, update the NTP setting
302 updateNtpSetting(mode);
303}
304
305void Manager::onTimeOwnerChanged()
306{
307 for (const auto& listener : listeners)
308 {
309 listener->onOwnerChanged(timeOwner);
310 }
Lei YU415b9642017-02-09 11:37:26 +0800311}
312
Lei YU710d49b2017-08-01 17:10:17 +0800313std::string Manager::getSetting(const char* path,
314 const char* interface,
315 const char* setting) const
316{
317 std::string settingManager = utils::getService(bus, path, interface);
318 return utils::getProperty<std::string>(bus,
319 settingManager.c_str(),
320 path,
321 interface,
322 setting);
323}
324
Lei YU415b9642017-02-09 11:37:26 +0800325}
326}