blob: bcc581cea3a0366071bf0f47e83cc92a4ab04fb7 [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{
10constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host";
11constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
12constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
Lei YU415b9642017-02-09 11:37:26 +080013
Lei YU415b9642017-02-09 11:37:26 +080014// TODO: Use new settings in xyz.openbmc_project
15const auto MATCH_PROPERTY_CHANGE =
16 rules::type::signal() +
17 rules::member("PropertiesChanged") +
18 rules::path("/org/openbmc/settings/host0") +
19 rules::interface("org.freedesktop.DBus.Properties");
20
Lei YUc6fe8692017-02-23 15:12:07 +080021const auto MATCH_PGOOD_CHANGE =
22 rules::type::signal() +
23 rules::member("PropertiesChanged") +
24 rules::path("/org/openbmc/control/power0") +
25 rules::interface("org.freedesktop.DBus.Properties");
26
Lei YUc6fe8692017-02-23 15:12:07 +080027constexpr auto POWER_SERVICE = "org.openbmc.control.Power";
28constexpr auto POWER_PATH = "/org/openbmc/control/power0";
29constexpr auto POWER_INTERFACE = POWER_SERVICE;
30constexpr auto PGOOD_STR = "pgood";
Lei YUa7417132017-02-23 15:24:05 +080031
32constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
33constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
34constexpr auto SYSTEMD_TIME_INTERFACE = SYSTEMD_TIME_SERVICE;
35constexpr auto METHOD_SET_NTP = "SetNTP";
36
37constexpr auto OBMC_NETWORK_SERVICE = "org.openbmc.NetworkManager";
38constexpr auto OBMC_NETWORK_PATH = "/org/openbmc/NetworkManager/Interface";
39constexpr auto OBMC_NETWORK_INTERFACE = OBMC_NETWORK_SERVICE;
40constexpr 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
53const std::map<std::string, Owner> Manager::ownerMap =
54{
55 { "BMC", Owner::BMC },
56 { "HOST", Owner::HOST },
57 { "SPLIT", Owner::SPLIT },
58 { "BOTH", Owner::BOTH },
59};
60
61Manager::Manager(sdbusplus::bus::bus& bus)
62 : bus(bus),
Lei YUc6fe8692017-02-23 15:12:07 +080063 propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this),
64 pgoodChangeMatch(bus, MATCH_PGOOD_CHANGE, onPgoodChanged, this)
Lei YU415b9642017-02-09 11:37:26 +080065{
Lei YUc6fe8692017-02-23 15:12:07 +080066 checkHostOn();
Lei YU7f4fca52017-02-23 15:15:51 +080067
68 // Restore settings from persistent storage
69 restoreSettings();
70
71 // Check the settings daemon to process the new settings
72 onPropertyChanged(PROPERTY_TIME_MODE, getSettings(PROPERTY_TIME_MODE));
73 onPropertyChanged(PROPERTY_TIME_OWNER, getSettings(PROPERTY_TIME_OWNER));
Lei YUa7417132017-02-23 15:24:05 +080074
75 checkDhcpNtp();
Lei YU415b9642017-02-09 11:37:26 +080076}
77
78void Manager::addListener(PropertyChangeListner* listener)
79{
80 // Notify listener about the initial value
81 listener->onModeChanged(timeMode);
82 listener->onOwnerChanged(timeOwner);
83
84 listeners.insert(listener);
85}
86
Lei YU7f4fca52017-02-23 15:15:51 +080087void Manager::restoreSettings()
88{
89 auto mode = utils::readData<std::string>(modeFile);
90 if (!mode.empty())
91 {
92 timeMode = convertToMode(mode);
93 }
94 auto owner = utils::readData<std::string>(ownerFile);
95 if (!owner.empty())
96 {
97 timeOwner = convertToOwner(owner);
98 }
99}
100
Lei YUc6fe8692017-02-23 15:12:07 +0800101void Manager::checkHostOn()
102{
Lei YUa7417132017-02-23 15:24:05 +0800103 int pgood = utils::getProperty<int>(bus,
104 POWER_SERVICE,
105 POWER_PATH,
106 POWER_INTERFACE,
107 PGOOD_STR);
108 hostOn = static_cast<bool>(pgood);
109}
Lei YUc6fe8692017-02-23 15:12:07 +0800110
Lei YUa7417132017-02-23 15:24:05 +0800111void Manager::checkDhcpNtp()
112{
113 std::string useDhcpNtp = utils::getProperty<std::string>(
114 bus,
115 SETTINGS_SERVICE,
116 SETTINGS_PATH,
117 SETTINGS_INTERFACE,
118 PROPERTY_DHCP_NTP);
119 updateDhcpNtpSetting(useDhcpNtp);
Lei YUc6fe8692017-02-23 15:12:07 +0800120}
121
Lei YU415b9642017-02-09 11:37:26 +0800122void Manager::onPropertyChanged(const std::string& key,
123 const std::string& value)
124{
Lei YU7f4fca52017-02-23 15:15:51 +0800125 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800126 {
Lei YU7f4fca52017-02-23 15:15:51 +0800127 // If host is on, set the values as requested time mode/owner.
128 // And when host becomes off, notify the listners.
129 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800130 }
Lei YU7f4fca52017-02-23 15:15:51 +0800131 else
Lei YU415b9642017-02-09 11:37:26 +0800132 {
Lei YU7f4fca52017-02-23 15:15:51 +0800133 // If host is off, notify listners
134 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800135 {
Lei YU7f4fca52017-02-23 15:15:51 +0800136 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800137 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800138 }
139 else if (key == PROPERTY_TIME_OWNER)
140 {
141 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800142 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800143 }
144 }
145}
146
147int Manager::onPropertyChanged(sd_bus_message* msg,
148 void* userData,
149 sd_bus_error* retError)
150{
151 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800152 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800153 auto m = sdbusplus::message::message(msg);
154 // message type: sa{sv}as
155 std::string ignore;
156 properties props;
157 m.read(ignore, props);
Lei YUa7417132017-02-23 15:24:05 +0800158 auto manager = static_cast<Manager*>(userData);
Lei YU415b9642017-02-09 11:37:26 +0800159 for (const auto& item : props)
160 {
161 if (managedProperties.find(item.first) != managedProperties.end())
162 {
Lei YUa7417132017-02-23 15:24:05 +0800163 // For managed properties, notify listeners
164 manager->onPropertyChanged(
Lei YU7f4fca52017-02-23 15:15:51 +0800165 item.first, item.second.get<std::string>());
Lei YU415b9642017-02-09 11:37:26 +0800166 }
Lei YUa7417132017-02-23 15:24:05 +0800167 else if (item.first == PROPERTY_DHCP_NTP)
168 {
169 // For other manager interested properties, handle specifically
170 manager->updateDhcpNtpSetting(item.second.get<std::string>());
171 }
Lei YU415b9642017-02-09 11:37:26 +0800172 }
173 return 0;
174}
175
Lei YU7f4fca52017-02-23 15:15:51 +0800176void Manager::setPropertyAsRequested(const std::string& key,
177 const std::string& value)
178{
179 if (key == PROPERTY_TIME_MODE)
180 {
181 setRequestedMode(value);
182 }
183 else if (key == PROPERTY_TIME_OWNER)
184 {
185 setRequestedOwner(value);
186 }
187 else
188 {
189 // The key shall be already the supported one
190 // TODO: use elog API
191 assert(false);
192 }
193}
194
195void Manager::setRequestedMode(const std::string& mode)
196{
197 requestedMode = mode;
198}
199
200void Manager::setRequestedOwner(const std::string& owner)
201{
202 requestedOwner = owner;
203}
204
Lei YUa7417132017-02-23 15:24:05 +0800205void Manager::updateNtpSetting(const std::string& value)
206{
207 bool isNtp = (value == "NTP");
208 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
209 SYSTEMD_TIME_PATH,
210 SYSTEMD_TIME_INTERFACE,
211 METHOD_SET_NTP);
212 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
213 // 'false' meaning no policy-kit
214
215 if (bus.call(method))
216 {
217 log<level::INFO>("Updated NTP setting",
218 entry("ENABLED:%d", isNtp));
219 }
220 else
221 {
222 log<level::ERR>("Failed to update NTP setting");
223 }
224}
225
226void Manager::updateDhcpNtpSetting(const std::string& useDhcpNtp)
227{
228 auto method = bus.new_method_call(OBMC_NETWORK_SERVICE,
229 OBMC_NETWORK_PATH,
230 OBMC_NETWORK_INTERFACE,
231 METHOD_UPDATE_USE_NTP);
232 method.append(useDhcpNtp);
233
234 if (bus.call(method))
235 {
236 log<level::INFO>("Updated use ntp field",
237 entry("USENTPFIELD:%s", useDhcpNtp.c_str()));
238 }
239 else
240 {
241 log<level::ERR>("Failed to update UseNtpField");
242 }
243}
244
Lei YUc6fe8692017-02-23 15:12:07 +0800245void Manager::onPgoodChanged(bool pgood)
246{
247 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800248 if (hostOn)
249 {
250 return;
251 }
252 if (!requestedMode.empty())
253 {
Lei YUa5003ce2017-02-24 15:35:25 +0800254 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800255 {
Lei YUa5003ce2017-02-24 15:35:25 +0800256 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800257 }
258 setRequestedMode({}); // Clear requested mode
259 }
260 if (!requestedOwner.empty())
261 {
Lei YUa5003ce2017-02-24 15:35:25 +0800262 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800263 {
Lei YUa5003ce2017-02-24 15:35:25 +0800264 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800265 }
266 setRequestedOwner({}); // Clear requested owner
267 }
Lei YUc6fe8692017-02-23 15:12:07 +0800268}
269
270int Manager::onPgoodChanged(sd_bus_message* msg,
271 void* userData,
272 sd_bus_error* retError)
273{
274 using properties = std::map < std::string,
275 sdbusplus::message::variant<int> >;
276 auto m = sdbusplus::message::message(msg);
277 // message type: sa{sv}as
278 std::string ignore;
279 properties props;
280 m.read(ignore, props);
281 for (const auto& item : props)
282 {
283 if (item.first == PGOOD_STR)
284 {
285 static_cast<Manager*>(userData)
286 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
287 }
288 }
289 return 0;
290}
Lei YU415b9642017-02-09 11:37:26 +0800291
Lei YUa5003ce2017-02-24 15:35:25 +0800292bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800293{
Lei YUa5003ce2017-02-24 15:35:25 +0800294 auto newMode = convertToMode(mode);
295 if (newMode != timeMode)
296 {
297 log<level::INFO>("Time mode is changed",
298 entry("MODE=%s", mode.c_str()));
299 timeMode = newMode;
300 utils::writeData(modeFile, mode);
301 return true;
302 }
303 else
304 {
305 return false;
306 }
Lei YU415b9642017-02-09 11:37:26 +0800307}
308
Lei YUa5003ce2017-02-24 15:35:25 +0800309bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800310{
Lei YUa5003ce2017-02-24 15:35:25 +0800311 auto newOwner = convertToOwner(owner);
312 if (newOwner != timeOwner)
313 {
314 log<level::INFO>("Time owner is changed",
315 entry("OWNER=%s", owner.c_str()));
316 timeOwner = newOwner;
317 utils::writeData(ownerFile, owner);
318 return true;
319 }
320 else
321 {
322 return false;
323 }
324}
325
326void Manager::onTimeModeChanged(const std::string& mode)
327{
328 for (const auto listener : listeners)
329 {
330 listener->onModeChanged(timeMode);
331 }
332 // When time_mode is updated, update the NTP setting
333 updateNtpSetting(mode);
334}
335
336void Manager::onTimeOwnerChanged()
337{
338 for (const auto& listener : listeners)
339 {
340 listener->onOwnerChanged(timeOwner);
341 }
Lei YU415b9642017-02-09 11:37:26 +0800342}
343
344std::string Manager::getSettings(const char* value) const
345{
Lei YUa7417132017-02-23 15:24:05 +0800346 return utils::getProperty<std::string>(
347 bus,
348 SETTINGS_SERVICE,
349 SETTINGS_PATH,
350 SETTINGS_INTERFACE,
351 value);
Lei YU415b9642017-02-09 11:37:26 +0800352}
353
354Mode Manager::convertToMode(const std::string& mode)
355{
356 if (mode == "NTP")
357 {
358 return Mode::NTP;
359 }
360 else if (mode == "MANUAL")
361 {
362 return Mode::MANUAL;
363 }
364 else
365 {
366 log<level::ERR>("Unrecognized mode",
367 entry("%s", mode.c_str()));
368 return Mode::NTP;
369 }
370}
371
372Owner Manager::convertToOwner(const std::string& owner)
373{
374 auto it = ownerMap.find(owner);
375 if (it == ownerMap.end())
376 {
377 log<level::ERR>("Unrecognized owner",
378 entry("%s", owner.c_str()));
379 return Owner::BMC;
380 }
381 return it->second;
382}
383
384}
385}