feat(xo-web/host): allow to force smartReboot
This commit is contained in:
parent
3bf6aae103
commit
549d9b70a9
@ -7,6 +7,8 @@
|
||||
|
||||
> Users must be able to say: “Nice enhancement, I'm eager to test it”
|
||||
|
||||
- [Host/Advanced] Allow to force _Smart reboot_ if some resident VMs have the suspend operation blocked [Forum#7136](https://xcp-ng.org/forum/topic/7136/suspending-vms-during-host-reboot/23) (PR [#7025](https://github.com/vatesfr/xen-orchestra/pull/7025))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
> Users must be able to say: “I had this issue, happy to know it's fixed”
|
||||
@ -29,5 +31,6 @@
|
||||
|
||||
- @xen-orchestra/xapi minor
|
||||
- xo-server minor
|
||||
- xo-web minor
|
||||
|
||||
<!--packages-end-->
|
||||
|
@ -963,9 +963,13 @@ const messages = {
|
||||
enableHostLabel: 'Enable',
|
||||
disableHostLabel: 'Disable',
|
||||
restartHostAgent: 'Restart toolstack',
|
||||
smartRebootBypassCurrentVmCheck:
|
||||
'As the XOA is hosted on the host that is scheduled for a reboot, it will also be restarted. Consequently, XO won\'t be able to resume VMs, and VMs with the "Protect from accidental shutdown" option enabled will not have this option reactivated automatically.',
|
||||
smartRebootHostLabel: 'Smart reboot',
|
||||
smartRebootHostTooltip: 'Suspend resident VMs, reboot host and resume VMs automatically',
|
||||
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?',
|
||||
rebootHostLabel: 'Reboot',
|
||||
noHostsAvailableErrorTitle: 'Error while restarting host',
|
||||
noHostsAvailableErrorMessage:
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
incorrectState,
|
||||
noHostsAvailable,
|
||||
operationBlocked,
|
||||
operationFailed,
|
||||
vmLacksFeature,
|
||||
} from 'xo-common/api-errors'
|
||||
|
||||
@ -821,42 +822,89 @@ export const setRemoteSyslogHost = (host, syslogDestination) =>
|
||||
export const setRemoteSyslogHosts = (hosts, syslogDestination) =>
|
||||
Promise.all(map(hosts, host => setRemoteSyslogHost(host, syslogDestination)))
|
||||
|
||||
export const restartHost = (host, force = false, suspendResidentVms = false) =>
|
||||
confirm({
|
||||
export const restartHost = async (
|
||||
host,
|
||||
force = false,
|
||||
suspendResidentVms = false,
|
||||
bypassBlockedSuspend = false,
|
||||
bypassCurrentVmCheck = false
|
||||
) => {
|
||||
await confirm({
|
||||
title: _('restartHostModalTitle'),
|
||||
body: _('restartHostModalMessage'),
|
||||
}).then(
|
||||
() =>
|
||||
_call('host.restart', { id: resolveId(host), force, suspendResidentVms })
|
||||
.catch(async error => {
|
||||
if (
|
||||
forbiddenOperation.is(error, {
|
||||
reason: `A backup may run on the pool: ${host.$poolId}`,
|
||||
}) ||
|
||||
forbiddenOperation.is(error, {
|
||||
reason: `A backup is running on the pool: ${host.$poolId}`,
|
||||
})
|
||||
) {
|
||||
await confirm({
|
||||
body: (
|
||||
<p className='text-warning'>
|
||||
<Icon icon='alarm' /> {_('bypassBackupHostModalMessage')}
|
||||
</p>
|
||||
),
|
||||
title: _('restartHostModalTitle'),
|
||||
})
|
||||
return _call('host.restart', { id: resolveId(host), force, suspendResidentVms, bypassBackupCheck: true })
|
||||
}
|
||||
throw error
|
||||
})
|
||||
.catch(error => {
|
||||
if (noHostsAvailable.is(error)) {
|
||||
alert(_('noHostsAvailableErrorTitle'), _('noHostsAvailableErrorMessage'))
|
||||
}
|
||||
throw error
|
||||
}),
|
||||
noop
|
||||
)
|
||||
})
|
||||
return _restartHost({ host, force, suspendResidentVms, bypassBlockedSuspend, bypassCurrentVmCheck })
|
||||
}
|
||||
|
||||
const _restartHost = async ({ host, ...opts }) => {
|
||||
opts = { ...opts, id: resolveId(host) }
|
||||
|
||||
try {
|
||||
await _call('host.restart', opts)
|
||||
} catch (error) {
|
||||
if (cantSuspend(error)) {
|
||||
await confirm({
|
||||
body: (
|
||||
<p>
|
||||
<Icon icon='alarm' /> {_('forceSmartRebootHost', { nVms: error.data.actual.length })}
|
||||
</p>
|
||||
),
|
||||
title: _('restartHostModalTitle'),
|
||||
})
|
||||
return _restartHost({ ...opts, host, bypassBlockedSuspend: true })
|
||||
}
|
||||
|
||||
if (xoaOnHost(error)) {
|
||||
await confirm({
|
||||
body: (
|
||||
<p>
|
||||
<Icon icon='alarm' /> {_('smartRebootBypassCurrentVmCheck')}
|
||||
</p>
|
||||
),
|
||||
title: _('restartHostModalTitle'),
|
||||
})
|
||||
return _restartHost({ ...opts, host, bypassCurrentVmCheck: true })
|
||||
}
|
||||
|
||||
if (backupIsRunning(error, host.$poolId)) {
|
||||
await confirm({
|
||||
body: (
|
||||
<p className='text-warning'>
|
||||
<Icon icon='alarm' /> {_('bypassBackupHostModalMessage')}
|
||||
</p>
|
||||
),
|
||||
title: _('restartHostModalTitle'),
|
||||
})
|
||||
return _restartHost({ ...opts, host, bypassBackupCheck: true })
|
||||
}
|
||||
|
||||
if (noHostsAvailableErrCheck(error)) {
|
||||
alert(_('noHostsAvailableErrorTitle'), _('noHostsAvailableErrorMessage'))
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Restart Host errors
|
||||
const cantSuspend = err =>
|
||||
err !== undefined &&
|
||||
incorrectState.is(err, {
|
||||
object: 'suspendBlocked',
|
||||
})
|
||||
const xoaOnHost = err =>
|
||||
err !== undefined &&
|
||||
operationFailed.is(err, {
|
||||
code: 'xoaOnHost',
|
||||
})
|
||||
const backupIsRunning = (err, poolId) =>
|
||||
err !== undefined &&
|
||||
(forbiddenOperation.is(err, {
|
||||
reason: `A backup may run on the pool: ${poolId}`,
|
||||
}) ||
|
||||
forbiddenOperation.is(err, {
|
||||
reason: `A backup is running on the pool: ${poolId}`,
|
||||
}))
|
||||
const noHostsAvailableErrCheck = err => err !== undefined && noHostsAvailable.is(err)
|
||||
|
||||
export const restartHosts = (hosts, force = false) => {
|
||||
const nHosts = size(hosts)
|
||||
|
@ -76,7 +76,7 @@ const downloadLogs = async uuid => {
|
||||
const forceReboot = host => restartHost(host, true)
|
||||
|
||||
const smartReboot = ALLOW_SMART_REBOOT
|
||||
? host => restartHost(host, false, true) // don't force, suspend resident VMs
|
||||
? host => restartHost(host, false, true, false, false) // don't force, suspend resident VMs, don't bypass blocked suspend, don't bypass current VM check
|
||||
: () => {}
|
||||
|
||||
const formatPack = ({ name, author, description, version }, key) => (
|
||||
|
Loading…
Reference in New Issue
Block a user