blob: 1145d33dc17f9f52e74d66801b08745f79156147 [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
197 if (bus.call(method))
198 {
199 log<level::INFO>("Updated NTP setting",
200 entry("ENABLED:%d", isNtp));
201 }
202 else
203 {
204 log<level::ERR>("Failed to update NTP setting");
205 }
206}
207
Lei YUdebe1d82017-10-13 13:21:37 +0800208void Manager::onHostStateChanged(sdbusplus::message::message& msg)
Lei YUc6fe8692017-02-23 15:12:07 +0800209{
Lei YUdebe1d82017-10-13 13:21:37 +0800210 using Interface = std::string;
211 using Property = std::string;
212 using Value = std::string;
213 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
214 using Host = sdbusplus::xyz::openbmc_project::State::server::Host;
215
216 Interface interface;
217 Properties properties;
218
219 msg.read(interface, properties);
220
221 for(const auto& p : properties)
222 {
223 if (p.first == HOST_CURRENT_STATE)
224 {
225 auto state = Host::convertHostStateFromString(p.second.get<std::string>());
226 onHostState(state == Host::HostState::Running);
227 break;
228 }
229 }
230}
231
232void Manager::onHostState(bool on)
233{
234 hostOn = on;
Lei YU7f4fca52017-02-23 15:15:51 +0800235 if (hostOn)
236 {
Lei YUdebe1d82017-10-13 13:21:37 +0800237 log<level::INFO>("Changing time settings is *deferred* now");
Lei YU7f4fca52017-02-23 15:15:51 +0800238 return;
239 }
Lei YUdebe1d82017-10-13 13:21:37 +0800240 log<level::INFO>("Changing time settings allowed now");
Lei YU7f4fca52017-02-23 15:15:51 +0800241 if (!requestedMode.empty())
242 {
Lei YUa5003ce2017-02-24 15:35:25 +0800243 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800244 {
Lei YUa5003ce2017-02-24 15:35:25 +0800245 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800246 }
247 setRequestedMode({}); // Clear requested mode
248 }
249 if (!requestedOwner.empty())
250 {
Lei YUa5003ce2017-02-24 15:35:25 +0800251 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800252 {
Lei YUa5003ce2017-02-24 15:35:25 +0800253 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800254 }
255 setRequestedOwner({}); // Clear requested owner
256 }
Lei YUc6fe8692017-02-23 15:12:07 +0800257}
258
Lei YUa5003ce2017-02-24 15:35:25 +0800259bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800260{
Lei YUddd54422017-04-18 16:38:44 +0800261 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800262 if (newMode != timeMode)
263 {
264 log<level::INFO>("Time mode is changed",
265 entry("MODE=%s", mode.c_str()));
266 timeMode = newMode;
267 utils::writeData(modeFile, mode);
268 return true;
269 }
270 else
271 {
272 return false;
273 }
Lei YU415b9642017-02-09 11:37:26 +0800274}
275
Lei YUa5003ce2017-02-24 15:35:25 +0800276bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800277{
Lei YUddd54422017-04-18 16:38:44 +0800278 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800279 if (newOwner != timeOwner)
280 {
281 log<level::INFO>("Time owner is changed",
282 entry("OWNER=%s", owner.c_str()));
283 timeOwner = newOwner;
284 utils::writeData(ownerFile, owner);
285 return true;
286 }
287 else
288 {
289 return false;
290 }
291}
292
293void Manager::onTimeModeChanged(const std::string& mode)
294{
295 for (const auto listener : listeners)
296 {
297 listener->onModeChanged(timeMode);
298 }
299 // When time_mode is updated, update the NTP setting
300 updateNtpSetting(mode);
301}
302
303void Manager::onTimeOwnerChanged()
304{
305 for (const auto& listener : listeners)
306 {
307 listener->onOwnerChanged(timeOwner);
308 }
Lei YU415b9642017-02-09 11:37:26 +0800309}
310
Lei YU710d49b2017-08-01 17:10:17 +0800311std::string Manager::getSetting(const char* path,
312 const char* interface,
313 const char* setting) const
314{
315 std::string settingManager = utils::getService(bus, path, interface);
316 return utils::getProperty<std::string>(bus,
317 settingManager.c_str(),
318 path,
319 interface,
320 setting);
321}
322
Lei YU415b9642017-02-09 11:37:26 +0800323}
324}