xref: /openbmc/phosphor-time-manager/manager.cpp (revision c0e77cf805dbc85608b92ec593513f111619e5b8)
1  #include "manager.hpp"
2  
3  #include "utils.hpp"
4  
5  #include <phosphor-logging/lg2.hpp>
6  
7  #include <cassert>
8  
9  namespace rules = sdbusplus::bus::match::rules;
10  
11  namespace // anonymous
12  {
13  
14  constexpr auto systemdTimeService = "org.freedesktop.timedate1";
15  constexpr auto systemdTimePath = "/org/freedesktop/timedate1";
16  constexpr auto systemdTimeInterface = "org.freedesktop.timedate1";
17  constexpr auto methodSetNtp = "SetNTP";
18  constexpr auto propertyNtp = "NTP";
19  } // namespace
20  
21  namespace phosphor
22  {
23  namespace time
24  {
25  
26  PHOSPHOR_LOG2_USING;
27  
Manager(sdbusplus::bus_t & bus)28  Manager::Manager(sdbusplus::bus_t& bus) : bus(bus), settings(bus)
29  {
30      using namespace sdbusplus::bus::match::rules;
31      timedateMatches.emplace_back(
32          bus, propertiesChanged(systemdTimePath, systemdTimeInterface),
33          [&](sdbusplus::message_t& m) { onTimedateChanged(m); });
34      settingsMatches.emplace_back(
35          bus, propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
36          [&](sdbusplus::message_t& m) { onSettingsChanged(m); });
37  
38      // Check the settings daemon to process the new settings
39      auto mode = getSetting(settings.timeSyncMethod.c_str(),
40                             settings::timeSyncIntf, propertyTimeMode);
41  
42      onPropertyChanged(propertyTimeMode, mode, true);
43  }
44  
onPropertyChanged(const std::string & key,const std::string & value,bool forceSet)45  void Manager::onPropertyChanged(const std::string& key,
46                                  const std::string& value, bool forceSet)
47  {
48      assert(key == propertyTimeMode);
49  
50      bool newNtpMode = (settings::ntpSync == value);
51      bool oldNtpMode = (Mode::NTP == getTimeMode());
52      if (forceSet || (newNtpMode != oldNtpMode))
53      {
54          // Notify listeners
55          onTimeModeChanged(value);
56          setCurrentTimeMode(value);
57          debug("NTP property changed in phosphor-settings, update to systemd"
58                " time service.");
59      }
60      else
61      {
62          debug("NTP mode is already the same, skip setting to systemd time"
63                " service again.");
64      }
65  }
66  
onSettingsChanged(sdbusplus::message_t & msg)67  int Manager::onSettingsChanged(sdbusplus::message_t& msg)
68  {
69      using Interface = std::string;
70      using Property = std::string;
71      using Value = std::string;
72      using Properties = std::map<Property, std::variant<Value>>;
73  
74      Interface interface;
75      Properties properties;
76  
77      msg.read(interface, properties);
78  
79      for (const auto& p : properties)
80      {
81          onPropertyChanged(p.first, std::get<std::string>(p.second));
82      }
83  
84      return 0;
85  }
86  
onTimedateChanged(sdbusplus::message_t & msg)87  int Manager::onTimedateChanged(sdbusplus::message_t& msg)
88  {
89      using Properties = std::map<std::string, std::variant<std::string, bool>>;
90  
91      std::string interface;
92      Properties properties;
93  
94      msg.read(interface, properties);
95  
96      auto iter = properties.find(propertyNtp);
97      if (iter == properties.end())
98      {
99          return -1;
100      }
101  
102      try
103      {
104          bool newNtpMode = std::get<bool>(iter->second);
105          bool oldNtpMode = (Mode::NTP == getTimeMode());
106          if (newNtpMode != oldNtpMode)
107          {
108              const auto& timeMode =
109                  newNtpMode ? settings::ntpSync : settings::manualSync;
110              std::string settingManager = utils::getService(
111                  bus, settings.timeSyncMethod.c_str(), settings::timeSyncIntf);
112              utils::setProperty(bus, settingManager, settings.timeSyncMethod,
113                                 settings::timeSyncIntf, propertyTimeMode,
114                                 timeMode);
115              setCurrentTimeMode(timeMode);
116              debug("NTP property changed in systemd time service, update to"
117                    " phosphor-settings.");
118          }
119          else
120          {
121              debug("NTP mode is already the same, skip setting to"
122                    " phosphor-settings again.");
123          }
124      }
125      catch (const std::exception& ex)
126      {
127          error("Failed to sync NTP: {ERROR}", "ERROR", ex);
128      }
129  
130      return 0;
131  }
132  
updateNtpSetting(const std::string & value)133  void Manager::updateNtpSetting(const std::string& value)
134  {
135      try
136      {
137          bool isNtp =
138              (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
139          auto method = bus.new_method_call(systemdTimeService, systemdTimePath,
140                                            systemdTimeInterface, methodSetNtp);
141          method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
142                                       // 'false' meaning no policy-kit
143  
144          bus.call_noreply(method);
145          info("Updated NTP setting: {ENABLED}", "ENABLED", isNtp);
146      }
147      catch (const sdbusplus::exception_t& ex)
148      {
149          error("Failed to update NTP setting: {ERROR}", "ERROR", ex);
150      }
151  }
152  
setCurrentTimeMode(const std::string & mode)153  bool Manager::setCurrentTimeMode(const std::string& mode)
154  {
155      try
156      {
157          auto newMode = utils::strToMode(mode);
158          if (newMode != timeMode)
159          {
160              info("Time mode has been changed to {MODE}", "MODE", newMode);
161              timeMode = newMode;
162              return true;
163          }
164      }
165      catch (const sdbusplus::exception_t& ex)
166      {
167          error("Failed to convert mode from string: {ERROR}", "ERROR", ex);
168      }
169  
170      return false;
171  }
172  
onTimeModeChanged(const std::string & mode)173  void Manager::onTimeModeChanged(const std::string& mode)
174  {
175      // When time_mode is updated, update the NTP setting
176      updateNtpSetting(mode);
177  }
178  
getSetting(const char * path,const char * interface,const char * setting) const179  std::string Manager::getSetting(const char* path, const char* interface,
180                                  const char* setting) const
181  {
182      try
183      {
184          std::string settingManager = utils::getService(bus, path, interface);
185          return utils::getProperty<std::string>(bus, settingManager.c_str(),
186                                                 path, interface, setting);
187      }
188      catch (const std::exception& ex)
189      {
190          error(
191              "Failed to get property: {ERROR}, path: {PATH}, interface: {INTERFACE}, name: {NAME}",
192              "ERROR", ex, "PATH", path, "INTERFACE", interface, "NAME", setting);
193          return {};
194      }
195  }
196  
197  } // namespace time
198  } // namespace phosphor
199