Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(xo-web/pool): ability to do a rolling pool reboot #7243

Merged
merged 7 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading