Skip to content

Commit

Permalink
feat(xo-web/VM/advanced): add button for warm migration (#6533)
Browse files Browse the repository at this point in the history
See #6549
  • Loading branch information
MathieuRA authored and ByScripts committed Dec 14, 2022
1 parent 44cba14 commit 93f519b
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [Settings/Users] Add `Remove` button to delete OTP of users from the admin panel [Forum#6521](https://xcp-ng.org/forum/topic/6521/remove-totp-on-a-user-account) (PR [#6541](https://github.com/vatesfr/xen-orchestra/pull/6541))
- [Plugin/transport-nagios] XO now reports backed up VMs invidually with the VM name label used as _host_ and backup job name used as _service_
- [Proxies] Ability to register an existing proxy (PR [#6556](https://github.com/vatesfr/xen-orchestra/pull/6556))
- [VM/Advanced] Add warm migration button (PR [#6533](https://github.com/vatesfr/xen-orchestra/pull/6533))

### Bug fixes

Expand Down
6 changes: 6 additions & 0 deletions packages/xo-web/src/common/intl/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const messages = {
alpha: 'Alpha',
creation: 'Creation',
description: 'Description',
deleteSourceVm: 'Delete source VM',
expiration: 'Expiration',
keyValue: '{key}: {value}',

Expand Down Expand Up @@ -108,6 +109,7 @@ const messages = {
replaceExistingCertificate: 'Replace existing certificate',
customFields: 'Custom fields',
addCustomField: 'Add custom field',
availableXoaPremium: 'Available in XOA Premium',
editCustomField: 'Edit custom field',
deleteCustomField: 'Delete custom field',
onlyAvailableXoaUsers: 'Only available to XOA users',
Expand Down Expand Up @@ -771,8 +773,12 @@ const messages = {
cloneVmLabel: 'Clone',
cleanVm: 'Clean VM directory',
fastCloneVmLabel: 'Fast clone',
startMigratedVm: 'Start the migrated VM',
vmConsoleLabel: 'Console',
vmExportUrlValidity: 'The URL is valid once for a short period of time.',
vmWarmMigration: 'Warm migration',
vmWarmMigrationProcessInfo:
'Warm migration process will first create a copy of the VM on the destination while the source VM is still running, then shutdown the source VM and send the changes that happened during the migration to the destination to minimize downtime.',
backupLabel: 'Backup',

// ----- SR general tab -----
Expand Down
17 changes: 17 additions & 0 deletions packages/xo-web/src/common/xo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ 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 WarmMigrationModal from './warm-migration-modal'
import renderXoItem, { renderXoItemFromId, Vm } from '../render-xo-item'
import store from 'store'
import WarmMigrationModal from './warm-migration-modal'
import { alert, chooseAction, confirm } from '../modal'
import { error, info, success } from '../notification'
import { getObject } from 'selectors'
Expand Down Expand Up @@ -1880,6 +1883,20 @@ export const shareVm = async (vm, resourceSet) =>
}),
}).then(() => editVm(vm, { share: true }), noop)

export const vmWarmMigration = async vm => {
const { sr, deleteSourceVm, startDestinationVm } = await confirm({
body: <WarmMigrationModal />,
title: _('vmWarmMigration'),
icon: 'vm-warm-migration',
})
return _call('vm.warmMigration', {
deleteSourceVm,
sr: resolveId(sr),
startDestinationVm,
vm: resolveId(vm),
})
}

// DISK ---------------------------------------------------------------

export const createDisk = (name, size, sr, { vm, bootable, mode, position }) =>
Expand Down
48 changes: 48 additions & 0 deletions packages/xo-web/src/common/xo/warm-migration-modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import _ from 'intl'
import Component from 'base-component'
import Icon from 'icon'
import React from 'react'
import SingleLineRow from 'single-line-row'
import { Col, Container } from 'grid'
import { SelectSr } from 'select-objects'
import { Toggle } from 'form'

export default class WarmMigrationModal extends Component {
state = {
deleteSourceVm: false,
sr: undefined,
startDestinationVm: false,
}
get value() {
return this.state
}

render() {
const { deleteSourceVm, sr, startDestinationVm } = this.state
return (
<Container>
<div className='text-info'>
<Icon icon='info' /> <i>{_('vmWarmMigrationProcessInfo')}</i>
</div>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('destinationSR')}</Col>
<Col size={6}>
<SelectSr onChange={this.linkState('sr')} value={sr} />
</Col>
</SingleLineRow>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('deleteSourceVm')}</Col>
<Col size={6}>
<Toggle onChange={this.toggleState('deleteSourceVm')} value={deleteSourceVm} />
</Col>
</SingleLineRow>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('startMigratedVm')}</Col>
<Col size={6}>
<Toggle onChange={this.toggleState('startDestinationVm')} value={startDestinationVm} />
</Col>
</SingleLineRow>
</Container>
)
}
}
4 changes: 4 additions & 0 deletions packages/xo-web/src/icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@
@extend .fa;
@extend .fa-list-alt;
}
&-warm-migration {
@extend .fa;
@extend .fa-fire;
}
}

// Generic states
Expand Down
12 changes: 12 additions & 0 deletions packages/xo-web/src/xo-app/vm/tab-advanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ import {
subscribeResourceSets,
subscribeUsers,
suspendVm,
vmWarmMigration,
XEN_DEFAULT_CPU_CAP,
XEN_DEFAULT_CPU_WEIGHT,
XEN_VIDEORAM_VALUES,
} from 'xo'
import { createGetObject, createGetObjectsOfType, createSelector, isAdmin } from 'selectors'
import { getXoaPlan, PREMIUM } from 'xoa-plans'
import { SelectSuspendSr } from 'select-suspend-sr'

import BootOrder from './boot-order'
Expand Down Expand Up @@ -450,6 +452,7 @@ export default class TabAdvanced extends Component {

render() {
const { container, isAdmin, vgpus, vm, vmPool } = this.props
const isWarmMigrationAvailable = getXoaPlan().value >= PREMIUM.value
return (
<Container>
<Row>
Expand Down Expand Up @@ -484,6 +487,15 @@ export default class TabAdvanced extends Component {
icon='vm-force-shutdown'
labelId='forceShutdownVmLabel'
/>
<TabButton
btnStyle='warning'
disabled={!isWarmMigrationAvailable}
handler={vmWarmMigration}
handlerParam={vm}
icon='vm-warm-migration'
labelId='vmWarmMigration'
tooltip={isWarmMigrationAvailable ? undefined : _('availableXoaPremium')}
/>
</span>
)}
{vm.power_state === 'Halted' && (
Expand Down

0 comments on commit 93f519b

Please sign in to comment.