Skip to content

Conversation

changlei-li
Copy link
Contributor

@changlei-li changlei-li commented Sep 29, 2025

New filed: host.ntp_mode, host.ntp_custom_servers
New API: host.set_ntp_mode, host.set_ntp_custom_servers, host.get_ntp_mode, host.get_ntp_custom_servers, host.get_ntp_servers_status.

ntp_mode_dhcp: In this mode, ntp uses the dhcp assigned ntp servers as sources. In Dom0, dhclient triggers chrony.sh to update the ntp servers when network event happens. It writes ntp servers to /run/chrony-dhcp/$interface.sources and the dir /run/chrony-dhcp is included in chrony.conf. The dhclient also stores dhcp lease in /var/lib/xcp/dhclient-$interface.leases, see https://github.com/xapi-project/xen-api/blob/v25.31.0/ocaml/networkd/lib/network_utils.ml#L925. When switch ntp mode to dhcp, XAPI checks the lease file and finds ntp server then fills chrony-dhcp file. The exec permission of chrony.sh is added. When swith ntp mode from dhcp to others, XAPI removes the chrony-dhcp files and the exec permission of chrony.sh. The operation is same with xsconsole https://github.com/xapi-project/xsconsole/blob/v11.1.1/XSConsoleData.py#L593. In this feature, xsconsole will change to use XenAPI to manage ntp later to avoid conflict.

ntp_mode_custom: In this mode, ntp uses host.ntp_custom_servers as sources. This is implemented by changing chrony.conf and restart chronyd. host.ntp_custom_servers is set by the user.

ntp_mode_default: In this mode, ntp uses default-ntp-servers in XAPI config file.

The dbsync, more APIs about NTP will be in following PRs.

@changlei-li
Copy link
Contributor Author

changlei-li commented Sep 29, 2025

Examles:

    def set_mode(mode):
        session.xenapi.host.set_ntp_mode(host_ref, mode)

    def set_custom_servers(servers):
        session.xenapi.host.set_ntp_custom_servers(host_ref, servers)

    def enable_ntp():
        session.xenapi.host.enable_ntp(host_ref)

    def disable_ntp():
        session.xenapi.host.disable_ntp(host_ref)

    def show():
        enabled = session.xenapi.host.get_ntp_enabled(host_ref)
        mode = session.xenapi.host.get_ntp_mode(host_ref)
        custom_servers = session.xenapi.host.get_ntp_custom_servers(host_ref)
        status = session.xenapi.host.get_ntp_servers_status(host_ref)
        print(f'enabled {enabled}; mode {mode}; custom_servers {custom_servers}; status {status}')

    def init():
        set_mode('ntp_mode_default')
        set_custom_servers([])
        disable_ntp()

    init()
    show()
    set_mode('ntp_mode_dhcp')
    show()
    enable_ntp()
    time.sleep(5)
    show()
    set_mode('ntp_mode_default')
    time.sleep(5)
    show()
    set_custom_servers(['time.google.com', 'time.windows.com', 'time.apple.com'])
    set_mode('ntp_mode_custom')
    time.sleep(5)
    show()

output:

enabled False; mode ntp_mode_default; custom_servers []; status {}
enabled False; mode ntp_mode_dhcp; custom_servers []; status {}
enabled True; mode ntp_mode_dhcp; custom_servers []; status {'10.71.56.11': 'synced'}
enabled True; mode ntp_mode_default; custom_servers []; status {'5.255.124.190': 'unreachable', '193.111.32.123': 'unreachable', '191.96.11.19': 'unreachable', '45.91.209.64': 'unreachable'}
enabled True; mode ntp_mode_custom; custom_servers ['time.google.com', 'time.windows.com', 'time.apple.com']; status {'216.239.35.4': 'unreachable', '20.101.57.9': 'unreachable', '17.253.52.253': 'unreachable'}

xe

# xe host-param-set uuid=46a671ce-65f2-4dd4-a61a-75ff6f1274b1 ntp-custom-servers=time.apple.org,3.xenserver.pool.ntp.org
# xe host-param-get uuid=46a671ce-65f2-4dd4-a61a-75ff6f1274b1 param-name=ntp-custom-servers 
time.apple.org, 3.xenserver.pool.ntp.org
# xe host-param-set uuid=46a671ce-65f2-4dd4-a61a-75ff6f1274b1 ntp-mode=ntp_mode_custom
# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^? web1.articlecontent.com       0   7     0     -     +0ns[   +0ns] +/-    0ns
^* nu.binary.net                 2   6    17     8    +79us[ +488us] +/-   51ms
# cat /etc/chrony.conf | grep ^server
server time.apple.org iburst
server 3.xenserver.pool.ntp.org iburst
# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* mia03-controller              5   6    17    10  -2801ns[  -23us] +/-   34ms
# xe host-param-set uuid=46a671ce-65f2-4dd4-a61a-75ff6f1274b1 ntp-mode=ntp_mode_default
# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* owners.kjsl.com               2   6     7     2   +232us[+3998us] +/-   37ms
^+ 23.157.160.168                2   6    17     0  -1998us[-1998us] +/-   50ms
^+ vps-4e90522b.vps.ovh.us       2   6     7     2  +5279us[+9045us] +/-   73ms
^+ ntp.shastacoe.net             2   6     7     2  -2803us[ +963us] +/-   61ms

@changlei-li changlei-li marked this pull request as draft September 29, 2025 07:20
@edwintorok
Copy link
Contributor

edwintorok commented Sep 29, 2025

# xe host-param-set uuid=46a671ce-65f2-4dd4-a61a-75ff6f1274b1 ntp-custom-servers=time.apple.org,3.xenserver.pool.ntp.org

Did you mean time.apple.com instead of time.apple.org? Both exist, but I think only the former is a time server and owned by Apple.


let chrony_conf = "/etc/chrony.conf"

let chrony_script = "/etc/dhcp/dhclient.d/chrony.sh"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually scripts are added to the list of requited commands in ocaml/idl so xapi will refuse to run if any of them are missing. Is there any reason this shouldn't be the case here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I am not aware of this. Let me check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean xapi_globs.ml right?

@edwintorok
Copy link
Contributor

How about Active Directory? IIUC that relies on a working clock synchronization with the AD servers (which may be out of sync with NTP, e.g. we've had situations where they were 30m off).
So if AD is enabled should we have a mode where we automatically set the host to sync with the AD server? (although the problem might be that there are multiple AD servers, and their clocks aren't synchronized between them, but that is something the AD admins should fix if XS detects/reports it).

- write ntp servers to chrony.conf
- interaction with dhclient
  - handle /run/chrony-dhcp/$interface.sources
  - handle chrony.sh
- restart/enable/disable chronyd

Signed-off-by: Changlei Li <[email protected]>
@changlei-li changlei-li force-pushed the private/changleli/ntp-config branch 2 times, most recently from 2d3bf3b to d52e6d9 Compare October 13, 2025 07:33
@changlei-li changlei-li marked this pull request as ready for review October 13, 2025 07:50
@changlei-li changlei-li force-pushed the private/changleli/ntp-config branch from d52e6d9 to f2c3a5c Compare October 13, 2025 08:17
@changlei-li changlei-li force-pushed the private/changleli/ntp-config branch from f2c3a5c to 97d6734 Compare October 13, 2025 08:21
@changlei-li
Copy link
Contributor Author

How about Active Directory? IIUC that relies on a working clock synchronization with the AD servers (which may be out of sync with NTP, e.g. we've had situations where they were 30m off). So if AD is enabled should we have a mode where we automatically set the host to sync with the AD server? (although the problem might be that there are multiple AD servers, and their clocks aren't synchronized between them, but that is something the AD admins should fix if XS detects/reports it).

It's a good point. But it is beyond the feature scope. Maybe worth exploring in future discussions or tickets

~ssh_enabled_timeout ~ssh_expiry ~console_idle_timeout ~ssh_auto_mode
~max_cstate:"" ~secure_boot ;
~max_cstate:"" ~secure_boot ~ntp_mode:`ntp_mode_dhcp ~ntp_custom_servers:[]
~ntp_enabled:false ;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible the default ntp service status is enabled after XS installation? If so, I would suggest add synchronization for the ntp service status when xapi starts.

Copy link
Contributor Author

@changlei-li changlei-li Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I need consider more for the dbsync (like ntp_mode, compatibility for old default ntp servers etc.). So, I plan to handle it in a new PR and ticket.

let open Xapi_host_ntp in
let ensure_custom_servers_exist servers =
if servers = [] then
Helpers.internal_error "ntp_custom_servers is empty, please set first"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about raise an api_errors? internal_error seems like an error caused by some XS internal issue. But actually this error is caused by a wrong customer configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.
xe error:

# xe host-param-set uuid=20370b70-d4df-4d43-b3a0-d0ad0227f022 ntp-mode=ntp_mode_custom
The NTP configuration is invalid.
reason: Can't set ntp_mode_custom when ntp_custom_servers is empty

# xe host-param-set uuid=20370b70-d4df-4d43-b3a0-d0ad0227f022 ntp-custom-servers=""
The NTP configuration is invalid.
reason: Can't set ntp_custom_servers empty when ntp_mode is custom

python sdk exception:

['INVALID_NTP_CONFIG', "Can't set ntp_mode_custom when ntp_custom_servers is empty"]
['INVALID_NTP_CONFIG', "Can't set ntp_custom_servers empty when ntp_mode is custom"]

Db.Host.set_ntp_mode ~__context ~self ~value
)

let set_ntp_custom_servers ~__context ~self ~value =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check the IP/domain format here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me consider it. But it seems hard to construct a valid domain format rule to check.

Copy link
Contributor Author

@changlei-li changlei-li Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will not check to format as it's hard to determine the valid domain format. And they will be written to server xxxxx iburst to chrony conf. ntp service will handle them. If incorrect, the ntp service will be abnormal due to the user's wrong configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants