Skip to content

Commit

Permalink
feat(xo-web/host): allow to force smartReboot
Browse files Browse the repository at this point in the history
  • Loading branch information
MathieuRA committed Oct 6, 2023
1 parent efb0dc7 commit 69e4821
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 35 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -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”
Expand All @@ -29,5 +31,6 @@

- @xen-orchestra/xapi minor
- xo-server minor
- xo-web minor

<!--packages-end-->
4 changes: 4 additions & 0 deletions packages/xo-web/src/common/intl/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
116 changes: 82 additions & 34 deletions packages/xo-web/src/common/xo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
incorrectState,
noHostsAvailable,
operationBlocked,
operationFailed,
vmLacksFeature,
} from 'xo-common/api-errors'

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion packages/xo-web/src/xo-app/host/tab-advanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => (
Expand Down

0 comments on commit 69e4821

Please sign in to comment.