From 4bed50b4ede7d32d696abbc504fdb5809926baaf Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Thu, 12 May 2022 15:09:17 +0200 Subject: [PATCH] chore(xo-server): remove unused {export,import}DeltaVm functions --- packages/xo-server/src/api/test.mjs | 11 - packages/xo-server/src/xapi/index.mjs | 356 -------------------------- 2 files changed, 367 deletions(-) diff --git a/packages/xo-server/src/api/test.mjs b/packages/xo-server/src/api/test.mjs index 0d4843dd5..7e97b58ca 100644 --- a/packages/xo-server/src/api/test.mjs +++ b/packages/xo-server/src/api/test.mjs @@ -62,17 +62,6 @@ export async function copyVm({ vm, sr }) { console.log('import full VM...') await tgtXapi.VM_destroy((await tgtXapi.importVm(input, { srId: sr })).$ref) } - - // delta - { - console.log('export delta VM...') - const input = await srcXapi.exportDeltaVm(vm) - console.log('import delta VM...') - const { vm: copyVm } = await tgtXapi.importDeltaVm(input, { - srId: sr, - }) - await tgtXapi.VM_destroy(copyVm.$ref) - } } copyVm.description = 'export/import full/delta VM' diff --git a/packages/xo-server/src/xapi/index.mjs b/packages/xo-server/src/xapi/index.mjs index 36dfa403c..19efb4094 100644 --- a/packages/xo-server/src/xapi/index.mjs +++ b/packages/xo-server/src/xapi/index.mjs @@ -6,7 +6,6 @@ import filter from 'lodash/filter.js' import find from 'lodash/find.js' import flatMap from 'lodash/flatMap.js' import flatten from 'lodash/flatten.js' -import groupBy from 'lodash/groupBy.js' import identity from 'lodash/identity.js' import includes from 'lodash/includes.js' import isEmpty from 'lodash/isEmpty.js' @@ -14,9 +13,7 @@ import mapToArray from 'lodash/map.js' import mixin from '@xen-orchestra/mixin/legacy.js' import ms from 'ms' import noop from 'lodash/noop.js' -import omit from 'lodash/omit.js' import once from 'lodash/once.js' -import semver from 'semver' import tarStream from 'tar-stream' import uniq from 'lodash/uniq.js' import { asyncMap } from '@xen-orchestra/async-map' @@ -33,9 +30,7 @@ import { Xapi as XapiBase } from '@xen-orchestra/xapi' import { Ref } from 'xen-api' import { synchronized } from 'decorator-synchronized' -import ensureArray from '../_ensureArray.mjs' import fatfsBuffer, { init as fatfsBufferInit } from '../fatfs-buffer.mjs' -import { asyncMapValues } from '../_asyncMapValues.mjs' import { camelToSnakeCase, forEach, map, parseSize, pDelay, promisifyAll } from '../utils.mjs' import mixins from './mixins/index.mjs' @@ -65,11 +60,6 @@ class AggregateError extends Error { // =================================================================== -const TAG_BASE_DELTA = 'xo:base_delta' -export const TAG_COPY_SRC = 'xo:copy_of' - -// =================================================================== - export * from './utils.mjs' // VDI formats. (Raw is not available for delta vdi.) @@ -593,352 +583,6 @@ export default class Xapi extends XapiBase { return writeStream } - // Create a snapshot (if necessary) of the VM and returns a delta export - // object. - @cancelable - @decorateWith(deferrable) - async exportDeltaVm( - $defer, - $cancelToken, - vmId, - baseVmId, - { - bypassVdiChainsCheck = false, - - // Contains a vdi.$id set of vmId. - fullVdisRequired = [], - - disableBaseTags = false, - snapshotNameLabel = undefined, - } = {} - ) { - let vm = this.getObject(vmId) - - // do not use the snapshot name in the delta export - const exportedNameLabel = vm.name_label - if (!vm.is_a_snapshot) { - if (!bypassVdiChainsCheck) { - await this.VM_assertHealthyVdiChains(vm.$ref) - } - - vm = await this.getRecord( - 'VM', - await this.VM_snapshot(vm.$ref, { cancelToken: $cancelToken, name_label: snapshotNameLabel }) - ) - $defer.onFailure(() => this.VM_destroy(vm.$ref)) - } - - const baseVm = baseVmId && this.getObject(baseVmId) - - // refs of VM's VDIs → base's VDIs. - const baseVdis = {} - baseVm && - forEach(baseVm.$VBDs, vbd => { - let vdi, snapshotOf - if ( - (vdi = vbd.$VDI) && - (snapshotOf = vdi.$snapshot_of) && - !find(fullVdisRequired, id => snapshotOf.$id === id) - ) { - baseVdis[vdi.snapshot_of] = vdi - } - }) - - const streams = {} - const vdis = {} - const vbds = {} - forEach(vm.$VBDs, vbd => { - let vdi - if (vbd.type !== 'Disk' || !(vdi = vbd.$VDI)) { - // Ignore this VBD. - return - } - - // If the VDI name start with `[NOBAK]`, do not export it. - if (vdi.name_label.startsWith('[NOBAK]')) { - // FIXME: find a way to not create the VDI snapshot in the - // first time. - // - // The snapshot must not exist otherwise it could break the - // next export. - vdi.$destroy()::ignoreErrors() - return - } - - vbds[vbd.$ref] = vbd - - const vdiRef = vdi.$ref - if (vdiRef in vdis) { - // This VDI has already been managed. - return - } - - // Look for a snapshot of this vdi in the base VM. - const baseVdi = baseVdis[vdi.snapshot_of] - - vdis[vdiRef] = { - ...vdi, - other_config: { - ...vdi.other_config, - [TAG_BASE_DELTA]: baseVdi && !disableBaseTags ? baseVdi.uuid : undefined, - }, - $SR$uuid: vdi.$SR.uuid, - } - - streams[`${vdiRef}.vhd`] = () => this._exportVdi($cancelToken, vdi, baseVdi, VDI_FORMAT_VHD) - }) - - const suspendVdi = vm.$suspend_VDI - if (suspendVdi !== undefined) { - const vdiRef = suspendVdi.$ref - vdis[vdiRef] = { - ...suspendVdi, - $SR$uuid: suspendVdi.$SR.uuid, - } - streams[`${vdiRef}.vhd`] = () => this._exportVdi($cancelToken, suspendVdi, undefined, VDI_FORMAT_VHD) - } - - const vifs = {} - forEach(vm.$VIFs, vif => { - const network = vif.$network - vifs[vif.$ref] = { - ...vif, - $network$uuid: network.uuid, - $network$name_label: network.name_label, - // https://github.com/babel/babel-eslint/issues/595 - // eslint-disable-next-line no-undef - $network$VLAN: network.$PIFs[0]?.VLAN, - } - }) - - return Object.defineProperty( - { - version: '1.1.0', - vbds, - vdis, - vifs, - vm: { - ...vm, - name_label: exportedNameLabel, - other_config: - baseVm && !disableBaseTags - ? { - ...vm.other_config, - [TAG_BASE_DELTA]: baseVm.uuid, - } - : omit(vm.other_config, TAG_BASE_DELTA), - }, - }, - 'streams', - { - configurable: true, - value: streams, - writable: true, - } - ) - } - - @decorateWith(deferrable) - async importDeltaVm( - $defer, - delta, - { - deleteBase = false, - detectBase = true, - disableStartAfterImport = true, - mapVdisSrs = {}, - name_label = delta.vm.name_label, - srId = this.pool.default_SR, - } = {} - ) { - const { version } = delta - - if (!semver.satisfies(version, '^1')) { - throw new Error(`Unsupported delta backup version: ${version}`) - } - - let baseVm - if (detectBase) { - const remoteBaseVmUuid = delta.vm.other_config[TAG_BASE_DELTA] - if (remoteBaseVmUuid) { - baseVm = find(this.objects.all, obj => (obj = obj.other_config) && obj[TAG_COPY_SRC] === remoteBaseVmUuid) - - if (!baseVm) { - throw new Error(`could not find the base VM (copy of ${remoteBaseVmUuid})`) - } - } - } - - const baseVdis = {} - baseVm && - forEach(baseVm.$VBDs, vbd => { - const vdi = vbd.$VDI - if (vdi !== undefined) { - baseVdis[vbd.VDI] = vbd.$VDI - } - }) - - // 0. Create suspend_VDI - let suspendVdi - if (delta.vm.power_state === 'Suspended') { - const vdi = delta.vdis[delta.vm.suspend_VDI] - suspendVdi = await this.createVdi({ - ...vdi, - other_config: { - ...vdi.other_config, - [TAG_BASE_DELTA]: undefined, - [TAG_COPY_SRC]: vdi.uuid, - }, - sr: mapVdisSrs[vdi.uuid] || srId, - }) - $defer.onFailure.call(this, 'VDI_destroy', suspendVdi.$ref) - } - - // 1. Create the VMs. - const vm = await this._getOrWaitObject( - await this._createVmRecord( - { - ...delta.vm, - affinity: null, - blocked_operations: { - ...delta.vm.blocked_operations, - start: 'Importing…', - start_on: 'Importing…', - }, - ha_always_run: false, - is_a_template: false, - name_label: `[Importing…] ${name_label}`, - other_config: { - ...delta.vm.other_config, - [TAG_COPY_SRC]: delta.vm.uuid, - }, - }, - { suspend_VDI: suspendVdi?.$ref } - ) - ) - $defer.onFailure(() => this.VM_destroy(vm.$ref)) - - // 2. Delete all VBDs which may have been created by the import. - await asyncMapSettled(vm.$VBDs, vbd => this._deleteVbd(vbd))::ignoreErrors() - - // 3. Create VDIs & VBDs. - // - // TODO: move all VDIs creation before the VM and simplify the code - const vbds = groupBy(delta.vbds, 'VDI') - const newVdis = await asyncMapValues(delta.vdis, async (vdi, vdiRef) => { - let newVdi - - const remoteBaseVdiUuid = detectBase && vdi.other_config[TAG_BASE_DELTA] - if (remoteBaseVdiUuid) { - const baseVdi = find(baseVdis, vdi => vdi.other_config[TAG_COPY_SRC] === remoteBaseVdiUuid) - if (!baseVdi) { - throw new Error(`missing base VDI (copy of ${remoteBaseVdiUuid})`) - } - - newVdi = await this._getOrWaitObject(await this._cloneVdi(baseVdi)) - $defer.onFailure(() => newVdi.$destroy()) - - await newVdi.update_other_config(TAG_COPY_SRC, vdi.uuid) - } else if (vdiRef === delta.vm.suspend_VDI) { - // suspend VDI has been already created - newVdi = suspendVdi - } else { - newVdi = await this.createVdi({ - ...vdi, - other_config: { - ...vdi.other_config, - [TAG_BASE_DELTA]: undefined, - [TAG_COPY_SRC]: vdi.uuid, - }, - sr: mapVdisSrs[vdi.uuid] || srId, - }) - $defer.onFailure(() => newVdi.$destroy()) - } - - await asyncMapSettled(vbds[vdiRef], vbd => - this.createVbd({ - ...vbd, - vdi: newVdi, - vm, - }) - ) - - return newVdi - }) - - const networksByNameLabelByVlan = {} - let defaultNetwork - forEach(this.objects.all, object => { - if (object.$type === 'network') { - const pif = object.$PIFs[0] - if (pif === undefined) { - // ignore network - return - } - const vlan = pif.VLAN - const networksByNameLabel = networksByNameLabelByVlan[vlan] || (networksByNameLabelByVlan[vlan] = {}) - defaultNetwork = networksByNameLabel[object.name_label] = object - } - }) - - const { streams } = delta - - await Promise.all([ - // Import VDI contents. - asyncMapSettled(newVdis, async (vdi, id) => { - for (let stream of ensureArray(streams[`${id}.vhd`])) { - if (typeof stream === 'function') { - stream = await stream() - } - await this._importVdiContent(vdi, stream, VDI_FORMAT_VHD) - } - }), - - // Wait for VDI export tasks (if any) termination. - asyncMapSettled(streams, stream => stream.task), - - // Create VIFs. - asyncMapSettled(delta.vifs, vif => { - let network = vif.$network$uuid && this.getObject(vif.$network$uuid, undefined) - - if (network === undefined) { - const { $network$VLAN: vlan = -1 } = vif - const networksByNameLabel = networksByNameLabelByVlan[vlan] - if (networksByNameLabel !== undefined) { - network = networksByNameLabel[vif.$network$name_label] - if (network === undefined) { - network = networksByNameLabel[Object.keys(networksByNameLabel)[0]] - } - } else { - network = defaultNetwork - } - } - - if (network) { - return this._createVif(vm, network, vif) - } - }), - ]) - - if (deleteBase && baseVm) { - this.VM_destroy(baseVm.$ref)::ignoreErrors() - } - - await Promise.all([ - delta.vm.ha_always_run && vm.set_ha_always_run(true), - vm.set_name_label(name_label), - // FIXME: move - asyncMap(['start', 'start_on'], op => - vm.update_blocked_operations( - op, - disableStartAfterImport ? 'Do not start this VM, clone it if you want to use it.' : null - ) - ), - ]) - - return { vm } - } - async _migrateVmWithStorageMotion( vm, hostXapi,