Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
5bafbbc
Sync master into feature branch (#6683)
BengangY Sep 23, 2025
c604797
CP-54473 Implement max-state setting
changlei-li Sep 19, 2025
121cf3a
Add host.max_cstate and host.set_max_cstate
changlei-li Sep 19, 2025
3fcb233
update last_known_schema_hash
changlei-li Sep 19, 2025
c7e0f7c
CP-54473 Configure max-cstate by XAPI (#6681)
changlei-li Sep 29, 2025
8654f0c
Merge branch 'master' into feature/config-ntp-timezone-maxcstate
changlei-li Oct 13, 2025
b149cba
Merge master into feature/config-ntp-timezone-maxcstate (#6705)
changlei-li Oct 13, 2025
11d1fbb
CP-54471 Add ntp operations
changlei-li Sep 29, 2025
b7a44cb
CP-54471 Add host.ntp_mode and host.ntp_custom_servers
changlei-li Sep 29, 2025
ce0ece9
CP-54471 Add host.enable/disable_ntp
changlei-li Oct 11, 2025
680f30d
CP-54471 Add ntp config dbsync
changlei-li Oct 20, 2025
409244f
CP-308854 Add host.get_ntp_servers_status
changlei-li Oct 13, 2025
469ef69
Update last_known_schema_hash
changlei-li Sep 29, 2025
0922ece
CP-54471 Configure Dom0 NTP via XAPI (#6689)
changlei-li Oct 23, 2025
4c61c9a
Merge branch 'master' into feature/config-ntp-timezone-maxcstate
changlei-li Oct 23, 2025
24ac858
Merge master into feature/config-ntp-timezone-maxcstate (#6723)
changlei-li Oct 23, 2025
490d243
CP-308544 Promote legacy default ntp servers
changlei-li Oct 23, 2025
1383d1a
CP-308544 Promote legacy default ntp servers (#6727)
changlei-li Oct 28, 2025
c711a42
Merge maser into feature/config-ntp-timezone-maxcstate (#6742)
changlei-li Nov 5, 2025
01d742a
[doc] Add host-ntp-time feature doc
changlei-li Nov 6, 2025
0d72fdd
[doc] Add host-ntp-time feature doc (#6745)
changlei-li Nov 18, 2025
2659c9c
CP-308545 Add host.timezone
changlei-li Nov 11, 2025
f677ea7
Update last_known_schema_hash
changlei-li Nov 17, 2025
4a67e13
CP-308545 Add host.timezone (#6758)
changlei-li Nov 18, 2025
18db42a
CP-308856 host.get_ntp_synchronized
minglumlu Oct 30, 2025
9b674e9
CP-308855: host.set_servertime
minglumlu Nov 4, 2025
1ee40bf
Add host.get_ntp_synchronized and host.set_servertime (#6743)
minglumlu Nov 25, 2025
442efae
Merge master into feature/config-ntp-timezone-maxcstate (#6764)
changlei-li Nov 25, 2025
53cbd66
CP-54476 Merge ntp disable/enable to ntp mode
changlei-li Nov 14, 2025
cb78af3
Use timedatectl to enable/disable ntp
changlei-li Nov 12, 2025
fac9043
Fix `/run/chrony-dhcp` does not exist
changlei-li Nov 28, 2025
1b698f0
Update datamodel lifecycle and bump schema
changlei-li Nov 25, 2025
02ee3af
CP-54476 Merge ntp disable/enable to ntp mode (#6765)
changlei-li Dec 1, 2025
1dcbc15
Merge master into feature/config-ntp-timezone-maxcstate (#6777)
changlei-li Dec 1, 2025
dcc6219
Merge master into feature/config-ntp-timezone-maxcstate
changlei-li Dec 10, 2025
fe45173
Update lifecycle
changlei-li Dec 10, 2025
e02d597
Merge master into feature/config-ntp-timezone-maxcstate (#6787)
changlei-li Dec 10, 2025
fb66dfc
CA-421847: set vcpu affinity if node claim succeeded
mg12 Dec 10, 2025
06c1d62
CA-422071: preserve latest_synced_updates_applied and pending_guidanc…
edwintorok Dec 15, 2025
bd8c79a
CA-422071: add unit test for Host.create_params
edwintorok Dec 15, 2025
b0eaef3
CA-421847: set vcpu affinity if node claim succeeded (#6794)
edwintorok Dec 15, 2025
e9123bd
XSI-2088: CA-422080: External auth can not support large forest
Dec 13, 2025
a7a4606
CA-422072 Add new fields to host create params
changlei-li Dec 16, 2025
e4bf99c
CA-422072 Add new fields to host create params (#6801)
robhoes Dec 16, 2025
5b121e2
CA-422071: guard against losing Host field settings on pool join (#6799)
robhoes Dec 16, 2025
d70468e
Merge branch 'master' into feature/config-ntp-timezone-maxcstate
changlei-li Dec 16, 2025
7aa44cc
Sync master into feature/config-ntp-timezone-maxcstate (#6802)
changlei-li Dec 16, 2025
525daf6
XSI-2088: CA-422080: Code refine for comments
Dec 16, 2025
68bf47d
XSI-2088: CA-422080: External auth can not support large forest (#6800)
robhoes Dec 16, 2025
dfd30d0
ocaml/xapi-idl: change CLI help tests
psafont Dec 16, 2025
5df7250
ocaml: prepare formatting for new ocamlformat
psafont Dec 11, 2025
bc541ee
ocaml: prepare for ocaml 5.4 and ocamlformat 0.28.1 (#6805)
psafont Dec 17, 2025
278358b
coverage: remove dependency on bisect_ppx
psafont Dec 17, 2025
fefe7cf
coverage: remove dependency on bisect_ppx (#6807)
psafont Dec 17, 2025
2efeb43
CP-310867 Sort output of diagnostic-timing-stats
lindig Dec 17, 2025
b1d900b
Sort output of diagnostic-timing-stats (#6808)
lindig Dec 18, 2025
ff34a8a
Merge feature/config-ntp-timezone-maxcstate into master (#6810)
robhoes Dec 19, 2025
2a34053
XSI-2093: CA-422229: Host should not register all IPs to DNS server
Dec 19, 2025
69b54ad
XSI-2093: CA-422229: Host should not register all IPs to DNS server (…
liulinC Dec 22, 2025
fe0ae6e
[doc] Improvements on management of trusted certificates
minglumlu Dec 15, 2025
1878ccc
[doc] Split peer and root CA for trusted certificates; Add purpose (#…
minglumlu Dec 24, 2025
d308a91
CA-422282 Fix race condition about xenops cache
changlei-li Dec 31, 2025
37c017b
CA-422282 Fix race condition about xenops cache (#6813)
changlei-li Jan 4, 2026
535f626
Update hash for API schema
lindig Jan 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ build:
check:
dune build @check -j $(JOBS)

coverage:
dune runtest --instrument-with bisect_ppx --force --profile=$(RELEASE) -j $(JOBS)
bisect-ppx-report html
bisect-ppx-report summary --per-file

clean:
dune clean

Expand Down
210 changes: 210 additions & 0 deletions doc/content/design/host-ntp-time.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
---
title: Host NTP and time config API
layout: default
design_doc: true
revision: 1
status: proposed
---

# Host NTP and time

## Background

There are no APIs to config the NTP and timezone on the host. Previously, users
had to login on the host via ssh and configure NTP and time manually. The goal
of this feature is to introduce new APIs in XAPI to support NTP and time
configuration, especially in the scenario that users disable ssh service on the
host. XAPI can also store the NTP and timezone configuration in XAPI DB to provide
cache for the getter APIs.

## Use cases

- User can set time zone of the host via XenAPI
- User can get valid time zones list to set via XenAPI
- User can get the current time zone of the host via XenAPI
- User can set custom NTP servers via XenAPI
- User can get the current custom NTP servers via XenAPI
- User can enable/disable NTP service via XenAPI
- User can get the current NTP service enabled or disabled via XenAPI
- User can set NTP to use DHCP assigned servers via XenAPI
- User can set NTP to use custom servers via XenAPI
- User can set NTP to use default NTP servers via XenAPI
- User can get the DHCP assigned NTP servers via XenAPI
- User can get status of current NTP servers via XenAPI
- User can get NTP sync status via XenAPI
- User can set host’s time when NTP is disabled via XenAPI

## NTP configuration on the host

New fields:
`host.ntp_mode`, enum host_ntp_mode(DHCP, Custom, Factory, Disabled)
`host.ntp_custom_servers`, string set

New APIs: `host.set_ntp_mode`, `host.set_ntp_custom_servers`, `host.get_ntp_mode`,
`host.get_ntp_custom_servers`, `host.get_ntp_servers_status`

Abstract the NTP configuration to 4 modes.
- DHCP: set NTP to use DHCP assigned NTP servers
- Custom: set NTP to use custom NTP servers
- Factory: set NTP to use factory NTP servers
- Disabled: disable NTP service

### DHCP mode

In this mode, NTP uses the DHCP assigned NTP servers as sources.

How the NTP and DHCP interaction?

On the host, dhclient executes `/etc/dhcp/dhclient.d/chrony.sh` to update the
ntp servers when network event happens.
- `chrony.sh` writes ntp servers to `/run/chrony-dhcp/$interface.sources`
- Chonryd include the dir `/run/chrony-dhcp` by `sourcedir /run/chrony-dhcp` in
the conf file
- `chrony.sh` runs `chronyc reload sources` to reload NTP sources

Then NTP sources can be updated automatically in the DHCP mode

How to switch DHCP mode?

Dhclient stores dhcp lease in `/var/lib/xcp/dhclient-$interface.leases`, see
module Dhclient in `/ocaml/networkd/lib/network_utils.ml`.

When switch the NTP mode to DHCP, XAPI
- check ntp server item in the lease and fills it in chrony-dhcp files
- Add the exec permission of `chrony.sh`
- Remove all the NTP source items(Custom or Factory) in chronyd conf
- Restart chronyd

When switch ntp mode from dhcp to others, XAPI
- Remove the chrony-dhcp files
- Remove the exec permission of chrony.sh
- Add NTP source items(Custom or Factory) in chronyd conf
- Restart chronyd

### Custom mode

In this mode, NTP uses `host.ntp_custom_servers` as sources.

When switch the NTP mode to Custom, XAPI
- Remove NTP source items in chronyd conf
- Add `host.ntp_custom_servers` as NTP source items in chronyd conf
- Restart chronyd

When `host.ntp_custom_servers` changes and `host.ntp_mode` is Custom, set chronyd
conf with new custom servers and restart chronyd.

### Factory mode

In this mode, ntp uses `factory-ntp-servers` in XAPI config file. Generally the
factory-ntp-servers will be defined by the product.

### Disabled mode

This mode disables NTP service on the host.

### Others

`host.get_ntp_servers_status` calls `chronyc -c sources` to get ntp servers status.
Output parse:
```
Source mode: '^' = server, '=' = peer, '#' = local clock.
Source state: '*' = current synced, '+' = combined, '-' = not combined,
'?' = unreachable, 'x' = time may be in error, '~' = time too variable
```

## Timezone configuration on the host

New field: `host.timezone`, string

New APIs: `host.set_timezone`, `host.get_timezone`, `host.list_timezones`

The timezone is in IANA timezone database format. Timezone on the host can be
get by `realpath /etc/localtime` which is linked to timezone file under
`/usr/share/zoneinfo/`. It can set by link`/etc/localtime` to
`/usr/share/zoneinfo/<timezone>`. All the valid timezones are actually the files
under `/usr/share/zoneinfo/`.

Comparing to using a fixed UTC offset, the benefit is:
- User-friendly: familiar region names and same with most system facilities.
- Handles daylight saving time (DST) automatically

They are equivalent to the `timedatectl` commands
```
timedatectl set-timezone
timedatectl status | grep "Time zone"
timedatectl list-timezones
```

## Time on the host

New API: `host.get_ntp_synchronized`, `host.set_servertime`

`host.get_ntp_synchronized` shows if the system time is synchronized with NTP
source.

`host.set_servertime` offers an API to set the server time when NTP disabled.
it accepts a RFC3339 datetime format timestamp with timezone, i.e. ends with 'Z'
to represent the UTC or explicit UTC offset like '+05:00'.

## Dbsync and restriction

For the new fields in this doc, on XAPI start, dbsync will get the real host
status and sync to XAPI DB to make the real host status and XAPI DB consistent.
Upgrade case can also be benefited from the dbsync.

If the user changes the config behind XAPI, like modify the chronyd conf directly
via ssh, the real status on the host and XAPI DB come to inconsistent and may
lead to unpredicted result, unless restart XAPI.

## Usage examples

Set NTP DHCP mode and get the status
```python
session.xenapi.host.set_timezone(host_ref, 'UTC')
session.xenapi.host.set_ntp_mode(host_ref, 'DHCP')
session.xenapi.host.get_ntp_synchronized(host_ref)
session.xenapi.host.get_ntp_servers_status(host_ref)
```

Set NTP Custom mode and get the status
```python
session.xenapi.host.set_timezone(host_ref, 'Europe/London')
servers = ['time.server1.com', 'time.server2.com', 'time.server3.com']
session.xenapi.host.set_ntp_custom_servers(host_ref, servers)
session.xenapi.host.set_ntp_mode(host_ref, 'Custom')
session.xenapi.host.get_ntp_synchronized(host_ref)
session.xenapi.host.get_ntp_servers_status(host_ref)
```

Set NTP default mode and get the status
```python
session.xenapi.host.set_ntp_mode(host_ref, 'Factory')
session.xenapi.host.get_ntp_synchronized(host_ref)
session.xenapi.host.get_ntp_servers_status(host_ref)
```

Disable NTP and set server time
```python
session.xenapi.host.set_timezone(host_ref, 'Europe/London')
session.xenapi.host.set_ntp_mode(host_ref, 'Disabled')
session.xenapi.host.set_servertime(host_ref, "20251105T16:11:55Z")
```

## APIs summary

```
host.ntp_mode
host.ntp_custom_servers
host.timezone

host.set_timezone
host.list_timezones
host.get_timezone
host.get_ntp_synchronized
host.set_ntp_mode
host.get_ntp_mode
host.set_ntp_custom_servers
host.get_ntp_custom_servers
host.get_ntp_servers_status
host.set_servertime
```
151 changes: 151 additions & 0 deletions doc/content/design/trusted-certificates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
title: Trusted certificates for identity validation in TLS connections
layout: default
design_doc: true
revision: 1
status: draft
---

# Overview

In various use cases, TLS connections are established on the host on which XAPI runs.
When establishing a TLS connection, the peer identity needs to be validated.
This is done using either a root CA certificate to perform certificate chain validation, or a known peer certificate for validation with certificate pinning.
The root CA certificates and peer certificates involved in this process are referred to as trusted certificates.
When a trusted certificate is installed, the local endpoint can validate the peer identity during TLS connection establishment.
Certificate chain validation is a general-purpose, standards-based approach but requires additional steps, such as getting the peer's certificate signed by a CA.
In contrast, certificate pinning offers a quicker way to set up trust in some cases without the overhead of CA signing.
For example, when establishing a TLS connection, the peer endpoint presenting a self-signed server certificate, the local endpoint, after explicit user confirmation, can set up the trust by pinning the server certificate for this peer.
For subsequent connections, the local endpoint validates the peer against the pinned certificate.
This allows the use case to start in quicker and easier way without prior CA signing and without compromising security.

As the unified API for the whole system, XAPI also exposes interfaces for users to install and manage trusted certificates that are used by system components for different purposes.

The base design described in [pool-certificates.md](https://github.com/minglumlu/xen-api/blob/5d1ea1520825d502c57a90a02db476cd7d6a9132/doc/content/design/pool-certificates.md) defines the database, API, and trust store in the filesystem for managing trusted certificates.
This document introduces the following enhancements to that design:

* Explicit separation of root CA certificates and peer certificates:
In the base design, both certificate types share the same database schema, APIs, and are stored together in a single bundle file.
This makes it difficult to determine the appropriate validation approach based on the certificate type.
The improvement introduces a type value to separate root CA certificates and peer certificates explicitly.

* Add a "purpose" attribute for trusted certificates:
According to the base design, only certificates used for internal TLS connections among XAPI processes within a pool are stored separately.
All other trusted certificates are grouped in a single bundle, which may include certificates for multiple purposes.
By introducing a "purpose" attribute, certificates can be organized by their intended use, improving clarity and reducing ambiguity.

# Use Cases
* An XAPI client establishes a TLS connection to an XAPI service.
This case is outside the scope of trusted certificates managed by XAPI and is included here only for completeness.
* An XAPI process on one host initiates a TLS connection to an XAPI process on another host within the same pool.
This case is covered in the base design and is listed here for completeness.
* An XAPI process initiates a TLS connection to an external service, such as an appliance.
This case benefits from the improvements introduced in this design.
* A non-XAPI process (like licensing agent) running on a host managed by XAPI initiates a TLS connection to an external service, such as a License Server.
This case benefits from the improvements introduced in this design as well.


# Changes
## Database schema
The *Certificate* class in database is defined to represent general certificates, including trusted certificates.
One existing class field "type" supports the following enumeration values:
* "ca": trusted certificates including both root CA and peer.
* "host": identity certificate of a host for communication with entities outside the pool.
* "host_internal": identity certificate of a host for communication with other pool members.

Two improvements in this design:
* A new value "peer" is introduced in this design so that the existing "ca" now represents trusted root CA only.
The new "peer" will represent trusted peer certificates.

* A new enumeration type "purpose" is introduced to indicate the intended usage of a trusted certificate.
A new *Certificate* class field "purpose" (a set of values of enumeration type "purpose") will be added to represent all applicable purposes of a trusted certificate.
By default, this set is empty which corresponds to the existing "ca" certificates for general purpose.

## API

### pool.install_ca_certificate

This is an existing API to install a trusted certificate into the pool with its arguments being defined as:
* session (ref session_id): reference to a valid session;
* name (string): the name of the certificate;
* cert (string): the certificate in PEM format.

Prior to this design, the API's name parameter represents the certificate file name as persisted on the dom0 file system.
In this design, this API will be deprecated because it exposes implementation details that should remain internal and hidden from users.
The new "pool.install_trusted_certificate" should be used instead.
For the same reason, "pool.uninstall_ca_certificate" will also be deprecated.

### pool.install_trusted_certificate
This is a new API introduced in this design with its arguments being defined as:
* session (ref session_id): reference to a valid session;
* self (ref Pool): reference to the pool;
* ca (boolean): the trusted certificate is a root CA certificate used to verify a chain (true), or a peer certificate used for certificate pinning (false);
* cert (string): the trusted certificate in PEM format;
* purpose (string list): the purposes of the trusted certificate.

This new API is used to install trusted certificate.
When *purpose* is an empty set, it stands for a root CA certificate for general purpose.
The *purpose* can not be an empty set when the *ca* is false, because each peer certificate is specific to a single server and therefore unsuitable for a shared trusted certificate for general purpose.

It returns *void* when succeed. Otherwise, return corresponding API error.

### pool.uninstall_trusted_certificate
This is a new API introduced in this design to uninstall a trusted certificate with its arguments being defined as:
* session (ref session_id): reference to a valid session;
* certificate (ref Certificate): reference to the trusted certificate;
* force (bool): remove the database entry even if the file doesn't exist.

It returns *void* when succeed. Otherwise, return corresponding API error.

### pool.join
Prior to this design, trusted certificates are exchanged between the pool and the joining host during the pre‑join phase.
This design preserves that behavior to ensure the joiner works correctly both before and after joining the pool.

### pool.eject
The trusted certificates will be removed from any host which is being eject from the pool.

### Other APIs of managing trusted certificates
The install/uninstall APIs above are not the only ways of managing the trusted certificates.
A particular API, e.g. "pool.set_wlb_url", may also install the trusted certificate used to validate the WLB server on subsequent TLS connections.
However, regardless of the entry point, all trusted certificates must be represented by a *Certificate* database object and stored in the same way described below as if installed by the install APIs.

## Trust store
The trusted certificates are stored in individual hosts' filesystems.
The existing stores defined in the base design are:
| Name | Filesystem location | User-configurable | Used for |
| ---- | ------------------- | ----------------- | -------- |
| Trusted Default | /etc/stunnel/certs/ | yes (using API) | Certificates that users can install for trusting appliances
| Trusted Pool | /etc/stunnel/certs-pool/ | no | Certificates that are managed by the pool for host-to-host communications
| Default Bundle | /etc/stunnel/xapi-stunnel-ca-bundle.pem | no | Bundle of certificates that hosts use to verify appliances (in particular WLB), this is kept in sync with "Trusted Default"
| Pool Bundle | /etc/stunnel/xapi-pool-ca-bundle.pem | no | Bundle of certificates that hosts use to verify other hosts on pool communications, this is kept in sync with "Trusted Pool"

Regarding the "User-configurable", when it is "yes", it means a user can only install and remove the file with "name" parameter of "pool.install_ca_certificate" ; when it is "no", it means the user can't install or remove it even via APIs. In any cases, a user can't change the certificate files directly.

When a trusted certificate is being installed via "pool.install_ca_certificate", the trusted certificate will be stored in the "Trusted Default" and "Default Bundle".
This design doesn't change this for backwards compatibility. But the API "pool.install_ca_certificate" will be marked as *deprecated*.

The pool "Trusted Pool" and "Pool Bundle" are for host-to-host TLS communications within a pool. This design doesn't change them.

The stores for the certificates installed via "pool.install_trusted_certificate" are defined as:
| Name | Filesystem location | Used for |
| ---- | ------------------- | -------- |
| Trusted General CA | /etc/trusted-certs/ca-general/ | Trusted root CA certificates that users can install to validate a peer’s identity when establishing a TLS connection for general purpose.
| Trusted Peer | /etc/trusted-certs/peer-\<PURPOSE\>/ | Trusted peer certificates that users can install to validate a peer’s identity when establishing a TLS connection for \<PURPOSE\>.
| Trusted CA | /etc/trusted-certs/ca-\<PURPOSE\>/ | Trusted root CA certificates that users can install to validate a peer’s identity when establishing a TLS connection for \<PURPOSE\>.
| General Bundle | /etc/trusted-certs/ca-bundle-general.pem | Bundle of trusted root CA certificates under /etc/trusted-certs/ca-general/ to verify a peer's identity when establishing a TLS connection for general purpose.
| Peer Bundle | /etc/trusted-certs/peer-bundle-\<PURPOSE\>.pem | Bundle of trusted peer certificates under /etc/trusted-certs/peer-\<PURPOSE\>/ to verify a peer's identity when establishing a TLS connection for \<PURPOSE\>.
| CA Bundle | /etc/trusted-certs/ca-bundle-\<PURPOSE\>.pem | Bundle of trusted root CA certificates under /etc/trusted-certs/ca-\<PURPOSE\>/ to verify a peer's identity when establishing a TLS connection for \<PURPOSE\>.

The filesystem location is derived from the \<PURPOSE\>. Each \<PURPOSE\> string corresponds to a predefined value of the "purpose" type in the database, implemented as predefined constants.
The certificate file names under filesystem locations of "Trusted General CA", "Trusted Peer" and "Trusted CA" will be the UUIDs of the *Certificate* objects.

## Precedence order of choosing trust stores
The "Peer Bundle", "CA Bundle", and "Default Bundle" can be directly used when establishing TLS connections.
The endpoint to validate the peer's identity must unambiguously choose only one non-empty bundle from them with the following precedence order:
1. "Peer Bundle"
2. "CA Bundle"
3. "General Bundle"

No more attempts on remaining bundles when validation with the selected one fails (the server certificate is not trusted by the selected bundle).

For example, if "Peer Bundle" doesn't exist and the "CA Bundle" (if not empty) is selected to do the validation, the endpoint should not try with "General Bundle" even when the validation with "CA Bundle" failed.
1 change: 0 additions & 1 deletion dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,6 @@
(alcotest :with-test)
astring
base-unix
(bisect_ppx :with-test)
(clock
(and
(= :version)
Expand Down
6 changes: 6 additions & 0 deletions ocaml/idl/datamodel_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2062,6 +2062,12 @@ let _ =
error Api_errors.sysprep ["vm"; "message"]
~doc:"VM.sysprep error with details in the message" () ;

error Api_errors.invalid_ntp_config ["reason"]
~doc:"The NTP configuration is invalid." () ;

error Api_errors.not_allowed_when_ntp_is_enabled ["host"]
~doc:"The operation is not allowed on the host when the NTP is enabled." () ;

message
(fst Api_messages.ha_pool_overcommitted)
~doc:
Expand Down
Loading
Loading