diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 960fad96a..676797ba0 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -14,6 +14,7 @@ - [Servers] Ability to use an HTTP proxy between XO and a server - [Pool/advanced] Ability to define network for importing/exporting VMs/VDIs (PRĀ [#5957](https://github.com/vatesfr/xen-orchestra/pull/5957)) - [Menu] Notify user when proxies need to be upgraded (PR [#5930](https://github.com/vatesfr/xen-orchestra/pull/5930)) +- [Host] Handle evacuation failure during host shutdown (PR [#5966](https://github.com/vatesfr/xen-orchestra/pull/#5966)) ### Bug fixes diff --git a/packages/xo-server/src/api/host.mjs b/packages/xo-server/src/api/host.mjs index d1c48f59b..5afe99a36 100644 --- a/packages/xo-server/src/api/host.mjs +++ b/packages/xo-server/src/api/host.mjs @@ -183,14 +183,15 @@ start.resolve = { // ------------------------------------------------------------------- -export function stop({ host }) { - return this.getXapi(host).shutdownHost(host._xapiId) +export function stop({ host, bypassEvacuate }) { + return this.getXapi(host).shutdownHost(host._xapiId, { bypassEvacuate }) } stop.description = 'stop the host' stop.params = { id: { type: 'string' }, + bypassEvacuate: { type: 'boolean', optional: true }, } stop.resolve = { diff --git a/packages/xo-server/src/xapi/index.mjs b/packages/xo-server/src/xapi/index.mjs index 6b56fa1f9..cf994ea0c 100644 --- a/packages/xo-server/src/xapi/index.mjs +++ b/packages/xo-server/src/xapi/index.mjs @@ -297,10 +297,13 @@ export default class Xapi extends XapiBase { await this.call('host.syslog_reconfigure', host.$ref) } - async shutdownHost(hostId, force = false) { + async shutdownHost(hostId, { force = false, bypassEvacuate = false }) { const host = this.getObject(hostId) - - await this.clearHost(host, force) + if (bypassEvacuate) { + await this.call('host.disable', host.$ref) + } else { + await this.clearHost(host, force) + } await this.callAsync('host.shutdown', host.$ref) } diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js index 4f3559447..2d8b13d7a 100644 --- a/packages/xo-web/src/common/intl/messages.js +++ b/packages/xo-web/src/common/intl/messages.js @@ -1655,6 +1655,8 @@ const messages = { stopHostModalTitle: 'Shutdown host', stopHostModalMessage: "This will shutdown your host. Do you want to continue? If it's the pool master, your connection to the pool will be lost", + forceStopHost: 'Force shutdown host', + forceStopHostMessage: 'This will shutdown your host without evacuating its VMs. Do you want to continue?', addHostModalTitle: 'Add host', addHostModalMessage: 'Are you sure you want to add {host} to {pool}?', restartHostModalTitle: 'Restart host', diff --git a/packages/xo-web/src/common/xo/index.js b/packages/xo-web/src/common/xo/index.js index 73aefb37a..abdfa50d1 100644 --- a/packages/xo-web/src/common/xo/index.js +++ b/packages/xo-web/src/common/xo/index.js @@ -807,11 +807,26 @@ export const restartHostsAgents = hosts => { export const startHost = host => _call('host.start', { id: resolveId(host) }) -export const stopHost = host => - confirm({ - title: _('stopHostModalTitle'), +export const stopHost = async host => { + await confirm({ body: _('stopHostModalMessage'), - }).then(() => _call('host.stop', { id: resolveId(host) }), noop) + title: _('stopHostModalTitle'), + }) + + try { + await _call('host.stop', { id: resolveId(host) }) + } catch (err) { + if (err.message === 'no hosts available') { + // Retry with bypassEvacuate. + await confirm({ + body: _('forceStopHostMessage'), + title: _('forceStopHost'), + }) + return _call('host.stop', { id: resolveId(host), bypassEvacuate: true }) + } + throw error + } +} export const stopHosts = hosts => { const nHosts = size(hosts)