blob: fc2ca6552c98a0d7add36d9a46829fc719821427 [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 YU415b9642017-02-09 11:37:26 +08008
9namespace rules = sdbusplus::bus::match::rules;
10
11namespace // anonymous
12{
Lei YU415b9642017-02-09 11:37:26 +080013constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
14constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
Lei YU415b9642017-02-09 11:37:26 +080015
Lei YU415b9642017-02-09 11:37:26 +080016// TODO: Use new settings in xyz.openbmc_project
17const auto MATCH_PROPERTY_CHANGE =
18 rules::type::signal() +
19 rules::member("PropertiesChanged") +
20 rules::path("/org/openbmc/settings/host0") +
21 rules::interface("org.freedesktop.DBus.Properties");
22
Lei YUc6fe8692017-02-23 15:12:07 +080023const auto MATCH_PGOOD_CHANGE =
24 rules::type::signal() +
25 rules::member("PropertiesChanged") +
26 rules::path("/org/openbmc/control/power0") +
27 rules::interface("org.freedesktop.DBus.Properties");
28
Lei YUc6fe8692017-02-23 15:12:07 +080029constexpr auto POWER_PATH = "/org/openbmc/control/power0";
Lei YUdd8e9e42017-04-19 17:46:58 +080030constexpr auto POWER_INTERFACE = "org.openbmc.control.Power";
Lei YUc6fe8692017-02-23 15:12:07 +080031constexpr auto PGOOD_STR = "pgood";
Lei YUa7417132017-02-23 15:24:05 +080032
33constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
34constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
Lei YUdd8e9e42017-04-19 17:46:58 +080035constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
Lei YUa7417132017-02-23 15:24:05 +080036constexpr auto METHOD_SET_NTP = "SetNTP";
37
Lei YUa7417132017-02-23 15:24:05 +080038constexpr auto OBMC_NETWORK_PATH = "/org/openbmc/NetworkManager/Interface";
Lei YUdd8e9e42017-04-19 17:46:58 +080039constexpr auto OBMC_NETWORK_INTERFACE = "org.openbmc.NetworkManager";
Lei YUa7417132017-02-23 15:24:05 +080040constexpr auto METHOD_UPDATE_USE_NTP = "UpdateUseNtpField";
Lei YU415b9642017-02-09 11:37:26 +080041}
42
43namespace phosphor
44{
45namespace time
46{
47
48using namespace phosphor::logging;
49
50const std::set<std::string>
51Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
52
Lei YU415b9642017-02-09 11:37:26 +080053Manager::Manager(sdbusplus::bus::bus& bus)
54 : bus(bus),
Lei YUc6fe8692017-02-23 15:12:07 +080055 propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this),
56 pgoodChangeMatch(bus, MATCH_PGOOD_CHANGE, onPgoodChanged, this)
Lei YU415b9642017-02-09 11:37:26 +080057{
Lei YU710d49b2017-08-01 17:10:17 +080058 using namespace sdbusplus::bus::match::rules;
59 settingsMatches.emplace_back(
60 bus,
61 propertiesChanged(settings.timeOwner, settings::timeOwnerIntf),
62 std::bind(std::mem_fn(&Manager::onSettingsChanged),
63 this, std::placeholders::_1));
64 settingsMatches.emplace_back(
65 bus,
66 propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
67 std::bind(std::mem_fn(&Manager::onSettingsChanged),
68 this, std::placeholders::_1));
69
Lei YUc6fe8692017-02-23 15:12:07 +080070 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080071
72 // Restore settings from persistent storage
73 restoreSettings();
74
75 // Check the settings daemon to process the new settings
Lei YU710d49b2017-08-01 17:10:17 +080076 auto mode = getSetting(settings.timeSyncMethod.c_str(),
77 settings::timeSyncIntf,
78 PROPERTY_TIME_MODE);
79 auto owner = getSetting(settings.timeOwner.c_str(),
80 settings::timeOwnerIntf,
81 PROPERTY_TIME_OWNER);
82
83 onPropertyChanged(PROPERTY_TIME_MODE, mode);
84 onPropertyChanged(PROPERTY_TIME_OWNER, owner);
Lei YUa7417132017-02-23 15:24:05 +080085
86 checkDhcpNtp();
Lei YU415b9642017-02-09 11:37:26 +080087}
88
89void Manager::addListener(PropertyChangeListner* listener)
90{
91 // Notify listener about the initial value
92 listener->onModeChanged(timeMode);
93 listener->onOwnerChanged(timeOwner);
94
95 listeners.insert(listener);
96}
97
Lei YU7f4fca52017-02-23 15:15:51 +080098void Manager::restoreSettings()
99{
100 auto mode = utils::readData<std::string>(modeFile);
101 if (!mode.empty())
102 {
Lei YUddd54422017-04-18 16:38:44 +0800103 timeMode = utils::strToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +0800104 }
105 auto owner = utils::readData<std::string>(ownerFile);
106 if (!owner.empty())
107 {
Lei YUddd54422017-04-18 16:38:44 +0800108 timeOwner = utils::strToOwner(owner);
Lei YU7f4fca52017-02-23 15:15:51 +0800109 }
110}
111
Lei YUc6fe8692017-02-23 15:12:07 +0800112void Manager::checkHostOn()
113{
Lei YUdd8e9e42017-04-19 17:46:58 +0800114 std::string powerService = utils::getService(bus,
115 POWER_PATH,
116 POWER_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +0800117
Lei YUa7417132017-02-23 15:24:05 +0800118 int pgood = utils::getProperty<int>(bus,
Lei YUdd8e9e42017-04-19 17:46:58 +0800119 powerService.c_str(),
Lei YUa7417132017-02-23 15:24:05 +0800120 POWER_PATH,
121 POWER_INTERFACE,
122 PGOOD_STR);
123 hostOn = static_cast<bool>(pgood);
124}
Lei YUc6fe8692017-02-23 15:12:07 +0800125
Lei YUa7417132017-02-23 15:24:05 +0800126void Manager::checkDhcpNtp()
127{
Lei YUdd8e9e42017-04-19 17:46:58 +0800128 std::string useDhcpNtp = getSettings(PROPERTY_DHCP_NTP);
Lei YUa7417132017-02-23 15:24:05 +0800129 updateDhcpNtpSetting(useDhcpNtp);
Lei YUc6fe8692017-02-23 15:12:07 +0800130}
131
Lei YU415b9642017-02-09 11:37:26 +0800132void Manager::onPropertyChanged(const std::string& key,
133 const std::string& value)
134{
Lei YU7f4fca52017-02-23 15:15:51 +0800135 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800136 {
Lei YU7f4fca52017-02-23 15:15:51 +0800137 // If host is on, set the values as requested time mode/owner.
138 // And when host becomes off, notify the listners.
139 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800140 }
Lei YU7f4fca52017-02-23 15:15:51 +0800141 else
Lei YU415b9642017-02-09 11:37:26 +0800142 {
Lei YU7f4fca52017-02-23 15:15:51 +0800143 // If host is off, notify listners
144 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800145 {
Lei YU7f4fca52017-02-23 15:15:51 +0800146 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800147 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800148 }
149 else if (key == PROPERTY_TIME_OWNER)
150 {
151 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800152 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800153 }
154 }
155}
156
157int Manager::onPropertyChanged(sd_bus_message* msg,
158 void* userData,
159 sd_bus_error* retError)
160{
161 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800162 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800163 auto m = sdbusplus::message::message(msg);
164 // message type: sa{sv}as
165 std::string ignore;
166 properties props;
167 m.read(ignore, props);
Lei YUa7417132017-02-23 15:24:05 +0800168 auto manager = static_cast<Manager*>(userData);
Lei YU415b9642017-02-09 11:37:26 +0800169 for (const auto& item : props)
170 {
171 if (managedProperties.find(item.first) != managedProperties.end())
172 {
Lei YUa7417132017-02-23 15:24:05 +0800173 // For managed properties, notify listeners
174 manager->onPropertyChanged(
Lei YU7f4fca52017-02-23 15:15:51 +0800175 item.first, item.second.get<std::string>());
Lei YU415b9642017-02-09 11:37:26 +0800176 }
Lei YUa7417132017-02-23 15:24:05 +0800177 else if (item.first == PROPERTY_DHCP_NTP)
178 {
179 // For other manager interested properties, handle specifically
180 manager->updateDhcpNtpSetting(item.second.get<std::string>());
181 }
Lei YU415b9642017-02-09 11:37:26 +0800182 }
183 return 0;
184}
185
Lei YU710d49b2017-08-01 17:10:17 +0800186int Manager::onSettingsChanged(sdbusplus::message::message& msg)
187{
188 using Interface = std::string;
189 using Property = std::string;
190 using Value = std::string;
191 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
192
193 Interface interface;
194 Properties properties;
195
196 msg.read(interface, properties);
197
198 for(const auto& p : properties)
199 {
200 onPropertyChanged(p.first, p.second.get<std::string>());
201 }
202
203 return 0;
204}
205
Lei YU7f4fca52017-02-23 15:15:51 +0800206void Manager::setPropertyAsRequested(const std::string& key,
207 const std::string& value)
208{
209 if (key == PROPERTY_TIME_MODE)
210 {
211 setRequestedMode(value);
212 }
213 else if (key == PROPERTY_TIME_OWNER)
214 {
215 setRequestedOwner(value);
216 }
217 else
218 {
219 // The key shall be already the supported one
Lei YU86d80412017-07-12 13:12:12 +0800220 using InvalidArgumentError =
221 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
222 using namespace xyz::openbmc_project::Common;
223 elog<InvalidArgumentError>(
224 InvalidArgument::ARGUMENT_NAME(key.c_str()),
225 InvalidArgument::ARGUMENT_VALUE(value.c_str()));
Lei YU7f4fca52017-02-23 15:15:51 +0800226 }
227}
228
229void Manager::setRequestedMode(const std::string& mode)
230{
231 requestedMode = mode;
232}
233
234void Manager::setRequestedOwner(const std::string& owner)
235{
236 requestedOwner = owner;
237}
238
Lei YUa7417132017-02-23 15:24:05 +0800239void Manager::updateNtpSetting(const std::string& value)
240{
Lei YU710d49b2017-08-01 17:10:17 +0800241 bool isNtp =
242 (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
Lei YUa7417132017-02-23 15:24:05 +0800243 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
244 SYSTEMD_TIME_PATH,
245 SYSTEMD_TIME_INTERFACE,
246 METHOD_SET_NTP);
247 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
248 // 'false' meaning no policy-kit
249
250 if (bus.call(method))
251 {
252 log<level::INFO>("Updated NTP setting",
253 entry("ENABLED:%d", isNtp));
254 }
255 else
256 {
257 log<level::ERR>("Failed to update NTP setting");
258 }
259}
260
261void Manager::updateDhcpNtpSetting(const std::string& useDhcpNtp)
262{
Lei YUdd8e9e42017-04-19 17:46:58 +0800263 std::string networkService = utils::getService(bus,
264 OBMC_NETWORK_PATH,
265 OBMC_NETWORK_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +0800266
267 auto method = bus.new_method_call(networkService.c_str(),
Lei YUa7417132017-02-23 15:24:05 +0800268 OBMC_NETWORK_PATH,
269 OBMC_NETWORK_INTERFACE,
270 METHOD_UPDATE_USE_NTP);
271 method.append(useDhcpNtp);
272
273 if (bus.call(method))
274 {
275 log<level::INFO>("Updated use ntp field",
276 entry("USENTPFIELD:%s", useDhcpNtp.c_str()));
277 }
278 else
279 {
280 log<level::ERR>("Failed to update UseNtpField");
281 }
282}
283
Lei YUc6fe8692017-02-23 15:12:07 +0800284void Manager::onPgoodChanged(bool pgood)
285{
286 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800287 if (hostOn)
288 {
289 return;
290 }
291 if (!requestedMode.empty())
292 {
Lei YUa5003ce2017-02-24 15:35:25 +0800293 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800294 {
Lei YUa5003ce2017-02-24 15:35:25 +0800295 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800296 }
297 setRequestedMode({}); // Clear requested mode
298 }
299 if (!requestedOwner.empty())
300 {
Lei YUa5003ce2017-02-24 15:35:25 +0800301 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800302 {
Lei YUa5003ce2017-02-24 15:35:25 +0800303 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800304 }
305 setRequestedOwner({}); // Clear requested owner
306 }
Lei YUc6fe8692017-02-23 15:12:07 +0800307}
308
309int Manager::onPgoodChanged(sd_bus_message* msg,
310 void* userData,
311 sd_bus_error* retError)
312{
313 using properties = std::map < std::string,
314 sdbusplus::message::variant<int> >;
315 auto m = sdbusplus::message::message(msg);
316 // message type: sa{sv}as
317 std::string ignore;
318 properties props;
319 m.read(ignore, props);
320 for (const auto& item : props)
321 {
322 if (item.first == PGOOD_STR)
323 {
324 static_cast<Manager*>(userData)
325 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
326 }
327 }
328 return 0;
329}
Lei YU415b9642017-02-09 11:37:26 +0800330
Lei YUa5003ce2017-02-24 15:35:25 +0800331bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800332{
Lei YUddd54422017-04-18 16:38:44 +0800333 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800334 if (newMode != timeMode)
335 {
336 log<level::INFO>("Time mode is changed",
337 entry("MODE=%s", mode.c_str()));
338 timeMode = newMode;
339 utils::writeData(modeFile, mode);
340 return true;
341 }
342 else
343 {
344 return false;
345 }
Lei YU415b9642017-02-09 11:37:26 +0800346}
347
Lei YUa5003ce2017-02-24 15:35:25 +0800348bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800349{
Lei YUddd54422017-04-18 16:38:44 +0800350 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800351 if (newOwner != timeOwner)
352 {
353 log<level::INFO>("Time owner is changed",
354 entry("OWNER=%s", owner.c_str()));
355 timeOwner = newOwner;
356 utils::writeData(ownerFile, owner);
357 return true;
358 }
359 else
360 {
361 return false;
362 }
363}
364
365void Manager::onTimeModeChanged(const std::string& mode)
366{
367 for (const auto listener : listeners)
368 {
369 listener->onModeChanged(timeMode);
370 }
371 // When time_mode is updated, update the NTP setting
372 updateNtpSetting(mode);
373}
374
375void Manager::onTimeOwnerChanged()
376{
377 for (const auto& listener : listeners)
378 {
379 listener->onOwnerChanged(timeOwner);
380 }
Lei YU415b9642017-02-09 11:37:26 +0800381}
382
Lei YU710d49b2017-08-01 17:10:17 +0800383// TODO: This function is here only for use_dhcp_ntp.
384// When use_dhcp_ntp is transferred to new settings daemon,
385// this function can be removed.
Lei YUdd8e9e42017-04-19 17:46:58 +0800386std::string Manager::getSettings(const char* setting) const
Lei YU415b9642017-02-09 11:37:26 +0800387{
Lei YUdd8e9e42017-04-19 17:46:58 +0800388 std::string settingsService = utils::getService(bus,
389 SETTINGS_PATH,
390 SETTINGS_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +0800391
392 return utils::getProperty<std::string>(bus,
393 settingsService.c_str(),
394 SETTINGS_PATH,
395 SETTINGS_INTERFACE,
396 setting);
Lei YU415b9642017-02-09 11:37:26 +0800397}
398
Lei YU710d49b2017-08-01 17:10:17 +0800399std::string Manager::getSetting(const char* path,
400 const char* interface,
401 const char* setting) const
402{
403 std::string settingManager = utils::getService(bus, path, interface);
404 return utils::getProperty<std::string>(bus,
405 settingManager.c_str(),
406 path,
407 interface,
408 setting);
409}
410
Lei YU415b9642017-02-09 11:37:26 +0800411}
412}