blob: 15f1cec587b21b61dfcccccd106f16672f0afafd [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 YUc6fe8692017-02-23 15:12:07 +080013const auto MATCH_PGOOD_CHANGE =
14 rules::type::signal() +
15 rules::member("PropertiesChanged") +
16 rules::path("/org/openbmc/control/power0") +
17 rules::interface("org.freedesktop.DBus.Properties");
18
Lei YUc6fe8692017-02-23 15:12:07 +080019constexpr auto POWER_PATH = "/org/openbmc/control/power0";
Lei YUdd8e9e42017-04-19 17:46:58 +080020constexpr auto POWER_INTERFACE = "org.openbmc.control.Power";
Lei YUc6fe8692017-02-23 15:12:07 +080021constexpr auto PGOOD_STR = "pgood";
Lei YUa7417132017-02-23 15:24:05 +080022
23constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
24constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
Lei YUdd8e9e42017-04-19 17:46:58 +080025constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
Lei YUa7417132017-02-23 15:24:05 +080026constexpr auto METHOD_SET_NTP = "SetNTP";
Lei YU415b9642017-02-09 11:37:26 +080027}
28
29namespace phosphor
30{
31namespace time
32{
33
34using namespace phosphor::logging;
35
36const std::set<std::string>
37Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
38
Lei YU415b9642017-02-09 11:37:26 +080039Manager::Manager(sdbusplus::bus::bus& bus)
40 : bus(bus),
Lei YUc6fe8692017-02-23 15:12:07 +080041 pgoodChangeMatch(bus, MATCH_PGOOD_CHANGE, onPgoodChanged, this)
Lei YU415b9642017-02-09 11:37:26 +080042{
Lei YU710d49b2017-08-01 17:10:17 +080043 using namespace sdbusplus::bus::match::rules;
44 settingsMatches.emplace_back(
45 bus,
46 propertiesChanged(settings.timeOwner, settings::timeOwnerIntf),
47 std::bind(std::mem_fn(&Manager::onSettingsChanged),
48 this, std::placeholders::_1));
49 settingsMatches.emplace_back(
50 bus,
51 propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
52 std::bind(std::mem_fn(&Manager::onSettingsChanged),
53 this, std::placeholders::_1));
54
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
Lei YU710d49b2017-08-01 17:10:17 +080061 auto mode = getSetting(settings.timeSyncMethod.c_str(),
62 settings::timeSyncIntf,
63 PROPERTY_TIME_MODE);
64 auto owner = getSetting(settings.timeOwner.c_str(),
65 settings::timeOwnerIntf,
66 PROPERTY_TIME_OWNER);
67
68 onPropertyChanged(PROPERTY_TIME_MODE, mode);
69 onPropertyChanged(PROPERTY_TIME_OWNER, owner);
Lei YU415b9642017-02-09 11:37:26 +080070}
71
72void Manager::addListener(PropertyChangeListner* listener)
73{
74 // Notify listener about the initial value
75 listener->onModeChanged(timeMode);
76 listener->onOwnerChanged(timeOwner);
77
78 listeners.insert(listener);
79}
80
Lei YU7f4fca52017-02-23 15:15:51 +080081void Manager::restoreSettings()
82{
83 auto mode = utils::readData<std::string>(modeFile);
84 if (!mode.empty())
85 {
Lei YUddd54422017-04-18 16:38:44 +080086 timeMode = utils::strToMode(mode);
Lei YU7f4fca52017-02-23 15:15:51 +080087 }
88 auto owner = utils::readData<std::string>(ownerFile);
89 if (!owner.empty())
90 {
Lei YUddd54422017-04-18 16:38:44 +080091 timeOwner = utils::strToOwner(owner);
Lei YU7f4fca52017-02-23 15:15:51 +080092 }
93}
94
Lei YUc6fe8692017-02-23 15:12:07 +080095void Manager::checkHostOn()
96{
Lei YUdd8e9e42017-04-19 17:46:58 +080097 std::string powerService = utils::getService(bus,
98 POWER_PATH,
99 POWER_INTERFACE);
Lei YUdd8e9e42017-04-19 17:46:58 +0800100
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 YU415b9642017-02-09 11:37:26 +0800109void Manager::onPropertyChanged(const std::string& key,
110 const std::string& value)
111{
Lei YU7f4fca52017-02-23 15:15:51 +0800112 if (hostOn)
Lei YU415b9642017-02-09 11:37:26 +0800113 {
Lei YU7f4fca52017-02-23 15:15:51 +0800114 // If host is on, set the values as requested time mode/owner.
115 // And when host becomes off, notify the listners.
116 setPropertyAsRequested(key, value);
Lei YU415b9642017-02-09 11:37:26 +0800117 }
Lei YU7f4fca52017-02-23 15:15:51 +0800118 else
Lei YU415b9642017-02-09 11:37:26 +0800119 {
Lei YU7f4fca52017-02-23 15:15:51 +0800120 // If host is off, notify listners
121 if (key == PROPERTY_TIME_MODE)
Lei YU415b9642017-02-09 11:37:26 +0800122 {
Lei YU7f4fca52017-02-23 15:15:51 +0800123 setCurrentTimeMode(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800124 onTimeModeChanged(value);
Lei YU7f4fca52017-02-23 15:15:51 +0800125 }
126 else if (key == PROPERTY_TIME_OWNER)
127 {
128 setCurrentTimeOwner(value);
Lei YUa5003ce2017-02-24 15:35:25 +0800129 onTimeOwnerChanged();
Lei YU415b9642017-02-09 11:37:26 +0800130 }
131 }
132}
133
Lei YU710d49b2017-08-01 17:10:17 +0800134int Manager::onSettingsChanged(sdbusplus::message::message& msg)
135{
136 using Interface = std::string;
137 using Property = std::string;
138 using Value = std::string;
139 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
140
141 Interface interface;
142 Properties properties;
143
144 msg.read(interface, properties);
145
146 for(const auto& p : properties)
147 {
148 onPropertyChanged(p.first, p.second.get<std::string>());
149 }
150
151 return 0;
152}
153
Lei YU7f4fca52017-02-23 15:15:51 +0800154void Manager::setPropertyAsRequested(const std::string& key,
155 const std::string& value)
156{
157 if (key == PROPERTY_TIME_MODE)
158 {
159 setRequestedMode(value);
160 }
161 else if (key == PROPERTY_TIME_OWNER)
162 {
163 setRequestedOwner(value);
164 }
165 else
166 {
167 // The key shall be already the supported one
Lei YU86d80412017-07-12 13:12:12 +0800168 using InvalidArgumentError =
169 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
170 using namespace xyz::openbmc_project::Common;
171 elog<InvalidArgumentError>(
172 InvalidArgument::ARGUMENT_NAME(key.c_str()),
173 InvalidArgument::ARGUMENT_VALUE(value.c_str()));
Lei YU7f4fca52017-02-23 15:15:51 +0800174 }
175}
176
177void Manager::setRequestedMode(const std::string& mode)
178{
179 requestedMode = mode;
180}
181
182void Manager::setRequestedOwner(const std::string& owner)
183{
184 requestedOwner = owner;
185}
186
Lei YUa7417132017-02-23 15:24:05 +0800187void Manager::updateNtpSetting(const std::string& value)
188{
Lei YU710d49b2017-08-01 17:10:17 +0800189 bool isNtp =
190 (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
Lei YUa7417132017-02-23 15:24:05 +0800191 auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE,
192 SYSTEMD_TIME_PATH,
193 SYSTEMD_TIME_INTERFACE,
194 METHOD_SET_NTP);
195 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
196 // 'false' meaning no policy-kit
197
198 if (bus.call(method))
199 {
200 log<level::INFO>("Updated NTP setting",
201 entry("ENABLED:%d", isNtp));
202 }
203 else
204 {
205 log<level::ERR>("Failed to update NTP setting");
206 }
207}
208
Lei YUc6fe8692017-02-23 15:12:07 +0800209void Manager::onPgoodChanged(bool pgood)
210{
211 hostOn = pgood;
Lei YU7f4fca52017-02-23 15:15:51 +0800212 if (hostOn)
213 {
214 return;
215 }
216 if (!requestedMode.empty())
217 {
Lei YUa5003ce2017-02-24 15:35:25 +0800218 if (setCurrentTimeMode(requestedMode))
Lei YU7f4fca52017-02-23 15:15:51 +0800219 {
Lei YUa5003ce2017-02-24 15:35:25 +0800220 onTimeModeChanged(requestedMode);
Lei YU7f4fca52017-02-23 15:15:51 +0800221 }
222 setRequestedMode({}); // Clear requested mode
223 }
224 if (!requestedOwner.empty())
225 {
Lei YUa5003ce2017-02-24 15:35:25 +0800226 if (setCurrentTimeOwner(requestedOwner))
Lei YU7f4fca52017-02-23 15:15:51 +0800227 {
Lei YUa5003ce2017-02-24 15:35:25 +0800228 onTimeOwnerChanged();
Lei YU7f4fca52017-02-23 15:15:51 +0800229 }
230 setRequestedOwner({}); // Clear requested owner
231 }
Lei YUc6fe8692017-02-23 15:12:07 +0800232}
233
234int Manager::onPgoodChanged(sd_bus_message* msg,
235 void* userData,
236 sd_bus_error* retError)
237{
238 using properties = std::map < std::string,
239 sdbusplus::message::variant<int> >;
240 auto m = sdbusplus::message::message(msg);
241 // message type: sa{sv}as
242 std::string ignore;
243 properties props;
244 m.read(ignore, props);
245 for (const auto& item : props)
246 {
247 if (item.first == PGOOD_STR)
248 {
249 static_cast<Manager*>(userData)
250 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
251 }
252 }
253 return 0;
254}
Lei YU415b9642017-02-09 11:37:26 +0800255
Lei YUa5003ce2017-02-24 15:35:25 +0800256bool Manager::setCurrentTimeMode(const std::string& mode)
Lei YU415b9642017-02-09 11:37:26 +0800257{
Lei YUddd54422017-04-18 16:38:44 +0800258 auto newMode = utils::strToMode(mode);
Lei YUa5003ce2017-02-24 15:35:25 +0800259 if (newMode != timeMode)
260 {
261 log<level::INFO>("Time mode is changed",
262 entry("MODE=%s", mode.c_str()));
263 timeMode = newMode;
264 utils::writeData(modeFile, mode);
265 return true;
266 }
267 else
268 {
269 return false;
270 }
Lei YU415b9642017-02-09 11:37:26 +0800271}
272
Lei YUa5003ce2017-02-24 15:35:25 +0800273bool Manager::setCurrentTimeOwner(const std::string& owner)
Lei YU415b9642017-02-09 11:37:26 +0800274{
Lei YUddd54422017-04-18 16:38:44 +0800275 auto newOwner = utils::strToOwner(owner);
Lei YUa5003ce2017-02-24 15:35:25 +0800276 if (newOwner != timeOwner)
277 {
278 log<level::INFO>("Time owner is changed",
279 entry("OWNER=%s", owner.c_str()));
280 timeOwner = newOwner;
281 utils::writeData(ownerFile, owner);
282 return true;
283 }
284 else
285 {
286 return false;
287 }
288}
289
290void Manager::onTimeModeChanged(const std::string& mode)
291{
292 for (const auto listener : listeners)
293 {
294 listener->onModeChanged(timeMode);
295 }
296 // When time_mode is updated, update the NTP setting
297 updateNtpSetting(mode);
298}
299
300void Manager::onTimeOwnerChanged()
301{
302 for (const auto& listener : listeners)
303 {
304 listener->onOwnerChanged(timeOwner);
305 }
Lei YU415b9642017-02-09 11:37:26 +0800306}
307
Lei YU710d49b2017-08-01 17:10:17 +0800308std::string Manager::getSetting(const char* path,
309 const char* interface,
310 const char* setting) const
311{
312 std::string settingManager = utils::getService(bus, path, interface);
313 return utils::getProperty<std::string>(bus,
314 settingManager.c_str(),
315 path,
316 interface,
317 setting);
318}
319
Lei YU415b9642017-02-09 11:37:26 +0800320}
321}