From 85ec26194b66b557cf41e6ec8283840631a99e86 Mon Sep 17 00:00:00 2001 From: Mathieu <70369997+MathieuRA@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:18:40 +0100 Subject: [PATCH] feat(xo-web/host): ask for confirmation to reboot the updated slave host if the master is not (#7293) Fixes #7059 In case a slave host requires a reboot to apply updates and the master is using the same version as the slave host, a confirmation modal is triggered. --- CHANGELOG.unreleased.md | 1 + packages/xo-server/src/api/host.mjs | 22 +++++++++++++++++ packages/xo-web/src/common/intl/messages.js | 3 +++ packages/xo-web/src/common/xo/index.js | 26 ++++++++++++++++++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index ed2101dc2f3..3473f14c263 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -14,6 +14,7 @@ - [Pool/Host] Add a warning if hosts do not have the same version within a pool [#7059](https://github.com/vatesfr/xen-orchestra/issues/7059) (PR [#7280](https://github.com/vatesfr/xen-orchestra/pull/7280)) - [Plugins] Loading, or unloading, will respectively enable, or disable, _Auto-load at server start_, this should lead to least surprising behaviors (PR [#7317](https://github.com/vatesfr/xen-orchestra/pull/7317)) - [VM/Advanced] Admin can change VM creator [Forum#7313](https://xcp-ng.org/forum/topic/7313/change-created-by-and-date-information) (PR [#7276](https://github.com/vatesfr/xen-orchestra/pull/7276)) +- [Host/Reboot] Confirmation modal to reboot an updated slave host if the master is not [#7059](https://github.com/vatesfr/xen-orchestra/issues/7059) (PR [#7293](https://github.com/vatesfr/xen-orchestra/pull/7293)) ### Bug fixes diff --git a/packages/xo-server/src/api/host.mjs b/packages/xo-server/src/api/host.mjs index ee8713a70a3..c90015baaa9 100644 --- a/packages/xo-server/src/api/host.mjs +++ b/packages/xo-server/src/api/host.mjs @@ -128,7 +128,25 @@ export async function restart({ bypassBlockedSuspend = force, bypassCurrentVmCheck = force, + bypassVersionCheck = force, }) { + + if (bypassVersionCheck) { + log.warn('host.restart with argument "bypassVersionCheck" set to true', { hostId: host.id }) + } else { + const pool = this.getObject(host.$poolId, 'pool') + const master = this.getObject(pool.master, 'host') + const hostRebootRequired = host.rebootRequired + if (hostRebootRequired && host.id !== master.id && host.version === master.version) { + throw incorrectState({ + actual: hostRebootRequired, + expected: false, + object: master.id, + property: 'rebootRequired', + }) + } + } + if (bypassBackupCheck) { log.warn('host.restart with argument "bypassBackupCheck" set to true', { hostId: host.id }) } else { @@ -165,6 +183,10 @@ restart.params = { type: 'boolean', default: false, }, + bypassVersionCheck: { + type: 'boolean', + optional: true, + }, } restart.resolve = { diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js index a55099f1cde..85012742ae5 100644 --- a/packages/xo-web/src/common/intl/messages.js +++ b/packages/xo-web/src/common/intl/messages.js @@ -967,6 +967,8 @@ const messages = { // ----- Host actions ------ disableMaintenanceMode: 'Disable maintenance mode', enableMaintenanceMode: 'Enable maintenance mode', + slaveHostMoreUpToDateThanMasterAfterRestart: + 'It appears that this host will be more up-to-date than the master ({master}) after the restart. This will result in the slave being unable to contact the pool master. Please update and restart your master node first.', startHostLabel: 'Start', stopHostLabel: 'Stop', enableHostLabel: 'Enable', @@ -979,6 +981,7 @@ const messages = { forceRebootHostLabel: 'Force reboot', forceSmartRebootHost: 'Smart Reboot failed because {nVms, number} VM{nVms, plural, one {} other {s}} ha{nVms, plural, one {s} other {ve}} {nVms, plural, one {its} other {their}} Suspend operation blocked. Would you like to force?', + restartAnyway: 'Restart anyway', rebootHostLabel: 'Reboot', noHostsAvailableErrorTitle: 'Error while restarting host', noHostsAvailableErrorMessage: diff --git a/packages/xo-web/src/common/xo/index.js b/packages/xo-web/src/common/xo/index.js index e1cc3222ddf..cfd5514fd29 100644 --- a/packages/xo-web/src/common/xo/index.js +++ b/packages/xo-web/src/common/xo/index.js @@ -29,7 +29,7 @@ import Icon from '../icon' import logError from '../log-error' import NewAuthTokenModal from './new-auth-token-modal' import RegisterProxyModal from './register-proxy-modal' -import renderXoItem, { renderXoItemFromId, Vm } from '../render-xo-item' +import renderXoItem, { Host, renderXoItemFromId, Vm } from '../render-xo-item' import store from 'store' import WarmMigrationModal from './warm-migration-modal' import { alert, chooseAction, confirm } from '../modal' @@ -900,6 +900,24 @@ const _restartHost = async ({ host, ...opts }) => { return _restartHost({ ...opts, host, bypassBackupCheck: true }) } + if (masterNeedsUpdate(error)) { + const state = store.getState() + const master = getObject(state, getObject(state, host.$pool).master) + await chooseAction({ + body: ( +

+ {' '} + {_('slaveHostMoreUpToDateThanMasterAfterRestart', { master: })} +

+ ), + buttons: [{ label: _('restartAnyway'), btnStyle: 'danger' }], + icon: 'alarm', + title: _('restartHostModalTitle'), + }) + + return _restartHost({ ...opts, host, bypassVersionCheck: true }) + } + if (noHostsAvailableErrCheck(error)) { alert(_('noHostsAvailableErrorTitle'), _('noHostsAvailableErrorMessage')) } @@ -926,6 +944,12 @@ const backupIsRunning = (err, poolId) => forbiddenOperation.is(err, { reason: `A backup is running on the pool: ${poolId}`, })) +const masterNeedsUpdate = err => + err !== undefined && + incorrectState.is(err, { + property: 'rebootRequired', + }) + const noHostsAvailableErrCheck = err => err !== undefined && noHostsAvailable.is(err) export const restartHosts = (hosts, force = false) => {