diff --git a/@vates/types/src/lib/xen-orchestra-xapi.mts b/@vates/types/src/lib/xen-orchestra-xapi.mts index 129b84f1c7..e9ead7f258 100644 --- a/@vates/types/src/lib/xen-orchestra-xapi.mts +++ b/@vates/types/src/lib/xen-orchestra-xapi.mts @@ -419,8 +419,12 @@ export interface Xapi { pathname: string, params?: { host?: XenApiHost; query?: Record; task?: boolean | XenApiTask['$ref'] } ): Promise<{ body: Readable }> - clearHost(host: Pick, force?: boolean): Promise - disableHost(hostId: XoHost['id']): Promise + clearHost( + host: Pick, + force?: boolean, + opts?: { transient?: boolean } + ): Promise + disableHost(hostId: XoHost['id'], opts?: { transient?: boolean }): Promise enableHost(hostId: XoHost['id']): Promise getRecordByUuid< Type extends WrappedXenApiRecord['$type'], diff --git a/@xen-orchestra/rest-api/src/hosts/host.controller.mts b/@xen-orchestra/rest-api/src/hosts/host.controller.mts index 829a8505da..0d2bab0c49 100644 --- a/@xen-orchestra/rest-api/src/hosts/host.controller.mts +++ b/@xen-orchestra/rest-api/src/hosts/host.controller.mts @@ -458,6 +458,8 @@ export class HostController extends XapiXoController { * * Disable a host. * + * Set `autoEnable` to `true` to re-enable after a toolstack restart automatically + * * Set `evacuate` to `true` to also evacuate all running VMs to other hosts in the pool. * * Use `vmIdsToForceMigrate` to unblock VMs whose migration is currently blocked (e.g. by `pool_migrate` or `migrate_send` blocked operations). @@ -493,16 +495,21 @@ export class HostController extends XapiXoController { disable( @Path() id: string, // mark `evacuate` as optional to workaround a TSOA issue. See https://github.com/lukeautry/tsoa/pull/1840 - @Body() body?: { evacuate?: false } | { evacuate: true; force?: boolean; vmIdsToForceMigrate?: string[] }, + @Body() + body?: { autoEnable?: boolean } & ( + | { evacuate?: false } + | { evacuate: true; force?: boolean; vmIdsToForceMigrate?: string[] } + ), @Query() sync?: boolean ): CreateActionReturnType { const hostId = id as XoHost['id'] + const isTransient = body?.autoEnable ?? false const action = defer(async ($defer: Defer) => { const xapiHost = this.getXapiObject(hostId) const xapi = xapiHost.$xapi if (body?.evacuate !== true) { - await xapi.call('host.disable', xapiHost.$ref) + await xapi.disableHost(hostId, { transient: isTransient }) return } @@ -519,7 +526,7 @@ export class HostController extends XapiXoController { }) } - await xapi.clearHost(xapiHost, body.force) + await xapi.clearHost(xapiHost, body.force, { transient: isTransient }) }) return this.createAction(action, { diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index b88385a47d..35e5acc956 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -15,6 +15,7 @@ - `/pools/:id/actions/create_bonded_network` (PR [#9891](https://github.com/vatesfr/xen-orchestra/pull/9891)) - `/pools/:id/actions/create_internal_network` (PR [#9891](https://github.com/vatesfr/xen-orchestra/pull/9891)) - `/pools/:id/actions/management-reconfigure` (PR [#9891](https://github.com/vatesfr/xen-orchestra/pull/9891)) +- [REST API] Possibility of sending `autoEnable` in the body of the `/hosts/:id/actions/disable` endpoint (PR [#10040](https://github.com/vatesfr/xen-orchestra/pull/10040)) ### Bug fixes @@ -38,8 +39,9 @@ +- @vates/types minor - @xen-orchestra/rest-api minor - @xen-orchestra/web patch -- xo-server patch +- xo-server minor diff --git a/packages/xo-server/src/xapi/index.mjs b/packages/xo-server/src/xapi/index.mjs index 7680c5b5ff..dcfb18e961 100644 --- a/packages/xo-server/src/xapi/index.mjs +++ b/packages/xo-server/src/xapi/index.mjs @@ -201,8 +201,9 @@ export default class Xapi extends XapiBase { // // If `force` is false and the evacuation failed, the host is re- // enabled and the error is thrown. - async clearHost({ $ref: hostRef, $pool: pool }, force) { - await this.call('host.disable', hostRef) + // If `transient` is false, the host will be disabled indefinitely, across toolstack restarts and host reboots, until re-enabled explicitly with Host.enable. + async clearHost({ $ref: hostRef, $pool: pool }, force, { transient = true } = {}) { + await this.disableHost(hostRef, { transient }) const migrationNetworkRef = (id => { if (id !== undefined) {