Skip to content

Commit

Permalink
feat(xo-web/backup/restore): ability to ignore VDIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Rajaa-BARHTAOUI committed Mar 23, 2022
1 parent 7e27e0b commit 1c012f4
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 12 deletions.
7 changes: 6 additions & 1 deletion @xen-orchestra/backups/ImportVmBackup.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ exports.ImportVmBackup = class ImportVmBackup {
} else {
assert.strictEqual(metadata.mode, 'delta')

backup = await adapter.readDeltaVmBackup(metadata)
const ignoredVdis = new Set(
Object.entries(this._importDeltaVmSettings.mapVdisSrs)
.filter(([_, srUuid]) => srUuid === null)
.map(([vdiUuid]) => vdiUuid)
)
backup = await adapter.readDeltaVmBackup(metadata, ignoredVdis)
Object.values(backup.streams).forEach(stream => watchStreamSize(stream, sizeContainer))
}

Expand Down
11 changes: 7 additions & 4 deletions @xen-orchestra/backups/RemoteAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const fromCallback = require('promise-toolbox/fromCallback')
const fromEvent = require('promise-toolbox/fromEvent')
const pDefer = require('promise-toolbox/defer')
const groupBy = require('lodash/groupBy.js')
const pickBy = require('lodash/pickBy.js')
const { dirname, join, normalize, resolve } = require('path')
const { createLogger } = require('@xen-orchestra/log')
const { Constants, createVhdDirectoryFromStream, openVhd, VhdAbstract, VhdDirectory, VhdSynthetic } = require('vhd-lib')
Expand Down Expand Up @@ -576,14 +577,16 @@ class RemoteAdapter {
return stream
}

async readDeltaVmBackup(metadata) {
async readDeltaVmBackup(metadata, ignoredVdis) {
const handler = this._handler
const { vbds, vdis, vhds, vifs, vm } = metadata
const { vbds, vhds, vifs, vm } = metadata
const dir = dirname(metadata._filename)

const vdis = ignoredVdis === undefined ? metadata.vdis : pickBy(metadata.vdis, vdi => !ignoredVdis.has(vdi.uuid))

const streams = {}
await asyncMapSettled(Object.keys(vdis), async id => {
streams[`${id}.vhd`] = await this._createSyntheticStream(handler, join(dir, vhds[id]))
await asyncMapSettled(Object.keys(vdis), async ref => {
streams[`${ref}.vhd`] = await this._createSyntheticStream(handler, join(dir, vhds[ref]))
})

return {
Expand Down
3 changes: 3 additions & 0 deletions @xen-orchestra/backups/_deltaVm.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ exports.TAG_COPY_SRC = TAG_COPY_SRC

const ensureArray = value => (value === undefined ? [] : Array.isArray(value) ? value : [value])
const resolveUuid = async (xapi, cache, uuid, type) => {
if (uuid == null) {
return uuid
}
let ref = cache.get(uuid)
if (ref === undefined) {
ref = await xapi.call(`${type}.get_by_uuid`, uuid)
Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [REST API] Expose networks, VBDs, VDIs and VIFs
- [Console] Supports host and VM consoles behind HTTP proxies [#6133](https://github.com/vatesfr/xen-orchestra/pull/6133)
- [Delta Backup/Restore] Ability to ignore some VDIs (PR [#6143](https://github.com/vatesfr/xen-orchestra/pull/6143))

### Bug fixes

Expand Down Expand Up @@ -42,4 +43,5 @@
- vhd-cli minor
- @xen-orchestra/backups minor
- @xen-orchestra/proxy minor
- xo-server patch
- xo-server minor
- xo-web minor
1 change: 1 addition & 0 deletions packages/xo-web/src/common/intl/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,7 @@ const messages = {
'This VM contains a duplicate MAC address or has the same MAC address as another running VM. Do you want to continue?',
vmsWithDuplicatedMacAddressesMessage:
'{nVms, number} VM{nVms, plural, one {} other {s}} contain{nVms, plural, one {s} other {}} duplicate MAC addresses or {nVms, plural, one {has} other {have}} the same MAC addresses as other running VMs. Do you want to continue?',
ignoreVdi: 'Ignore this VDI',

// ----- Servers -----
enableServerErrorTitle: 'Enable server',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import Collapse from 'collapse'
import Component from 'base-component'
import Icon from 'icon'
import PropTypes from 'prop-types'
import React from 'react'
import Tooltip from 'tooltip'
import { Container, Col } from 'grid'
import { isEmpty, map } from 'lodash'
import { isSrWritable } from 'xo'
import { Vdi } from 'render-xo-item'

import _ from '../../intl'
import SingleLineRow from '../../single-line-row'
import { Container, Col } from 'grid'
import { isSrWritable } from 'xo'
import { SelectSr } from '../../select-objects'

const Collapsible = ({ collapsible, children, ...props }) =>
Expand All @@ -29,6 +31,7 @@ Collapsible.propTypes = {

export default class ChooseSrForEachVdisModal extends Component {
static propTypes = {
ignorableVdis: PropTypes.bool,
mainSrPredicate: PropTypes.func,
onChange: PropTypes.func.isRequired,
srPredicate: PropTypes.func,
Expand All @@ -53,6 +56,7 @@ export default class ChooseSrForEachVdisModal extends Component {
render() {
const { props } = this
const {
ignorableVdis = false,
mainSrPredicate = isSrWritable,
placeholder,
srPredicate = mainSrPredicate,
Expand All @@ -64,7 +68,7 @@ export default class ChooseSrForEachVdisModal extends Component {
<div>
<SelectSr
onChange={this._onChangeMainSr}
placeholder={placeholder !== undefined ? placeholder : 'chooseSrForEachVdisModalMainSr'}
placeholder={placeholder !== undefined ? placeholder : _('chooseSrForEachVdisModalMainSr')}
predicate={mainSrPredicate}
required
value={mainSr}
Expand All @@ -84,7 +88,9 @@ export default class ChooseSrForEachVdisModal extends Component {
</SingleLineRow>
{map(vdis, vdi => (
<SingleLineRow key={vdi.uuid}>
<Col size={6}>{vdi.name !== undefined ? vdi.name : <Vdi id={vdi.id} showSize />}</Col>
<Col size={ignorableVdis ? 5 : 6}>
{vdi.name !== undefined ? vdi.name : <Vdi id={vdi.id} showSize />}
</Col>
<Col size={6}>
<SelectSr
onChange={sr =>
Expand All @@ -96,6 +102,22 @@ export default class ChooseSrForEachVdisModal extends Component {
value={mapVdisSrs !== undefined && mapVdisSrs[vdi.uuid]}
/>
</Col>
{ignorableVdis && (
<Col size={1}>
<Tooltip content={_('ignoreVdi')}>
<a
role='button'
onClick={() =>
this._onChange({
mapVdisSrs: { ...mapVdisSrs, [vdi.uuid]: null },
})
}
>
<Icon icon='remove' />
</a>
</Tooltip>
</Col>
)}
</SingleLineRow>
))}
<i>{_('optionalEntry')}</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ export default class RestoreBackupsModalBody extends Component {

_getDisks = createSelector(
() => this.state.backup,
backup =>
() => this.state.targetSrs.mapVdisSrs,
(backup, mapVdisSrs) =>
backup !== undefined && backup.mode === 'delta'
? backup.disks.reduce((vdis, vdi) => ({ ...vdis, [vdi.uuid]: vdi }), {})
? backup.disks.reduce(
(vdis, vdi) =>
mapVdisSrs !== undefined && mapVdisSrs[vdi.uuid] === null ? vdis : { ...vdis, [vdi.uuid]: vdi },
{}
)
: {}
)

Expand All @@ -40,6 +45,7 @@ export default class RestoreBackupsModalBody extends Component {
<div>
<div className='mb-1'>
<ChooseSrForEachVdisModal
ignorableVdis
onChange={this.linkState('targetSrs')}
placeholder={_('importBackupModalSelectSr')}
required
Expand Down

0 comments on commit 1c012f4

Please sign in to comment.