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
4 files changed
tree: e34763ee2b62bf31b8203ead31887760bde9684e
  1. subprojects/
  2. test/
  3. .clang-format
  4. .clang-tidy
  5. .gitignore
  6. bmc_epoch.cpp
  7. bmc_epoch.hpp
  8. LICENSE
  9. main.cpp
  10. manager.cpp
  11. manager.hpp
  12. meson.build
  13. meson.options
  14. OWNERS
  15. property_change_listener.hpp
  16. README.md
  17. settings.cpp
  18. settings.hpp
  19. types.hpp
  20. utils.cpp
  21. utils.hpp
  22. xyz.openbmc_project.Time.Manager.service
README.md

Introduction

phosphor-time-manager is the time manager service that implements D-Bus interface xyz/openbmc_project/Time/EpochTime.interface.yaml. The user can get or set the BMC's time via this interface.

Configuration

phosphor-time-manager is configured by setting -D flags that correspond to options in phosphor-time-manager/meson.options. The option names become C++ preprocessor symbols that control which code is compiled into the program.

  • Compile phosphor-time-manager with default options:

       meson setup builddir
       ninja -C builddir
    
  • Compile phosphor-time-manager with some configurable options:

       meson setup builddir -Dbuildtype=minsize  -Dtests=disabled
       ninja -C builddir
    
  • Generate test coverage report:

       meson setup builddir -Db_coverage=true -Dtests=enabled
       ninja coverage -C builddir test
    

General usage

The service xyz.openbmc_project.Time.Manager provides an object on D-Bus:

  • /xyz/openbmc_project/time/bmc

where each object implements interface xyz.openbmc_project.Time.EpochTime.

The user can directly get or set the property Elapsed of the objects to get or set the time. For example on an authenticated session:

  • To get BMC's time:

    ### With busctl on BMC
    busctl get-property xyz.openbmc_project.Time.Manager \
        /xyz/openbmc_project/time/bmc xyz.openbmc_project.Time.EpochTime Elapsed
    
    ### With REST API on remote host
    curl -b cjar -k https://${BMC_IP}/xyz/openbmc_project/time/bmc
    
  • To set BMC's time:

    ### With busctl on BMC
    busctl set-property xyz.openbmc_project.Time.Manager \
        /xyz/openbmc_project/time/bmc xyz.openbmc_project.Time.EpochTime \
        Elapsed t <value-in-microseconds>
    
    ### With REST API on remote host
    curl -b cjar -k -H "Content-Type: application/json" -X PUT \
        -d '{"data": 1487304700000000}' \
        https://${BMC_IP}/xyz/openbmc_project/time/bmc/attr/Elapsed
    

Time settings

Getting BMC time is always allowed, but setting the time may not be allowed depending on the below two settings in the settings manager.

  • TimeSyncMethod
    • NTP: The time is set via NTP server.
    • MANUAL: The time is set manually.

A summary of which cases the time can be set on BMC or HOST:

ModeSet BMC Time
NTPFail to set
MANUALOK
  • To set an NTP server:

    ### With busctl on BMC
    busctl set-property  xyz.openbmc_project.Network \
       /xyz/openbmc_project/network/eth0 \
       xyz.openbmc_project.Network.EthernetInterface NTPServers \
       as 1 "<ntp_server>"
    
    ### With REST API on remote host
    curl -c cjar -b cjar -k -H "Content-Type: application/json" -X  PUT  -d \
        '{"data": ["<ntp_server>"] }' \
        https://${BMC_IP}/xyz/openbmc_project/network/eth0/attr/NTPServers
    
  • To go into NTP mode

    ### With busctl on BMC
    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"
    
    ### With REST API on remote host
    curl -c cjar -b cjar -k -H "Content-Type: application/json" -X  PUT  -d \
        '{"data": "xyz.openbmc_project.Time.Synchronization.Method.NTP" }' \
        https://${BMC_IP}/xyz/openbmc_project/time/sync_method/attr/TimeSyncMethod
    

Special note on changing NTP setting

Starting from OpenBMC 2.6 (with systemd v239), systemd's timedated introduces a new beahvior that it checks the NTP services' status during setting time, instead of checking the NTP setting:

  • When NTP server is set to disabled, and the NTP service is stopping but not stopped, setting time will get an error.

In OpenBMC 2.4 (with systemd v236), the above will always succeed.

This results in openbmc/openbmc#3459, and the related test cases are updated to cooperate with this behavior change.