1 #include "manager.hpp"
2 
3 #include "utils.hpp"
4 
5 #include <assert.h>
6 
7 #include <phosphor-logging/elog-errors.hpp>
8 #include <phosphor-logging/elog.hpp>
9 #include <phosphor-logging/log.hpp>
10 #include <xyz/openbmc_project/Common/error.hpp>
11 
12 namespace rules = sdbusplus::bus::match::rules;
13 
14 namespace // anonymous
15 {
16 
17 constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
18 constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
19 constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
20 constexpr auto METHOD_SET_NTP = "SetNTP";
21 } // namespace
22 
23 namespace phosphor
24 {
25 namespace time
26 {
27 
28 using namespace phosphor::logging;
29 
30 Manager::Manager(sdbusplus::bus::bus& bus) : bus(bus), settings(bus)
31 {
32     using namespace sdbusplus::bus::match::rules;
33     settingsMatches.emplace_back(
34         bus, propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
35         std::bind(std::mem_fn(&Manager::onSettingsChanged), this,
36                   std::placeholders::_1));
37 
38     // Check the settings daemon to process the new settings
39     auto mode = getSetting(settings.timeSyncMethod.c_str(),
40                            settings::timeSyncIntf, PROPERTY_TIME_MODE);
41 
42     onPropertyChanged(PROPERTY_TIME_MODE, mode);
43 }
44 
45 void Manager::onPropertyChanged(const std::string& key,
46                                 const std::string& value)
47 {
48     assert(key == PROPERTY_TIME_MODE);
49 
50     // Notify listeners
51     setCurrentTimeMode(value);
52     onTimeModeChanged(value);
53 }
54 
55 int Manager::onSettingsChanged(sdbusplus::message::message& msg)
56 {
57     using Interface = std::string;
58     using Property = std::string;
59     using Value = std::string;
60     using Properties = std::map<Property, std::variant<Value>>;
61 
62     Interface interface;
63     Properties properties;
64 
65     msg.read(interface, properties);
66 
67     for (const auto& p : properties)
68     {
69         onPropertyChanged(p.first, std::get<std::string>(p.second));
70     }
71 
72     return 0;
73 }
74 
75 void Manager::updateNtpSetting(const std::string& value)
76 {
77     bool isNtp =
78         (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
79     auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE, SYSTEMD_TIME_PATH,
80                                       SYSTEMD_TIME_INTERFACE, METHOD_SET_NTP);
81     method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
82                                  // 'false' meaning no policy-kit
83 
84     try
85     {
86         bus.call_noreply(method);
87         log<level::INFO>("Updated NTP setting", entry("ENABLED=%d", isNtp));
88     }
89     catch (const sdbusplus::exception::SdBusError& ex)
90     {
91         log<level::ERR>("Failed to update NTP setting",
92                         entry("ERR=%s", ex.what()));
93     }
94 }
95 
96 bool Manager::setCurrentTimeMode(const std::string& mode)
97 {
98     auto newMode = utils::strToMode(mode);
99     if (newMode != timeMode)
100     {
101         log<level::INFO>("Time mode is changed",
102                          entry("MODE=%s", mode.c_str()));
103         timeMode = newMode;
104         return true;
105     }
106     else
107     {
108         return false;
109     }
110 }
111 
112 void Manager::onTimeModeChanged(const std::string& mode)
113 {
114     // When time_mode is updated, update the NTP setting
115     updateNtpSetting(mode);
116 }
117 
118 std::string Manager::getSetting(const char* path, const char* interface,
119                                 const char* setting) const
120 {
121     std::string settingManager = utils::getService(bus, path, interface);
122     return utils::getProperty<std::string>(bus, settingManager.c_str(), path,
123                                            interface, setting);
124 }
125 
126 } // namespace time
127 } // namespace phosphor
128