Skip to content

Commit

Permalink
feat(xo-web/pool): ability to do a rolling pool reboot (#7243)
Browse files Browse the repository at this point in the history
Fixes #6885
See #7242
  • Loading branch information
MathieuRA authored Jan 26, 2024
1 parent c250cd9 commit 0c02510
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [Tags] Admin can create colored tags (PR [#7262](https://github.com/vatesfr/xen-orchestra/pull/7262))
- [Tags] Add tooltips on `xo:no-bak` and `xo:notify-on-snapshot` tags (PR [#7335](https://github.com/vatesfr/xen-orchestra/pull/7335))
- [VM] Custom notes [#5792](https://github.com/vatesfr/xen-orchestra/issues/5792) (PR [#7322](https://github.com/vatesfr/xen-orchestra/pull/7322))
- [Pool/Advanced] Ability to do a `Rolling Pool Reboot` (Enterprise plans) [#6885](https://github.com/vatesfr/xen-orchestra/issues/6885) (PRs [#7243](https://github.com/vatesfr/xen-orchestra/pull/7243), [#7242](https://github.com/vatesfr/xen-orchestra/pull/7242))

### Bug fixes

Expand Down
10 changes: 10 additions & 0 deletions packages/xo-web/src/common/intl/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,13 @@ const messages = {
poolSupportSourceUsers: 'XCP-ng Pro Support not available for source users',
poolSupportXcpngOnly: 'Only available for pool of XCP-ng hosts',
poolLicenseAlreadyFullySupported: 'The pool is already fully supported',
rollingPoolReboot: 'Rolling Pool Reboot',
rollingPoolRebootHaWarning: 'High Availability is enabled. This will automatically disable it during the reboot.',
rollingPoolRebootLoadBalancerWarning:
'Load Balancer plugin is running. This will automatically pause it during the reboot.',
rollingPoolRebootMessage:
'Are you sure you want to start a Rolling Pool Reboot? Running VMs will be migrated back and forth and this can take a while. Scheduled backups that may concern this pool will be disabled.',

setpoolMaster: 'Master',
syslogRemoteHost: 'Remote syslog host',
defaultMigrationNetwork: 'Default migration network',
Expand Down Expand Up @@ -2684,6 +2691,9 @@ const messages = {
proxyMultipleLicenses: 'This proxy has more than 1 license!',
proxyUnknownVm: 'Unknown proxy VM.',

// ----- plan -----
onlyAvailableToEnterprise: 'Only available to Enterprise users',

// ----- proxies -----
forgetProxyApplianceTitle: 'Forget prox{n, plural, one {y} other {ies}}',
forgetProxyApplianceMessage: 'Are you sure you want to forget {n, number} prox{n, plural, one {y} other {ies}}?',
Expand Down
27 changes: 27 additions & 0 deletions packages/xo-web/src/common/xo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
} from '../store/actions'

import parseNdJson from './_parseNdJson'
import RollingPoolRebootModal from './rolling-pool-reboot-modal'

// ===================================================================

Expand Down Expand Up @@ -816,6 +817,32 @@ export const setPoolMaster = host =>
}),
}).then(() => _call('pool.setPoolMaster', { host: resolveId(host) }), noop)

export const rollingPoolReboot = async pool => {
const poolId = resolveId(pool)
await confirm({
body: <RollingPoolRebootModal pool={poolId} />,
title: _('rollingPoolReboot'),
icon: 'pool-rolling-reboot',
})
try {
return await _call('pool.rollingReboot', { pool: poolId })
} catch (error) {
if (!forbiddenOperation.is(error)) {
throw error
}
await confirm({
body: (
<p className='text-warning'>
<Icon icon='alarm' /> {_('bypassBackupPoolModalMessage')}
</p>
),
title: _('rollingPoolReboot'),
icon: 'pool-rolling-reboot',
})
return _call('pool.rollingReboot', { pool: poolId, bypassBackupCheck: true })
}
}

// Host --------------------------------------------------------------

export const setSchedulerGranularity = (host, schedulerGranularity) =>
Expand Down
46 changes: 46 additions & 0 deletions packages/xo-web/src/common/xo/rolling-pool-reboot-modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import _ from 'intl'
import addSubscriptions from 'add-subscriptions'
import BaseComponent from 'base-component'
import Icon from 'icon'
import React from 'react'
import { connectStore } from 'utils'
import { createGetObjectsOfType } from 'selectors'

import { subscribePlugins } from '../'

@addSubscriptions(() => ({
plugins: subscribePlugins,
}))
@connectStore(
{
pools: createGetObjectsOfType('pool'),
},
{ withRef: true }
)
export default class RollingPoolRebootModal extends BaseComponent {
render() {
const pool = this.props.pools[this.props.pool]
const loadBalancerPlugin =
this.props.plugins !== undefined && this.props.plugins.find(plugin => plugin.name === 'load-balancer')

return (
<div>
<p>{_('rollingPoolRebootMessage')}</p>
{pool.HA_enabled && (
<p>
<em className='text-warning'>
<Icon icon='alarm' /> {_('rollingPoolRebootHaWarning')}
</em>
</p>
)}
{loadBalancerPlugin !== undefined && loadBalancerPlugin.loaded && (
<p>
<em className='text-warning'>
<Icon icon='alarm' /> {_('rollingPoolRebootLoadBalancerWarning')}
</em>
</p>
)}
</div>
)
}
}
4 changes: 4 additions & 0 deletions packages/xo-web/src/icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,10 @@
@extend .fa;
@extend .fa-angle-double-down;
}
&-rolling-reboot {
@extend .fa;
@extend .fa-circle-o-notch;
}
}

&-vif {
Expand Down
26 changes: 19 additions & 7 deletions packages/xo-web/src/xo-app/pool/tab-advanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
editPool,
installSupplementalPackOnAllHosts,
isSrWritable,
rollingPoolReboot,
setHostsMultipathing,
setPoolMaster,
setRemoteSyslogHost,
Expand All @@ -45,7 +46,7 @@ import { confirm } from '../../common/modal'
import { error } from '../../common/notification'
import { Host, Pool } from '../../common/render-xo-item'
import { isAdmin } from '../../common/selectors'
import { SOURCES, getXoaPlan } from '../../common/xoa-plans'
import { ENTERPRISE, SOURCES, getXoaPlan } from '../../common/xoa-plans'

const BindLicensesButton = decorate([
addSubscriptions({
Expand Down Expand Up @@ -266,22 +267,33 @@ export default class TabAdvanced extends Component {
const { enabled: hostsEnabledMultipathing, disabled: hostsDisabledMultipathing } = hostsByMultipathing
const { crashDumpSr } = pool
const crashDumpSrPredicate = this._getCrashDumpSrPredicate()
const isEnterprisePlan = getXoaPlan().value >= ENTERPRISE.value

return (
<div>
<Container>
{this._isNetboxPluginLoaded() && (
<Row>
<Col className='text-xs-right'>
<Row>
<Col className='text-xs-right'>
<TabButton
btnStyle='warning'
handler={rollingPoolReboot}
handlerParam={pool}
icon='pool-rolling-reboot'
labelId='rollingPoolReboot'
disabled={!isEnterprisePlan}
tooltip={!isEnterprisePlan ? _('onlyAvailableToEnterprise') : undefined}
/>
{this._isNetboxPluginLoaded() && (
<TabButton
btnStyle='primary'
handler={synchronizeNetbox}
handlerParam={[pool]}
icon='refresh'
labelId='syncNetbox'
/>
</Col>
</Row>
)}
)}
</Col>
</Row>
<Row>
<Col>
<h3>{_('xenSettingsLabel')}</h3>
Expand Down

0 comments on commit 0c02510

Please sign in to comment.