blob: 0fedd098b51c2d0d0a0874ea8a19930a5d30b0c3 [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 YUc6fe8692017-02-23 15:12:07 +080058 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080059
60 // Restore settings from persistent storage
61 restoreSettings();
62
63 // Check the settings daemon to process the new settings
64 onPropertyChanged(PROPERTY_TIME_MODE, getSettings(PROPERTY_TIME_MODE));
65 onPropertyChanged(PROPERTY_TIME_OWNER, getSettings(PROPERTY_TIME_OWNER));
Lei YUa7417132017-02-23 15:24:05 +080066
67 checkDhcpNtp();
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 YUdd8e9e42017-04-19 17:46:58 +080095 std::string powerService = utils::getService(bus,
96 POWER_PATH,
97 POWER_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +080098
Lei YUa7417132017-02-23 15:24:05 +080099 int pgood = utils::getProperty<int>(bus,
Lei YUdd8e9e42017-04-19 17:46:58 +0800100 powerService.c_str(),
Lei YUa7417132017-02-23 15:24:05 +0800101 POWER_PATH,
102 POWER_INTERFACE,
103 PGOOD_STR);
104 hostOn = static_cast<bool>(pgood);
105}
Lei YUc6fe8692017-02-23 15:12:07 +0800106
Lei YUa7417132017-02-23 15:24:05 +0800107void Manager::checkDhcpNtp()
108{
Lei YUdd8e9e42017-04-19 17:46:58 +0800109 std::string useDhcpNtp = getSettings(PROPERTY_DHCP_NTP);
Lei YUa7417132017-02-23 15:24:05 +0800110 updateDhcpNtpSetting(useDhcpNtp);
Lei YUc6fe8692017-02-23 15:12:07 +0800111}
112
Lei YU415b9642017-02-09 11:37:26 +0800113void Manager::onPropertyChanged(const std::string& key,
114 const std::string& value)
115{
Lei YU7f4fca52017-02-23 15:15:51 +0800116 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800117 {
Lei YU7f4fca52017-02-23 15:15:51 +0800118 // If host is on, set the values as requested time mode/owner.
119 // And when host becomes off, notify the listners.
120 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800121 }
Lei YU7f4fca52017-02-23 15:15:51 +0800122 else
Lei YU415b9642017-02-09 11:37:26 +0800123 {
Lei YU7f4fca52017-02-23 15:15:51 +0800124 // If host is off, notify listners
125 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800126 {
Lei YU7f4fca52017-02-23 15:15:51 +0800127 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800128 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800129 }
130 else if (key == PROPERTY_TIME_OWNER)
131 {
132 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800133 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800134 }
135 }
136}
137
138int Manager::onPropertyChanged(sd_bus_message* msg,
139 void* userData,
140 sd_bus_error* retError)
141{
142 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800143 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800144 auto m = sdbusplus::message::message(msg);
145 // message type: sa{sv}as
146 std::string ignore;
147 properties props;
148 m.read(ignore, props);
Lei YUa7417132017-02-23 15:24:05 +0800149 auto manager = static_cast<Manager*>(userData);
Lei YU415b9642017-02-09 11:37:26 +0800150 for (const auto& item : props)
151 {
152 if (managedProperties.find(item.first) != managedProperties.end())
153 {
Lei YUa7417132017-02-23 15:24:05 +0800154 // For managed properties, notify listeners
155 manager->onPropertyChanged(
Lei YU7f4fca52017-02-23 15:15:51 +0800156 item.first, item.second.get<std::string>());
Lei YU415b9642017-02-09 11:37:26 +0800157 }
Lei YUa7417132017-02-23 15:24:05 +0800158 else if (item.first == PROPERTY_DHCP_NTP)
159 {
160 // For other manager interested properties, handle specifically
161 manager->updateDhcpNtpSetting(item.second.get<std::string>());
162 }
Lei YU415b9642017-02-09 11:37:26 +0800163 }
164 return 0;
165}
166
Lei YU7f4fca52017-02-23 15:15:51 +0800167void Manager::setPropertyAsRequested(const std::string& key,
168 const std::string& value)
169{
170 if (key == PROPERTY_TIME_MODE)
171 {
172 setRequestedMode(value);
173 }
174 else if (key == PROPERTY_TIME_OWNER)
175 {
176 setRequestedOwner(value);
177 }
178 else
179 {
180 // The key shall be already the supported one
Lei YU86d80412017-07-12 13:12:12 +0800181 using InvalidArgumentError =
182 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
183 using namespace xyz::openbmc_project::Common;
184 elog<InvalidArgumentError>(
185 InvalidArgument::ARGUMENT_NAME(key.c_str()),
186 InvalidArgument::ARGUMENT_VALUE(value.c_str()));
Lei YU7f4fca52017-02-23 15:15:51 +0800187 }
188}
189
190void Manager::setRequestedMode(const std::string& mode)
191{
192 requestedMode = mode;
193}
194
195void Manager::setRequestedOwner(const std::string& owner)
196{
197 requestedOwner = owner;
198}
199
Lei YUa7417132017-02-23 15:24:05 +0800200void Manager::updateNtpSetting(const std::string& value)
201{
202 bool isNtp = (value == "NTP");
203 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
204 SYSTEMD_TIME_PATH,
205 SYSTEMD_TIME_INTERFACE,
206 METHOD_SET_NTP);
207 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
208 // 'false' meaning no policy-kit
209
210 if (bus.call(method))
211 {
212 log<level::INFO>("Updated NTP setting",
213 entry("ENABLED:%d", isNtp));
214 }
215 else
216 {
217 log<level::ERR>("Failed to update NTP setting");
218 }
219}
220
221void Manager::updateDhcpNtpSetting(const std::string& useDhcpNtp)
222{
Lei YUdd8e9e42017-04-19 17:46:58 +0800223 std::string networkService = utils::getService(bus,
224 OBMC_NETWORK_PATH,
225 OBMC_NETWORK_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +0800226
227 auto method = bus.new_method_call(networkService.c_str(),
Lei YUa7417132017-02-23 15:24:05 +0800228 OBMC_NETWORK_PATH,
229 OBMC_NETWORK_INTERFACE,
230 METHOD_UPDATE_USE_NTP);
231 method.append(useDhcpNtp);
232
233 if (bus.call(method))
234 {
235 log<level::INFO>("Updated use ntp field",
236 entry("USENTPFIELD:%s", useDhcpNtp.c_str()));
237 }
238 else
239 {
240 log<level::ERR>("Failed to update UseNtpField");
241 }
242}
243
Lei YUc6fe8692017-02-23 15:12:07 +0800244void Manager::onPgoodChanged(bool pgood)
245{
246 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800247 if (hostOn)
248 {
249 return;
250 }
251 if (!requestedMode.empty())
252 {
Lei YUa5003ce2017-02-24 15:35:25 +0800253 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800254 {
Lei YUa5003ce2017-02-24 15:35:25 +0800255 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800256 }
257 setRequestedMode({}); // Clear requested mode
258 }
259 if (!requestedOwner.empty())
260 {
Lei YUa5003ce2017-02-24 15:35:25 +0800261 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800262 {
Lei YUa5003ce2017-02-24 15:35:25 +0800263 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800264 }
265 setRequestedOwner({}); // Clear requested owner
266 }
Lei YUc6fe8692017-02-23 15:12:07 +0800267}
268
269int Manager::onPgoodChanged(sd_bus_message* msg,
270 void* userData,
271 sd_bus_error* retError)
272{
273 using properties = std::map < std::string,
274 sdbusplus::message::variant<int> >;
275 auto m = sdbusplus::message::message(msg);
276 // message type: sa{sv}as
277 std::string ignore;
278 properties props;
279 m.read(ignore, props);
280 for (const auto& item : props)
281 {
282 if (item.first == PGOOD_STR)
283 {
284 static_cast<Manager*>(userData)
285 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
286 }
287 }
288 return 0;
289}
Lei YU415b9642017-02-09 11:37:26 +0800290
Lei YUa5003ce2017-02-24 15:35:25 +0800291bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800292{
Lei YUddd54422017-04-18 16:38:44 +0800293 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800294 if (newMode != timeMode)
295 {
296 log<level::INFO>("Time mode is changed",
297 entry("MODE=%s", mode.c_str()));
298 timeMode = newMode;
299 utils::writeData(modeFile, mode);
300 return true;
301 }
302 else
303 {
304 return false;
305 }
Lei YU415b9642017-02-09 11:37:26 +0800306}
307
Lei YUa5003ce2017-02-24 15:35:25 +0800308bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800309{
Lei YUddd54422017-04-18 16:38:44 +0800310 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800311 if (newOwner != timeOwner)
312 {
313 log<level::INFO>("Time owner is changed",
314 entry("OWNER=%s", owner.c_str()));
315 timeOwner = newOwner;
316 utils::writeData(ownerFile, owner);
317 return true;
318 }
319 else
320 {
321 return false;
322 }
323}
324
325void Manager::onTimeModeChanged(const std::string& mode)
326{
327 for (const auto listener : listeners)
328 {
329 listener->onModeChanged(timeMode);
330 }
331 // When time_mode is updated, update the NTP setting
332 updateNtpSetting(mode);
333}
334
335void Manager::onTimeOwnerChanged()
336{
337 for (const auto& listener : listeners)
338 {
339 listener->onOwnerChanged(timeOwner);
340 }
Lei YU415b9642017-02-09 11:37:26 +0800341}
342
Lei YUdd8e9e42017-04-19 17:46:58 +0800343std::string Manager::getSettings(const char* setting) const
Lei YU415b9642017-02-09 11:37:26 +0800344{
Lei YUdd8e9e42017-04-19 17:46:58 +0800345 std::string settingsService = utils::getService(bus,
346 SETTINGS_PATH,
347 SETTINGS_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +0800348
349 return utils::getProperty<std::string>(bus,
350 settingsService.c_str(),
351 SETTINGS_PATH,
352 SETTINGS_INTERFACE,
353 setting);
Lei YU415b9642017-02-09 11:37:26 +0800354}
355
Lei YU415b9642017-02-09 11:37:26 +0800356}
357}