blob: 56e0d0ba1a7c933d4e225a6e428dfc186ce57da9 [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);
137 for (const auto listener : listeners)
138 {
139 listener->onModeChanged(timeMode);
140 }
Lei YUa7417132017-02-23 15:24:05 +0800141 // When time_mode is updated, update the NTP setting
142 updateNtpSetting(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800143 }
144 else if (key == PROPERTY_TIME_OWNER)
145 {
146 setCurrentTimeOwner(value);
147 for (const auto listener : listeners)
148 {
149 listener->onOwnerChanged(timeOwner);
150 }
Lei YU415b9642017-02-09 11:37:26 +0800151 }
152 }
153}
154
155int Manager::onPropertyChanged(sd_bus_message* msg,
156 void* userData,
157 sd_bus_error* retError)
158{
159 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800160 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800161 auto m = sdbusplus::message::message(msg);
162 // message type: sa{sv}as
163 std::string ignore;
164 properties props;
165 m.read(ignore, props);
Lei YUa7417132017-02-23 15:24:05 +0800166 auto manager = static_cast<Manager*>(userData);
Lei YU415b9642017-02-09 11:37:26 +0800167 for (const auto& item : props)
168 {
169 if (managedProperties.find(item.first) != managedProperties.end())
170 {
Lei YUa7417132017-02-23 15:24:05 +0800171 // For managed properties, notify listeners
172 manager->onPropertyChanged(
Lei YU7f4fca52017-02-23 15:15:51 +0800173 item.first, item.second.get<std::string>());
Lei YU415b9642017-02-09 11:37:26 +0800174 }
Lei YUa7417132017-02-23 15:24:05 +0800175 else if (item.first == PROPERTY_DHCP_NTP)
176 {
177 // For other manager interested properties, handle specifically
178 manager->updateDhcpNtpSetting(item.second.get<std::string>());
179 }
Lei YU415b9642017-02-09 11:37:26 +0800180 }
181 return 0;
182}
183
Lei YU7f4fca52017-02-23 15:15:51 +0800184void Manager::setPropertyAsRequested(const std::string& key,
185 const std::string& value)
186{
187 if (key == PROPERTY_TIME_MODE)
188 {
189 setRequestedMode(value);
190 }
191 else if (key == PROPERTY_TIME_OWNER)
192 {
193 setRequestedOwner(value);
194 }
195 else
196 {
197 // The key shall be already the supported one
198 // TODO: use elog API
199 assert(false);
200 }
201}
202
203void Manager::setRequestedMode(const std::string& mode)
204{
205 requestedMode = mode;
206}
207
208void Manager::setRequestedOwner(const std::string& owner)
209{
210 requestedOwner = owner;
211}
212
Lei YUa7417132017-02-23 15:24:05 +0800213void Manager::updateNtpSetting(const std::string& value)
214{
215 bool isNtp = (value == "NTP");
216 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
217 SYSTEMD_TIME_PATH,
218 SYSTEMD_TIME_INTERFACE,
219 METHOD_SET_NTP);
220 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
221 // 'false' meaning no policy-kit
222
223 if (bus.call(method))
224 {
225 log<level::INFO>("Updated NTP setting",
226 entry("ENABLED:%d", isNtp));
227 }
228 else
229 {
230 log<level::ERR>("Failed to update NTP setting");
231 }
232}
233
234void Manager::updateDhcpNtpSetting(const std::string& useDhcpNtp)
235{
236 auto method = bus.new_method_call(OBMC_NETWORK_SERVICE,
237 OBMC_NETWORK_PATH,
238 OBMC_NETWORK_INTERFACE,
239 METHOD_UPDATE_USE_NTP);
240 method.append(useDhcpNtp);
241
242 if (bus.call(method))
243 {
244 log<level::INFO>("Updated use ntp field",
245 entry("USENTPFIELD:%s", useDhcpNtp.c_str()));
246 }
247 else
248 {
249 log<level::ERR>("Failed to update UseNtpField");
250 }
251}
252
Lei YUc6fe8692017-02-23 15:12:07 +0800253void Manager::onPgoodChanged(bool pgood)
254{
255 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800256 if (hostOn)
257 {
258 return;
259 }
260 if (!requestedMode.empty())
261 {
262 setCurrentTimeMode(requestedMode);
263 for (const auto& listener : listeners)
264 {
265 listener->onModeChanged(timeMode);
266 }
Lei YUa7417132017-02-23 15:24:05 +0800267 updateNtpSetting(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800268 setRequestedMode({}); // Clear requested mode
269 }
270 if (!requestedOwner.empty())
271 {
272 setCurrentTimeOwner(requestedOwner);
273 for (const auto& listener : listeners)
274 {
275 listener->onOwnerChanged(timeOwner);
276 }
277 setRequestedOwner({}); // Clear requested owner
278 }
Lei YUc6fe8692017-02-23 15:12:07 +0800279}
280
281int Manager::onPgoodChanged(sd_bus_message* msg,
282 void* userData,
283 sd_bus_error* retError)
284{
285 using properties = std::map < std::string,
286 sdbusplus::message::variant<int> >;
287 auto m = sdbusplus::message::message(msg);
288 // message type: sa{sv}as
289 std::string ignore;
290 properties props;
291 m.read(ignore, props);
292 for (const auto& item : props)
293 {
294 if (item.first == PGOOD_STR)
295 {
296 static_cast<Manager*>(userData)
297 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
298 }
299 }
300 return 0;
301}
Lei YU415b9642017-02-09 11:37:26 +0800302
303void Manager::setCurrentTimeMode(const std::string& mode)
304{
305 log<level::INFO>("Time mode is changed",
306 entry("MODE=%s", mode.c_str()));
307 timeMode = convertToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +0800308 utils::writeData(modeFile, mode);
Lei YU415b9642017-02-09 11:37:26 +0800309}
310
311void Manager::setCurrentTimeOwner(const std::string& owner)
312{
313 log<level::INFO>("Time owner is changed",
314 entry("OWNER=%s", owner.c_str()));
315 timeOwner = convertToOwner(owner);
Lei YU7f4fca52017-02-23 15:15:51 +0800316 utils::writeData(ownerFile, owner);
Lei YU415b9642017-02-09 11:37:26 +0800317}
318
319std::string Manager::getSettings(const char* value) const
320{
Lei YUa7417132017-02-23 15:24:05 +0800321 return utils::getProperty<std::string>(
322 bus,
323 SETTINGS_SERVICE,
324 SETTINGS_PATH,
325 SETTINGS_INTERFACE,
326 value);
Lei YU415b9642017-02-09 11:37:26 +0800327}
328
329Mode Manager::convertToMode(const std::string& mode)
330{
331 if (mode == "NTP")
332 {
333 return Mode::NTP;
334 }
335 else if (mode == "MANUAL")
336 {
337 return Mode::MANUAL;
338 }
339 else
340 {
341 log<level::ERR>("Unrecognized mode",
342 entry("%s", mode.c_str()));
343 return Mode::NTP;
344 }
345}
346
347Owner Manager::convertToOwner(const std::string& owner)
348{
349 auto it = ownerMap.find(owner);
350 if (it == ownerMap.end())
351 {
352 log<level::ERR>("Unrecognized owner",
353 entry("%s", owner.c_str()));
354 return Owner::BMC;
355 }
356 return it->second;
357}
358
359}
360}