blob: 36ff351f528a2bbb48d84c11d751e10cb5485453 [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
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 YUa7417132017-02-23 15:24:05 +080095 int pgood = utils::getProperty<int>(bus,
96 POWER_SERVICE,
97 POWER_PATH,
98 POWER_INTERFACE,
99 PGOOD_STR);
100 hostOn = static_cast<bool>(pgood);
101}
Lei YUc6fe8692017-02-23 15:12:07 +0800102
Lei YUa7417132017-02-23 15:24:05 +0800103void Manager::checkDhcpNtp()
104{
105 std::string useDhcpNtp = utils::getProperty<std::string>(
106 bus,
107 SETTINGS_SERVICE,
108 SETTINGS_PATH,
109 SETTINGS_INTERFACE,
110 PROPERTY_DHCP_NTP);
111 updateDhcpNtpSetting(useDhcpNtp);
Lei YUc6fe8692017-02-23 15:12:07 +0800112}
113
Lei YU415b9642017-02-09 11:37:26 +0800114void Manager::onPropertyChanged(const std::string& key,
115 const std::string& value)
116{
Lei YU7f4fca52017-02-23 15:15:51 +0800117 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800118 {
Lei YU7f4fca52017-02-23 15:15:51 +0800119 // If host is on, set the values as requested time mode/owner.
120 // And when host becomes off, notify the listners.
121 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800122 }
Lei YU7f4fca52017-02-23 15:15:51 +0800123 else
Lei YU415b9642017-02-09 11:37:26 +0800124 {
Lei YU7f4fca52017-02-23 15:15:51 +0800125 // If host is off, notify listners
126 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800127 {
Lei YU7f4fca52017-02-23 15:15:51 +0800128 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800129 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800130 }
131 else if (key == PROPERTY_TIME_OWNER)
132 {
133 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800134 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800135 }
136 }
137}
138
139int Manager::onPropertyChanged(sd_bus_message* msg,
140 void* userData,
141 sd_bus_error* retError)
142{
143 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800144 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800145 auto m = sdbusplus::message::message(msg);
146 // message type: sa{sv}as
147 std::string ignore;
148 properties props;
149 m.read(ignore, props);
Lei YUa7417132017-02-23 15:24:05 +0800150 auto manager = static_cast<Manager*>(userData);
Lei YU415b9642017-02-09 11:37:26 +0800151 for (const auto& item : props)
152 {
153 if (managedProperties.find(item.first) != managedProperties.end())
154 {
Lei YUa7417132017-02-23 15:24:05 +0800155 // For managed properties, notify listeners
156 manager->onPropertyChanged(
Lei YU7f4fca52017-02-23 15:15:51 +0800157 item.first, item.second.get<std::string>());
Lei YU415b9642017-02-09 11:37:26 +0800158 }
Lei YUa7417132017-02-23 15:24:05 +0800159 else if (item.first == PROPERTY_DHCP_NTP)
160 {
161 // For other manager interested properties, handle specifically
162 manager->updateDhcpNtpSetting(item.second.get<std::string>());
163 }
Lei YU415b9642017-02-09 11:37:26 +0800164 }
165 return 0;
166}
167
Lei YU7f4fca52017-02-23 15:15:51 +0800168void Manager::setPropertyAsRequested(const std::string& key,
169 const std::string& value)
170{
171 if (key == PROPERTY_TIME_MODE)
172 {
173 setRequestedMode(value);
174 }
175 else if (key == PROPERTY_TIME_OWNER)
176 {
177 setRequestedOwner(value);
178 }
179 else
180 {
181 // The key shall be already the supported one
182 // TODO: use elog API
183 assert(false);
184 }
185}
186
187void Manager::setRequestedMode(const std::string& mode)
188{
189 requestedMode = mode;
190}
191
192void Manager::setRequestedOwner(const std::string& owner)
193{
194 requestedOwner = owner;
195}
196
Lei YUa7417132017-02-23 15:24:05 +0800197void Manager::updateNtpSetting(const std::string& value)
198{
199 bool isNtp = (value == "NTP");
200 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
201 SYSTEMD_TIME_PATH,
202 SYSTEMD_TIME_INTERFACE,
203 METHOD_SET_NTP);
204 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
205 // 'false' meaning no policy-kit
206
207 if (bus.call(method))
208 {
209 log<level::INFO>("Updated NTP setting",
210 entry("ENABLED:%d", isNtp));
211 }
212 else
213 {
214 log<level::ERR>("Failed to update NTP setting");
215 }
216}
217
218void Manager::updateDhcpNtpSetting(const std::string& useDhcpNtp)
219{
220 auto method = bus.new_method_call(OBMC_NETWORK_SERVICE,
221 OBMC_NETWORK_PATH,
222 OBMC_NETWORK_INTERFACE,
223 METHOD_UPDATE_USE_NTP);
224 method.append(useDhcpNtp);
225
226 if (bus.call(method))
227 {
228 log<level::INFO>("Updated use ntp field",
229 entry("USENTPFIELD:%s", useDhcpNtp.c_str()));
230 }
231 else
232 {
233 log<level::ERR>("Failed to update UseNtpField");
234 }
235}
236
Lei YUc6fe8692017-02-23 15:12:07 +0800237void Manager::onPgoodChanged(bool pgood)
238{
239 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800240 if (hostOn)
241 {
242 return;
243 }
244 if (!requestedMode.empty())
245 {
Lei YUa5003ce2017-02-24 15:35:25 +0800246 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800247 {
Lei YUa5003ce2017-02-24 15:35:25 +0800248 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800249 }
250 setRequestedMode({}); // Clear requested mode
251 }
252 if (!requestedOwner.empty())
253 {
Lei YUa5003ce2017-02-24 15:35:25 +0800254 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800255 {
Lei YUa5003ce2017-02-24 15:35:25 +0800256 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800257 }
258 setRequestedOwner({}); // Clear requested owner
259 }
Lei YUc6fe8692017-02-23 15:12:07 +0800260}
261
262int Manager::onPgoodChanged(sd_bus_message* msg,
263 void* userData,
264 sd_bus_error* retError)
265{
266 using properties = std::map < std::string,
267 sdbusplus::message::variant<int> >;
268 auto m = sdbusplus::message::message(msg);
269 // message type: sa{sv}as
270 std::string ignore;
271 properties props;
272 m.read(ignore, props);
273 for (const auto& item : props)
274 {
275 if (item.first == PGOOD_STR)
276 {
277 static_cast<Manager*>(userData)
278 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
279 }
280 }
281 return 0;
282}
Lei YU415b9642017-02-09 11:37:26 +0800283
Lei YUa5003ce2017-02-24 15:35:25 +0800284bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800285{
Lei YUddd54422017-04-18 16:38:44 +0800286 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800287 if (newMode != timeMode)
288 {
289 log<level::INFO>("Time mode is changed",
290 entry("MODE=%s", mode.c_str()));
291 timeMode = newMode;
292 utils::writeData(modeFile, mode);
293 return true;
294 }
295 else
296 {
297 return false;
298 }
Lei YU415b9642017-02-09 11:37:26 +0800299}
300
Lei YUa5003ce2017-02-24 15:35:25 +0800301bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800302{
Lei YUddd54422017-04-18 16:38:44 +0800303 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800304 if (newOwner != timeOwner)
305 {
306 log<level::INFO>("Time owner is changed",
307 entry("OWNER=%s", owner.c_str()));
308 timeOwner = newOwner;
309 utils::writeData(ownerFile, owner);
310 return true;
311 }
312 else
313 {
314 return false;
315 }
316}
317
318void Manager::onTimeModeChanged(const std::string& mode)
319{
320 for (const auto listener : listeners)
321 {
322 listener->onModeChanged(timeMode);
323 }
324 // When time_mode is updated, update the NTP setting
325 updateNtpSetting(mode);
326}
327
328void Manager::onTimeOwnerChanged()
329{
330 for (const auto& listener : listeners)
331 {
332 listener->onOwnerChanged(timeOwner);
333 }
Lei YU415b9642017-02-09 11:37:26 +0800334}
335
336std::string Manager::getSettings(const char* value) const
337{
Lei YUa7417132017-02-23 15:24:05 +0800338 return utils::getProperty<std::string>(
339 bus,
340 SETTINGS_SERVICE,
341 SETTINGS_PATH,
342 SETTINGS_INTERFACE,
343 value);
Lei YU415b9642017-02-09 11:37:26 +0800344}
345
Lei YU415b9642017-02-09 11:37:26 +0800346}
347}