blob: 416ffc9ed2906c9b4023e23a57aa571dbf74ccd5 [file] [log] [blame]
Vishwanatha81ee91f2016-08-30 17:17:13 +05301#include <cstdlib>
2#include <fstream>
3#include <iostream>
4#include <memory>
5#include <mapper.h>
Patrick Williams6964ed12016-11-09 21:56:15 -06006#include <cassert>
Deepak Kodihalli41885672017-07-25 06:49:45 -05007#include <cctype>
8#include <algorithm>
9#include <phosphor-logging/log.hpp>
10#include <phosphor-logging/elog-errors.hpp>
11#include <xyz/openbmc_project/Common/error.hpp>
Vishwanatha81ee91f2016-08-30 17:17:13 +053012#include "time-manager.hpp"
13
Deepak Kodihalli41885672017-07-25 06:49:45 -050014using namespace phosphor::logging;
15using namespace sdbusplus::xyz::openbmc_project::Common::Error;
16
Vishwanatha81ee91f2016-08-30 17:17:13 +053017std::map<std::string, TimeConfig::FUNCTOR> TimeConfig::iv_TimeParams = {
Deepak Kodihalli41885672017-07-25 06:49:45 -050018 // TODO via openbmc/openbmc#668 - openbmc/openbmc#1770 is still work in
19 // progress at the time of writing this, so the use_dhcp_ntp is still using
20 // the old org.openbmc settings interfaces. The whole of time manager is
21 // anyway being rewritten to use new xyz.openbmc_project interfaces; as part
22 // of that switching to new setting interfaces is also covered.
Vishwanatha81ee91f2016-08-30 17:17:13 +053023 { "use_dhcp_ntp", std::make_tuple(&TimeConfig::getSystemSettings,
24 &TimeConfig::updateNetworkSettings)
25 }
26};
27
Deepak Kodihalli41885672017-07-25 06:49:45 -050028namespace internal
29{
30namespace setting
31{
32
33/** @brief Convert d-bus enum string to native string. For eg, convert
34 * "xyz.openbmc_project.Time.Owner.Split" to "SPLIT".
35 *
36 * @param[in] value - setting enum string
37 *
38 * @return converted string
39 */
40inline auto dbusToNative(std::string&& value)
41{
42 auto setting = std::move(value);
43 auto index = setting.find_last_of('.') + 1;
44 setting = setting.substr(index, setting.length() - index);
45 std::transform(setting.begin(), setting.end(), setting.begin(),
46 [](unsigned char c){ return std::toupper(c); });
47 return setting;
48}
49
50} // namespace setting
51} // namespace internal
52
Vishwanatha81ee91f2016-08-30 17:17:13 +053053TimeConfig::TimeConfig() :
Patrick Williams6a07ddb2016-11-09 21:43:20 -060054 iv_dbus(nullptr),
Vishwanatha Subbanna25b4ce92017-07-05 13:15:19 +053055 iv_CurrTimeMode(timeModes::MANUAL),
56 iv_RequestedTimeMode(timeModes::MANUAL),
57 iv_CurrTimeOwner(timeOwners::BOTH),
58 iv_RequestedTimeOwner(timeOwners::BOTH),
Vishwanatha81ee91f2016-08-30 17:17:13 +053059 iv_CurrDhcpNtp("yes"),
60 iv_SettingChangeAllowed(false),
Patrick Williams6a07ddb2016-11-09 21:43:20 -060061 iv_SplitModeChanged(false)
Vishwanatha81ee91f2016-08-30 17:17:13 +053062{
63 // Not really having anything to do here.
64}
65
66// Given a mode string, returns it's equivalent mode enum
67TimeConfig::timeModes TimeConfig::getTimeMode(const char* timeMode)
68{
69 // We are forcing the values to be in specific case and range
70 if (!strcmp(timeMode,"NTP"))
71 {
72 return timeModes::NTP;
73 }
74 else
75 {
76 return timeModes::MANUAL;
77 }
78}
79
80// Accepts a timeMode enum and returns it's string value
Patrick Williams6964ed12016-11-09 21:56:15 -060081const char* TimeConfig::modeStr(TimeConfig::timeModes timeMode)
Vishwanatha81ee91f2016-08-30 17:17:13 +053082{
83 switch(timeMode)
84 {
85 case timeModes::NTP:
86 {
87 return "NTP";
88 }
89 case timeModes::MANUAL:
90 {
91 return "MANUAL";
92 }
93 }
Patrick Williams6964ed12016-11-09 21:56:15 -060094
95 assert(false);
96 return nullptr;
Vishwanatha81ee91f2016-08-30 17:17:13 +053097}
98
99// Given a owner string, returns it's equivalent owner enum
100TimeConfig::timeOwners TimeConfig::getTimeOwner(const char* timeOwner)
101{
102 if (!strcmp(timeOwner,"BMC"))
103 {
104 return timeOwners::BMC;
105 }
106 else if (!strcmp(timeOwner,"HOST"))
107 {
108 return timeOwners::HOST;
109 }
110 else if (!strcmp(timeOwner,"SPLIT"))
111 {
112 return timeOwners::SPLIT;
113 }
114 else
115 {
116 return timeOwners::BOTH;
117 }
118}
119
120// Accepts a timeOwner enum and returns it's string value
Patrick Williams6964ed12016-11-09 21:56:15 -0600121const char* TimeConfig::ownerStr(timeOwners timeOwner)
Vishwanatha81ee91f2016-08-30 17:17:13 +0530122{
123 switch(timeOwner)
124 {
125 case timeOwners::BMC:
126 {
127 return "BMC";
128 }
129 case timeOwners::HOST:
130 {
131 return "HOST";
132 }
133 case timeOwners::SPLIT:
134 {
135 return "SPLIT";
136 }
137 case timeOwners::BOTH:
138 {
139 return "BOTH";
140 }
141 }
Patrick Williams6964ed12016-11-09 21:56:15 -0600142
143 assert(false);
144 return nullptr;
Vishwanatha81ee91f2016-08-30 17:17:13 +0530145}
146
147// Returns the busname that hosts objPath
148std::unique_ptr<char> TimeConfig::getProvider(const char* objPath)
149{
150 char *provider = nullptr;
151 mapper_get_service(iv_dbus, objPath, &provider);
152 return std::unique_ptr<char>(provider);
153}
154
155// Accepts a settings name and returns its value.
156// for the variant of type 'string' now.
157std::string TimeConfig::getSystemSettings(const char* key)
158{
159 constexpr auto settingsObj = "/org/openbmc/settings/host0";
160 constexpr auto propertyIntf = "org.freedesktop.DBus.Properties";
161 constexpr auto hostIntf = "org.openbmc.settings.Host";
162
163 const char* value = nullptr;
164 std::string settingsVal {};
165 sd_bus_message* reply = nullptr;
166
167 std::cout <<"Getting System Settings: " << key << std::endl;
168
169 // Get the provider from object mapper
170 auto settingsProvider = getProvider(settingsObj);
171 if (!settingsProvider)
172 {
173 std::cerr << "Error Getting service for Settings" << std::endl;
174 return value;
175 }
176
177 auto r = sd_bus_call_method(iv_dbus,
178 settingsProvider.get(),
179 settingsObj,
180 propertyIntf,
181 "Get",
182 nullptr,
183 &reply,
184 "ss",
185 hostIntf,
186 key);
187 if (r < 0)
188 {
189 std::cerr <<"Error" << strerror(-r)
190 <<" reading system settings" << std::endl;
191 goto finish;
192 }
193
194 r = sd_bus_message_read(reply, "v", "s", &value);
195 if (r < 0)
196 {
197 std::cerr <<"Error " << strerror(-r)
198 <<" parsing settings data" << std::endl;
199 }
200finish:
201 if (value)
202 {
203 settingsVal.assign(value);
204 }
205 reply = sd_bus_message_unref(reply);
206 return settingsVal;
207}
208
209// Reads value from /org/openbmc/control/power0
210// This signature on purpose to plug into time parameter map
211std::string TimeConfig::getPowerSetting(const char* key)
212{
213 constexpr auto powerObj = "/org/openbmc/control/power0";
214 constexpr auto powerIntf = "org.openbmc.control.Power";
215 constexpr auto propertyIntf = "org.freedesktop.DBus.Properties";
216
217 int value = -1;
218 std::string powerValue {};
219 sd_bus_message* reply = nullptr;
220
221 std::cout <<"Reading Power Control key: " << key << std::endl;
222
223 // Get the provider from object mapper
224 auto powerProvider = getProvider(powerObj);
225 if (!powerProvider)
226 {
227 std::cerr <<" Error getting provider for Power Settings" << std::endl;
228 return powerValue;
229 }
230
231 auto r = sd_bus_call_method(iv_dbus,
232 powerProvider.get(),
233 powerObj,
234 propertyIntf,
235 "Get",
236 nullptr,
237 &reply,
238 "ss",
239 powerIntf,
240 key);
241 if (r < 0)
242 {
243 std::cerr <<"Error " << strerror(-r)
244 << "reading: " << key << std::endl;
245 goto finish;
246 }
247
248 r = sd_bus_message_read(reply, "v", "i", &value);
249 if (r < 0)
250 {
251 std::cerr <<"Error " << strerror(-r)
252 <<" parsing " << key << "value" << std::endl;
253 // For maintenance
254 goto finish;
255 }
256finish:
257 if (value != -1)
258 {
259 powerValue = std::to_string(value);
260 }
261 reply = sd_bus_message_unref(reply);
262 return powerValue;
263}
264
265// Updates .network file with UseNtp=
266int TimeConfig::updateNetworkSettings(const std::string& useDhcpNtp)
267{
268 constexpr auto networkObj = "/org/openbmc/NetworkManager/Interface";
269 constexpr auto networkIntf = "org.openbmc.NetworkManager";
270
271 std::cout << "use_dhcp_ntp = " << useDhcpNtp.c_str() << std::endl;
272
273 // If what we have already is what it is, then just return.
274 if (iv_CurrDhcpNtp == useDhcpNtp)
275 {
276 return 0;
277 }
278
279 // Get the provider from object mapper
280 auto networkProvider = getProvider(networkObj);
281 if (!networkProvider)
282 {
283 return -1;
284 }
285
286 auto r = sd_bus_call_method(iv_dbus,
287 networkProvider.get(),
288 networkObj,
289 networkIntf,
290 "UpdateUseNtpField",
291 nullptr,
292 nullptr,
293 "s",
294 useDhcpNtp.c_str());
295 if (r < 0)
296 {
297 std::cerr <<"Error " << strerror(-r)
298 << " updating UseNtp" << std::endl;
299 }
300 else
301 {
302 std::cout <<"Successfully updated UseNtp=["
303 << useDhcpNtp << "]" << std::endl;
304
Patrick Williamsf0c91c02016-11-09 21:35:04 -0600305 r = writeData(cv_DhcpNtpFile, useDhcpNtp);
Vishwanatha81ee91f2016-08-30 17:17:13 +0530306 }
307
308 return 0;
309}
310
311// Reads the values from 'settingsd' and applies:
312// 1) Time Mode
313// 2) time Owner
314// 3) UseNTP setting
315// 4) Pgood
316int TimeConfig::processInitialSettings(sd_bus* dbus)
317{
318 // First call from TimeManager to config manager
319 iv_dbus = dbus;
320
Deepak Kodihalli41885672017-07-25 06:49:45 -0500321 auto timeOwnerFunctor = std::make_tuple(&TimeConfig::getTimeOwnerSetting,
322 &TimeConfig::updateTimeOwner);
323 iv_TimeParams.emplace(settings.timeOwner, std::move(timeOwnerFunctor));
324 auto timeSyncFunctor = std::make_tuple(
325 &TimeConfig::getTimeSyncMethodSetting,
326 &TimeConfig::updateTimeMode);
327 iv_TimeParams.emplace(settings.timeSyncMethod, std::move(timeSyncFunctor));
328
329 using namespace sdbusplus::bus::match::rules;
330 sdbusplus::bus::bus bus(iv_dbus);
331
332 settingsMatches.emplace_back(
333 bus,
334 propertiesChanged(settings.timeOwner, settings::timeOwnerIntf),
335 std::bind(std::mem_fn(&TimeConfig::settingsChanged),
336 this, std::placeholders::_1));
337
338 settingsMatches.emplace_back(
339 bus,
340 propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
341 std::bind(std::mem_fn(&TimeConfig::settingsChanged),
342 this, std::placeholders::_1));
343
Vishwanatha81ee91f2016-08-30 17:17:13 +0530344 // Read saved info like Who was the owner , what was the mode,
345 // what was the use_dhcp_ntp setting before etc..
346 auto r = readPersistentData();
347 if (r < 0)
348 {
349 std::cerr << "Error reading the data saved in flash."
350 << std::endl;
351 return r;
352 }
353
354 // Now read whats in settings and apply if allowed.
355 for (auto& iter : iv_TimeParams)
356 {
357 // Get the settings value for various keys.
358 auto reader = std::get<READER>(iter.second);
359 auto value = (this->*reader)(iter.first.c_str());
360 if (!value.empty())
361 {
362 // Get the value for the key and validate.
363 auto updater = std::get<UPDATER>(iter.second);
364 auto r = (this->*updater)(value);
365 if (r < 0)
366 {
367 std::cerr << "Error setting up initial keys" << std::endl;
368 return r;
369 }
370 }
371 else
372 {
373 std::cerr << "key " << iter.first
374 <<" has no value: " << std::endl;
375 return -1;
376 }
377 }
378
379 // Now that we have taken care of consuming, push this as well
380 // so that we can use the same map for handling pgood change too.
381 auto readerUpdater = std::make_tuple(&TimeConfig::getPowerSetting,
382 &TimeConfig::processPgoodChange);
383 iv_TimeParams.emplace("pgood", readerUpdater);
384
385 return 0;
386}
387
388// This is called by Property Change handler on the event of
389// receiving notification on property value change.
390int TimeConfig::updatePropertyVal(const char* key, const std::string& value)
391{
392 auto iter = iv_TimeParams.find(key);
393 if (iter != iv_TimeParams.end())
394 {
395 auto updater = std::get<UPDATER>(iter->second);
396 return (this->*updater)(value);
397 }
398 // Coming here indicates that we never had a matching key.
399 return -1;
400}
401
402// Called by sd_event when Properties are changed in Control/power0
403// Interested in change to 'pgood'
404int TimeConfig::processPgoodChange(const std::string& newPgood)
405{
406 // Indicating that we are safe to apply any changes
407 if (!newPgood.compare("0"))
408 {
409 iv_SettingChangeAllowed = true;
410 std::cout <<"Changing time settings allowed now" << std::endl;
411 }
412 else
413 {
414 iv_SettingChangeAllowed = false;
415 std::cout <<"Changing time settings is *deferred* now" << std::endl;
416 }
417
418 // if we have had users that changed the time settings
419 // when we were not ready yet, do it now.
420 if (iv_RequestedTimeOwner != iv_CurrTimeOwner)
421 {
422 auto r = updateTimeOwner(ownerStr(iv_RequestedTimeOwner));
423 if (r < 0)
424 {
425 std::cerr << "Error updating new time owner" << std::endl;
426 return r;
427 }
428 std::cout << "New Owner is : "
429 << ownerStr(iv_RequestedTimeOwner) << std::endl;
430 }
431
432 if (iv_RequestedTimeMode != iv_CurrTimeMode)
433 {
434 auto r = updateTimeMode(modeStr(iv_RequestedTimeMode));
435 if (r < 0)
436 {
437 std::cerr << "Error updating new time mode" << std::endl;
438 return r;
439 }
440 std::cout <<"New Mode is : "
441 << modeStr(iv_RequestedTimeMode) << std::endl;
442 }
443 return 0;
444}
445
446// Manipulates time owner if the system setting allows it
447int TimeConfig::updateTimeMode(const std::string& newModeStr)
448{
449 auto r = 0;
450 iv_RequestedTimeMode = getTimeMode(newModeStr.c_str());
451
452 std::cout <<"Requested_Mode: " << newModeStr
453 << " Current_Mode: " << modeStr(iv_CurrTimeMode)
454 << std::endl;
455
456 if (iv_RequestedTimeMode == iv_CurrTimeMode)
457 {
458 std::cout << "Mode is already set to : "
459 << newModeStr << std::endl;
460 return 0;
461 }
462
463 // Also, if the time owner is HOST, then we should not allow NTP.
464 // However, it may so happen that there are 2 pending requests, one for
465 // changing to NTP and other for changing owner to something not HOST.
466 // So check if there is a pending timeOwner change and if so, allow NTP
467 // if the current is HOST and requested is non HOST.
468 if (iv_CurrTimeOwner == timeOwners::HOST &&
469 iv_RequestedTimeOwner == timeOwners::HOST &&
470 iv_RequestedTimeMode == timeModes::NTP)
471 {
472 std::cout <<"Can not set mode to NTP with HOST as owner"
473 << std::endl;
474 return 0;
475 }
476
477 if (iv_SettingChangeAllowed)
478 {
479 r = modifyNtpSettings(iv_RequestedTimeMode);
480 if (r < 0)
481 {
482 std::cerr << "Error changing TimeMode settings"
483 << std::endl;
484 }
485 else
486 {
487 iv_CurrTimeMode = iv_RequestedTimeMode;
488 }
489 std::cout << "Current_Mode changed to: "
490 << newModeStr << " :: " << modeStr(iv_CurrTimeMode) << std::endl;
491
492 // Need this when we either restart or come back from reset
493 r = writeData(cv_TimeModeFile, modeStr(iv_CurrTimeMode));
494 }
495 else
496 {
497 std::cout <<"Deferring update until system state allows it"
498 << std::endl;
499 }
500 return r;
501}
502
503// Manipulates time owner if the system setting allows it
504int TimeConfig::updateTimeOwner(const std::string& newOwnerStr)
505{
506 int r = 0;
507 iv_RequestedTimeOwner = getTimeOwner(newOwnerStr.c_str());
508
509 // Needed when owner changes to HOST
510 std::string manualMode = "Manual";
511
512 // Needed by time manager to do some house keeping
513 iv_SplitModeChanged = false;
514
515 if (iv_RequestedTimeOwner == iv_CurrTimeOwner)
516 {
517 std::cout <<"Owner is already set to : "
518 << newOwnerStr << std::endl;
519 return 0;
520 }
521
522 std::cout <<"Requested_Owner: " << newOwnerStr
523 << " Current_Owner: " << ownerStr(iv_CurrTimeOwner)
524 << std::endl;
525
526 if (iv_SettingChangeAllowed)
527 {
528 // If we are transitioning from SPLIT to something else,
529 // reset the host offset.
530 if (iv_CurrTimeOwner == timeOwners::SPLIT &&
531 iv_RequestedTimeOwner != timeOwners::SPLIT)
532 {
533 // Needed by time manager to do some house keeping
534 iv_SplitModeChanged = true;
535 }
536 iv_CurrTimeOwner = iv_RequestedTimeOwner;
537 std::cout << "Current_Owner is now: "
538 << newOwnerStr << std::endl;
539
540 // HOST and NTP are exclusive
541 if (iv_CurrTimeOwner == timeOwners::HOST)
542 {
543 std::cout <<"Forcing the mode to MANUAL" << std::endl;
544 r = updateTimeMode(manualMode);
545 if (r < 0)
546 {
547 std::cerr << "Error forcing the mode to MANUAL" << std::endl;
548 return r;
549 }
550 }
551 // Need this when we either restart or come back from reset
552 r = writeData(cv_TimeOwnerFile, ownerStr(iv_CurrTimeOwner));
553 }
554 else
555 {
556 std::cout <<"Deferring update until system state allows it"
557 << std::endl;
558 }
559
560 return r;
561}
562
563// Accepts the time mode and makes necessary changes to timedate1
564int TimeConfig::modifyNtpSettings(const timeModes& newTimeMode)
565{
566 auto ntpChangeOp = 0;
567
568 // Pass '1' -or- '0' to SetNTP method indicating Enable/Disable
569 ntpChangeOp = (newTimeMode == timeModes::NTP) ? 1 : 0;
570
571 std::cout <<"Applying NTP setting..." << std::endl;
572
573 auto r = sd_bus_call_method(iv_dbus,
574 "org.freedesktop.timedate1",
575 "/org/freedesktop/timedate1",
576 "org.freedesktop.timedate1",
577 "SetNTP",
578 nullptr,
579 nullptr, // timedate1 does not return response
580 "bb",
581 ntpChangeOp, // '1' means Enable
582 0); // '0' meaning no policy-kit
583 if (r < 0)
584 {
585 std::cerr <<"Error: " << strerror(-r)
586 << "changing time Mode" << std::endl;
587 }
588 else
589 {
590 std::cout << "SUCCESS. NTP setting is now: " <<
Patrick Williamsef52f032016-11-09 21:44:43 -0600591 ((ntpChangeOp) ? "Enabled" : "Disabled");
Vishwanatha81ee91f2016-08-30 17:17:13 +0530592
593 // TODO : https://github.com/openbmc/phosphor-time-manager/issues/1
594 if (ntpChangeOp)
595 {
Patrick Williamsd5ba0082016-11-09 21:36:21 -0600596 r = system("systemctl restart systemd-timesyncd &");
Vishwanatha81ee91f2016-08-30 17:17:13 +0530597 }
598 else
599 {
Patrick Williamsd5ba0082016-11-09 21:36:21 -0600600 r = system("systemctl stop systemd-timesyncd &");
Vishwanatha81ee91f2016-08-30 17:17:13 +0530601 }
602 }
603 return r;
604}
605
606// Reads all the saved data from the last run
607int TimeConfig::readPersistentData()
608{
609 // If we are coming back from a reset reload, then need to
610 // read what was the last successful Mode and Owner.
611 auto savedTimeMode = readData<std::string>(cv_TimeModeFile);
612 if (!savedTimeMode.empty())
613 {
614 iv_CurrTimeMode = getTimeMode(savedTimeMode.c_str());
615 std::cout <<"Last known time_mode: "
616 << savedTimeMode.c_str() << std::endl;
617 }
618
619 auto savedTimeOwner = readData<std::string>(cv_TimeOwnerFile);
620 if (!savedTimeOwner.empty())
621 {
622 iv_CurrTimeOwner = getTimeOwner(savedTimeOwner.c_str());
623 std::cout <<"Last known time_owner: "
624 << savedTimeOwner.c_str() << std::endl;
625 }
626
627 auto savedDhcpNtp = readData<std::string>(cv_DhcpNtpFile);
628 if (!savedDhcpNtp.empty())
629 {
630 iv_CurrDhcpNtp = savedDhcpNtp;
631 std::cout <<"Last known use_dhcp_ntp: "
632 << iv_CurrDhcpNtp.c_str() << std::endl;
633 }
634 else
635 {
636 // This seems to be the first time.
637 std::cerr <<"Empty DhcpNtp string" << std::endl;
638 iv_CurrDhcpNtp = "yes";
639 }
640
641 // Doing this here to make sure 'pgood' is read and handled
642 // first before anything.
643 auto pgood = getPowerSetting("pgood");
644 if (!pgood.compare("0"))
645 {
646 std::cout << "Changing settings *allowed* now" << std::endl;
647 iv_SettingChangeAllowed = true;
648 }
649 return 0;
650}
Deepak Kodihalli41885672017-07-25 06:49:45 -0500651
652std::string TimeConfig::getTimeOwnerSetting(const char* path)
653{
654 sdbusplus::bus::bus bus{iv_dbus};
655 auto method = bus.new_method_call(
656 settings.service(settings.timeOwner,
657 settings::timeOwnerIntf).c_str(),
658 path,
659 "org.freedesktop.DBus.Properties",
660 "Get");
661 method.append(settings::timeOwnerIntf, "TimeOwner");
662 auto reply = bus.call(method);
663 if (reply.is_method_error())
664 {
665 log<level::ERR>("Error in TimeOwner Get");
666 elog<InternalFailure>();
667 }
668
669 sdbusplus::message::variant<std::string> result;
670 reply.read(result);
671 // TODO via openbmc/openbmc#668 - because the old org.openbmc settings
672 // interfaces defined the time settings as strings, the code in this file
673 // is based around that fact. We use enums in the new settings interfaces,
674 // so code in this file can be changed to work with enums instead. That's
675 // being covered by the time manager rework (#668). For now, converting the
676 // settings to the string format that this object expects it to be.
677 // For eg, convert "xyz.openbmc_project.Time.Owner.Split" to "SPLIT".
678 auto setting = result.get<std::string>();
679 return internal::setting::dbusToNative(std::move(setting));
680}
681
682std::string TimeConfig::getTimeSyncMethodSetting(const char* path)
683{
684 sdbusplus::bus::bus bus{iv_dbus};
685 auto method = bus.new_method_call(
686 settings.service(settings.timeSyncMethod,
687 settings::timeSyncIntf).c_str(),
688 path,
689 "org.freedesktop.DBus.Properties",
690 "Get");
691 method.append(settings::timeSyncIntf, "TimeSyncMethod");
692 auto reply = bus.call(method);
693 if (reply.is_method_error())
694 {
695 log<level::ERR>("Error in TimeSyncMethod Get");
696 elog<InternalFailure>();
697 }
698
699 sdbusplus::message::variant<std::string> result;
700 reply.read(result);
701 auto setting = result.get<std::string>();
702 return internal::setting::dbusToNative(std::move(setting));
703}
704
705int TimeConfig::settingsChanged(sdbusplus::message::message& msg)
706{
707 using Interface = std::string;
708 using Property = std::string;
709 using Value = std::string;
710 using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
711
712 Interface interface;
713 Properties properties;
714
715 msg.read(interface, properties);
716
717 auto path = msg.get_path();
718 for(const auto& p : properties)
719 {
720 auto setting = p.second.get<std::string>();
721 updatePropertyVal(path,
722 internal::setting::dbusToNative(std::move(setting)));
723 }
724
725 return 0;
726}