Synchronize NTP settings with systemd-timedated

Bmcweb get/set the "NTP settings" on phosphor-settings.
phosphor-time-manager and phosphor-settings are responsible to sync the
settings with systemd-timedated. So the services like bmcweb and ipmid
will only have to get/set the property on phosphor-settings.

However, in order to avoid a race condition issue with NTP set, bmcweb
now directly uses systemd instead of routing through phosphor-settings.
As a result, there may be differences in the "NTP settings" between
phosphor-setttings and systemd-timedated. To address this, this commit
adds a match to monitor time sync method changes on systemd-timedated
and updates it to phosphor-settings.

Tested:
```
1. Get current NTP setting:
busctl get-property org.freedesktop.timedate1 /org/freedesktop/timedate1 org.freedesktop.timedate1 NTP
b true

busctl get-property xyz.openbmc_project.Settings /xyz/openbmc_project/time/sync_method xyz.openbmc_project.Time.Synchronization TimeSyncMethod -j
{
    "type" : "s",
    "data" : "xyz.openbmc_project.Time.Synchronization.Method.NTP"
}

2. Call method in systemd timedate, to change NTP setting:
busctl call org.freedesktop.timedate1 /org/freedesktop/timedate1 org.freedesktop.timedate1 SetNTP bb false false

journal log:
phosphor-time-manager[28150]: Time mode has been changed to xyz.openbmc_project.Time.Synchronization.Method.Manual
phosphor-time-manager[28150]: NTP property changed in systemd time service, update to phosphor-settings.
phosphor-time-manager[28150]: NTP mode is already the same, skip setting to systemd time service again.

3. Get NTP setting again, NTP in phosphor-settings is synced with systemd-timedated:
busctl get-property org.freedesktop.timedate1 /org/freedesktop/timedate1 org.freedesktop.timedate1 NTP
b false

busctl get-property xyz.openbmc_project.Settings /xyz/openbmc_project/time/sync_method xyz.openbmc_project.Time.Synchronization TimeSyncMethod -j
{
    "type" : "s",
    "data" : "xyz.openbmc_project.Time.Synchronization.Method.Manual"
}

4. Set property in phosphor-settings, to change NTP setting:
busctl set-property xyz.openbmc_project.Settings /xyz/openbmc_project/time/sync_method xyz.openbmc_project.Time.Synchronization TimeSyncMethod s "xyz.openbmc_project.Time.Synchronization.Method.NTP"

journal log:
phosphor-time-manager[28150]: Updated NTP setting: True
phosphor-time-manager[28150]: Time mode has been changed to xyz.openbmc_project.Time.Synchronization.Method.NTP
phosphor-time-manager[28150]: NTP property changed in phosphor-settings, update to systemd time service.
phosphor-time-manager[28150]: NTP mode is already the same, skip setting to phosphor-settings again.

5. Get NTP setting again, NTP in phosphor-settings is synced with systemd-timedated:
busctl get-property org.freedesktop.timedate1 /org/freedesktop/timedate1 org.freedesktop.timedate1 NTP
b true

busctl get-property xyz.openbmc_project.Settings /xyz/openbmc_project/time/sync_method xyz.openbmc_project.Time.Synchronization TimeSyncMethod -j
{
    "type" : "s",
    "data" : "xyz.openbmc_project.Time.Synchronization.Method.NTP"
}
```

Signed-off-by: Jason Zhu <zhujiesen@bytedance.com>
Change-Id: I192d2257569f46aa0f5473331595c5242d816964
diff --git a/utils.hpp b/utils.hpp
index 34a67e8..eaf92c3 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -58,6 +58,42 @@
     }
 }
 
+/** @brief The template function to set property to the requested dbus path
+ *
+ * @param[in] bus          - The Dbus bus object
+ * @param[in] service      - The Dbus service name
+ * @param[in] path         - The Dbus object path
+ * @param[in] interface    - The Dbus interface
+ * @param[in] propertyName - The property name to set
+ * @param[in] value - the value to set the property to
+ *
+ */
+template <typename T>
+void setProperty(sdbusplus::bus_t& bus, const std::string& service,
+                 const std::string& path, const std::string& interface,
+                 const std::string& propertyName, T& value)
+{
+    std::variant<T> propertyValue(value);
+
+    auto method = bus.new_method_call(service.c_str(), path.c_str(),
+                                      "org.freedesktop.DBus.Properties", "Set");
+
+    method.append(interface, propertyName, propertyValue);
+
+    try
+    {
+        auto reply = bus.call(method);
+    }
+    catch (const sdbusplus::exception_t& ex)
+    {
+        error("SetProperty call failed, path:{PATH}, interface:{INTF}, "
+              "propertyName:{NAME}, error:{ERROR}",
+              "PATH", path, "INTF", interface, "NAME", propertyName, "ERROR",
+              ex);
+        throw std::runtime_error("SetProperty call failed");
+    }
+}
+
 /** @brief Get service name from object path and interface
  *
  * @param[in] bus          - The Dbus bus object