blob: 03992b116de9b7c8f6d17afde587fb81dc1c1996 [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
4#include <phosphor-logging/log.hpp>
5
6namespace rules = sdbusplus::bus::match::rules;
7
8namespace // anonymous
9{
Lei YU415b9642017-02-09 11:37:26 +080010constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
11constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
Lei YU415b9642017-02-09 11:37:26 +080012
Lei YU415b9642017-02-09 11:37:26 +080013// TODO: Use new settings in xyz.openbmc_project
14const auto MATCH_PROPERTY_CHANGE =
15 rules::type::signal() +
16 rules::member("PropertiesChanged") +
17 rules::path("/org/openbmc/settings/host0") +
18 rules::interface("org.freedesktop.DBus.Properties");
19
Lei YUc6fe8692017-02-23 15:12:07 +080020const auto MATCH_PGOOD_CHANGE =
21 rules::type::signal() +
22 rules::member("PropertiesChanged") +
23 rules::path("/org/openbmc/control/power0") +
24 rules::interface("org.freedesktop.DBus.Properties");
25
Lei YUc6fe8692017-02-23 15:12:07 +080026constexpr auto POWER_PATH = "/org/openbmc/control/power0";
Lei YUdd8e9e42017-04-19 17:46:58 +080027constexpr auto POWER_INTERFACE = "org.openbmc.control.Power";
Lei YUc6fe8692017-02-23 15:12:07 +080028constexpr auto PGOOD_STR = "pgood";
Lei YUa7417132017-02-23 15:24:05 +080029
30constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
31constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
Lei YUdd8e9e42017-04-19 17:46:58 +080032constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
Lei YUa7417132017-02-23 15:24:05 +080033constexpr auto METHOD_SET_NTP = "SetNTP";
34
Lei YUa7417132017-02-23 15:24:05 +080035constexpr auto OBMC_NETWORK_PATH = "/org/openbmc/NetworkManager/Interface";
Lei YUdd8e9e42017-04-19 17:46:58 +080036constexpr auto OBMC_NETWORK_INTERFACE = "org.openbmc.NetworkManager";
Lei YUa7417132017-02-23 15:24:05 +080037constexpr auto METHOD_UPDATE_USE_NTP = "UpdateUseNtpField";
Lei YU415b9642017-02-09 11:37:26 +080038}
39
40namespace phosphor
41{
42namespace time
43{
44
45using namespace phosphor::logging;
46
47const std::set<std::string>
48Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
49
Lei YU415b9642017-02-09 11:37:26 +080050Manager::Manager(sdbusplus::bus::bus& bus)
51 : bus(bus),
Lei YUc6fe8692017-02-23 15:12:07 +080052 propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this),
53 pgoodChangeMatch(bus, MATCH_PGOOD_CHANGE, onPgoodChanged, this)
Lei YU415b9642017-02-09 11:37:26 +080054{
Lei YUc6fe8692017-02-23 15:12:07 +080055 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080056
57 // Restore settings from persistent storage
58 restoreSettings();
59
60 // Check the settings daemon to process the new settings
61 onPropertyChanged(PROPERTY_TIME_MODE, getSettings(PROPERTY_TIME_MODE));
62 onPropertyChanged(PROPERTY_TIME_OWNER, getSettings(PROPERTY_TIME_OWNER));
Lei YUa7417132017-02-23 15:24:05 +080063
64 checkDhcpNtp();
Lei YU415b9642017-02-09 11:37:26 +080065}
66
67void Manager::addListener(PropertyChangeListner* listener)
68{
69 // Notify listener about the initial value
70 listener->onModeChanged(timeMode);
71 listener->onOwnerChanged(timeOwner);
72
73 listeners.insert(listener);
74}
75
Lei YU7f4fca52017-02-23 15:15:51 +080076void Manager::restoreSettings()
77{
78 auto mode = utils::readData<std::string>(modeFile);
79 if (!mode.empty())
80 {
Lei YUddd54422017-04-18 16:38:44 +080081 timeMode = utils::strToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +080082 }
83 auto owner = utils::readData<std::string>(ownerFile);
84 if (!owner.empty())
85 {
Lei YUddd54422017-04-18 16:38:44 +080086 timeOwner = utils::strToOwner(owner);
Lei YU7f4fca52017-02-23 15:15:51 +080087 }
88}
89
Lei YUc6fe8692017-02-23 15:12:07 +080090void Manager::checkHostOn()
91{
Lei YUdd8e9e42017-04-19 17:46:58 +080092 std::string powerService = utils::getService(bus,
93 POWER_PATH,
94 POWER_INTERFACE);
95 if (powerService.empty())
96 {
97 log<level::ERR>("Failed to get power service, assume host is off");
98 return;
99 }
100
Lei YUa7417132017-02-23 15:24:05 +0800101 int pgood = utils::getProperty<int>(bus,
Lei YUdd8e9e42017-04-19 17:46:58 +0800102 powerService.c_str(),
Lei YUa7417132017-02-23 15:24:05 +0800103 POWER_PATH,
104 POWER_INTERFACE,
105 PGOOD_STR);
106 hostOn = static_cast<bool>(pgood);
107}
Lei YUc6fe8692017-02-23 15:12:07 +0800108
Lei YUa7417132017-02-23 15:24:05 +0800109void Manager::checkDhcpNtp()
110{
Lei YUdd8e9e42017-04-19 17:46:58 +0800111 std::string useDhcpNtp = getSettings(PROPERTY_DHCP_NTP);
Lei YUa7417132017-02-23 15:24:05 +0800112 updateDhcpNtpSetting(useDhcpNtp);
Lei YUc6fe8692017-02-23 15:12:07 +0800113}
114
Lei YU415b9642017-02-09 11:37:26 +0800115void Manager::onPropertyChanged(const std::string& key,
116 const std::string& value)
117{
Lei YU7f4fca52017-02-23 15:15:51 +0800118 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800119 {
Lei YU7f4fca52017-02-23 15:15:51 +0800120 // If host is on, set the values as requested time mode/owner.
121 // And when host becomes off, notify the listners.
122 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800123 }
Lei YU7f4fca52017-02-23 15:15:51 +0800124 else
Lei YU415b9642017-02-09 11:37:26 +0800125 {
Lei YU7f4fca52017-02-23 15:15:51 +0800126 // If host is off, notify listners
127 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800128 {
Lei YU7f4fca52017-02-23 15:15:51 +0800129 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800130 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800131 }
132 else if (key == PROPERTY_TIME_OWNER)
133 {
134 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800135 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800136 }
137 }
138}
139
140int Manager::onPropertyChanged(sd_bus_message* msg,
141 void* userData,
142 sd_bus_error* retError)
143{
144 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800145 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800146 auto m = sdbusplus::message::message(msg);
147 // message type: sa{sv}as
148 std::string ignore;
149 properties props;
150 m.read(ignore, props);
Lei YUa7417132017-02-23 15:24:05 +0800151 auto manager = static_cast<Manager*>(userData);
Lei YU415b9642017-02-09 11:37:26 +0800152 for (const auto& item : props)
153 {
154 if (managedProperties.find(item.first) != managedProperties.end())
155 {
Lei YUa7417132017-02-23 15:24:05 +0800156 // For managed properties, notify listeners
157 manager->onPropertyChanged(
Lei YU7f4fca52017-02-23 15:15:51 +0800158 item.first, item.second.get<std::string>());
Lei YU415b9642017-02-09 11:37:26 +0800159 }
Lei YUa7417132017-02-23 15:24:05 +0800160 else if (item.first == PROPERTY_DHCP_NTP)
161 {
162 // For other manager interested properties, handle specifically
163 manager->updateDhcpNtpSetting(item.second.get<std::string>());
164 }
Lei YU415b9642017-02-09 11:37:26 +0800165 }
166 return 0;
167}
168
Lei YU7f4fca52017-02-23 15:15:51 +0800169void Manager::setPropertyAsRequested(const std::string& key,
170 const std::string& value)
171{
172 if (key == PROPERTY_TIME_MODE)
173 {
174 setRequestedMode(value);
175 }
176 else if (key == PROPERTY_TIME_OWNER)
177 {
178 setRequestedOwner(value);
179 }
180 else
181 {
182 // The key shall be already the supported one
183 // TODO: use elog API
184 assert(false);
185 }
186}
187
188void Manager::setRequestedMode(const std::string& mode)
189{
190 requestedMode = mode;
191}
192
193void Manager::setRequestedOwner(const std::string& owner)
194{
195 requestedOwner = owner;
196}
197
Lei YUa7417132017-02-23 15:24:05 +0800198void Manager::updateNtpSetting(const std::string& value)
199{
200 bool isNtp = (value == "NTP");
201 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
202 SYSTEMD_TIME_PATH,
203 SYSTEMD_TIME_INTERFACE,
204 METHOD_SET_NTP);
205 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
206 // 'false' meaning no policy-kit
207
208 if (bus.call(method))
209 {
210 log<level::INFO>("Updated NTP setting",
211 entry("ENABLED:%d", isNtp));
212 }
213 else
214 {
215 log<level::ERR>("Failed to update NTP setting");
216 }
217}
218
219void Manager::updateDhcpNtpSetting(const std::string& useDhcpNtp)
220{
Lei YUdd8e9e42017-04-19 17:46:58 +0800221 std::string networkService = utils::getService(bus,
222 OBMC_NETWORK_PATH,
223 OBMC_NETWORK_INTERFACE);
224 if (networkService.empty())
225 {
226 log<level::ERR>("Failed to get network service, ignore dhcp ntp");
227 return;
228 }
229
230 auto method = bus.new_method_call(networkService.c_str(),
Lei YUa7417132017-02-23 15:24:05 +0800231 OBMC_NETWORK_PATH,
232 OBMC_NETWORK_INTERFACE,
233 METHOD_UPDATE_USE_NTP);
234 method.append(useDhcpNtp);
235
236 if (bus.call(method))
237 {
238 log<level::INFO>("Updated use ntp field",
239 entry("USENTPFIELD:%s", useDhcpNtp.c_str()));
240 }
241 else
242 {
243 log<level::ERR>("Failed to update UseNtpField");
244 }
245}
246
Lei YUc6fe8692017-02-23 15:12:07 +0800247void Manager::onPgoodChanged(bool pgood)
248{
249 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800250 if (hostOn)
251 {
252 return;
253 }
254 if (!requestedMode.empty())
255 {
Lei YUa5003ce2017-02-24 15:35:25 +0800256 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800257 {
Lei YUa5003ce2017-02-24 15:35:25 +0800258 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800259 }
260 setRequestedMode({}); // Clear requested mode
261 }
262 if (!requestedOwner.empty())
263 {
Lei YUa5003ce2017-02-24 15:35:25 +0800264 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800265 {
Lei YUa5003ce2017-02-24 15:35:25 +0800266 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800267 }
268 setRequestedOwner({}); // Clear requested owner
269 }
Lei YUc6fe8692017-02-23 15:12:07 +0800270}
271
272int Manager::onPgoodChanged(sd_bus_message* msg,
273 void* userData,
274 sd_bus_error* retError)
275{
276 using properties = std::map < std::string,
277 sdbusplus::message::variant<int> >;
278 auto m = sdbusplus::message::message(msg);
279 // message type: sa{sv}as
280 std::string ignore;
281 properties props;
282 m.read(ignore, props);
283 for (const auto& item : props)
284 {
285 if (item.first == PGOOD_STR)
286 {
287 static_cast<Manager*>(userData)
288 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
289 }
290 }
291 return 0;
292}
Lei YU415b9642017-02-09 11:37:26 +0800293
Lei YUa5003ce2017-02-24 15:35:25 +0800294bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800295{
Lei YUddd54422017-04-18 16:38:44 +0800296 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800297 if (newMode != timeMode)
298 {
299 log<level::INFO>("Time mode is changed",
300 entry("MODE=%s", mode.c_str()));
301 timeMode = newMode;
302 utils::writeData(modeFile, mode);
303 return true;
304 }
305 else
306 {
307 return false;
308 }
Lei YU415b9642017-02-09 11:37:26 +0800309}
310
Lei YUa5003ce2017-02-24 15:35:25 +0800311bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800312{
Lei YUddd54422017-04-18 16:38:44 +0800313 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800314 if (newOwner != timeOwner)
315 {
316 log<level::INFO>("Time owner is changed",
317 entry("OWNER=%s", owner.c_str()));
318 timeOwner = newOwner;
319 utils::writeData(ownerFile, owner);
320 return true;
321 }
322 else
323 {
324 return false;
325 }
326}
327
328void Manager::onTimeModeChanged(const std::string& mode)
329{
330 for (const auto listener : listeners)
331 {
332 listener->onModeChanged(timeMode);
333 }
334 // When time_mode is updated, update the NTP setting
335 updateNtpSetting(mode);
336}
337
338void Manager::onTimeOwnerChanged()
339{
340 for (const auto& listener : listeners)
341 {
342 listener->onOwnerChanged(timeOwner);
343 }
Lei YU415b9642017-02-09 11:37:26 +0800344}
345
Lei YUdd8e9e42017-04-19 17:46:58 +0800346std::string Manager::getSettings(const char* setting) const
Lei YU415b9642017-02-09 11:37:26 +0800347{
Lei YUdd8e9e42017-04-19 17:46:58 +0800348 std::string settingsService = utils::getService(bus,
349 SETTINGS_PATH,
350 SETTINGS_INTERFACE);
351 if (settingsService.empty())
352 {
353 log<level::ERR>("Failed to get settings service, unable to get setting",
354 entry("SETTING=%s", setting));
355 return {};
356 }
357
358 return utils::getProperty<std::string>(bus,
359 settingsService.c_str(),
360 SETTINGS_PATH,
361 SETTINGS_INTERFACE,
362 setting);
Lei YU415b9642017-02-09 11:37:26 +0800363}
364
Lei YU415b9642017-02-09 11:37:26 +0800365}
366}