chore: remove VM metadata export/import (#631)
This commit is contained in:
parent
a6869638f5
commit
c8dc786008
@ -807,8 +807,8 @@ exports.rollingSnapshot = rollingSnapshot
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
backup = $coroutine ({vm, remoteId, file, compress, onlyMetadata}) ->
|
||||
yield @backupVm({vm, remoteId, file, compress, onlyMetadata})
|
||||
backup = $coroutine ({vm, remoteId, file, compress}) ->
|
||||
yield @backupVm({vm, remoteId, file, compress})
|
||||
|
||||
backup.permission = 'admin'
|
||||
|
||||
@ -817,7 +817,6 @@ backup.params = {
|
||||
remoteId: { type: 'string' }
|
||||
file: { type: 'string' }
|
||||
compress: { type: 'boolean', optional: true }
|
||||
onlyMetadata: { type: 'boolean', optional: true }
|
||||
}
|
||||
|
||||
backup.resolve = {
|
||||
@ -850,14 +849,13 @@ exports.importBackup = importBackup
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
rollingBackup = $coroutine ({vm, remoteId, tag, depth, retention = depth, compress, onlyMetadata}) ->
|
||||
rollingBackup = $coroutine ({vm, remoteId, tag, depth, retention = depth, compress}) ->
|
||||
return yield @rollingBackupVm({
|
||||
vm,
|
||||
remoteId,
|
||||
tag,
|
||||
retention,
|
||||
compress,
|
||||
onlyMetadata
|
||||
})
|
||||
|
||||
rollingBackup.permission = 'admin'
|
||||
@ -1014,10 +1012,9 @@ exports.revert = revert
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
handleExport = $coroutine (req, res, {xapi, id, compress, onlyMetadata}) ->
|
||||
handleExport = $coroutine (req, res, {xapi, id, compress}) ->
|
||||
stream = yield xapi.exportVm(id, {
|
||||
compress: compress ? true,
|
||||
onlyMetadata: onlyMetadata ? false
|
||||
})
|
||||
res.on('close', () ->
|
||||
stream.cancel()
|
||||
@ -1034,7 +1031,7 @@ handleExport = $coroutine (req, res, {xapi, id, compress, onlyMetadata}) ->
|
||||
return
|
||||
|
||||
# TODO: integrate in xapi.js
|
||||
export_ = $coroutine ({vm, compress, onlyMetadata}) ->
|
||||
export_ = $coroutine ({vm, compress}) ->
|
||||
if vm.power_state is 'Running'
|
||||
yield checkPermissionOnSrs.call(this, vm)
|
||||
|
||||
@ -1042,7 +1039,6 @@ export_ = $coroutine ({vm, compress, onlyMetadata}) ->
|
||||
xapi: @getXapi(vm),
|
||||
id: vm._xapiId,
|
||||
compress,
|
||||
onlyMetadata
|
||||
}
|
||||
|
||||
return {
|
||||
@ -1054,7 +1050,6 @@ export_ = $coroutine ({vm, compress, onlyMetadata}) ->
|
||||
export_.params = {
|
||||
vm: { type: 'string' }
|
||||
compress: { type: 'boolean', optional: true }
|
||||
onlyMetadata: { type: 'boolean', optional: true }
|
||||
}
|
||||
|
||||
export_.resolve = {
|
||||
|
@ -529,7 +529,6 @@ export default class Xapi extends XapiBase {
|
||||
const sr = targetXapi.getObject(targetSrId)
|
||||
let stream = await this.exportVm(vmId, {
|
||||
compress,
|
||||
onlyMetadata: false,
|
||||
})
|
||||
|
||||
const sizeStream = createSizeStream()
|
||||
@ -724,19 +723,17 @@ export default class Xapi extends XapiBase {
|
||||
// Returns a stream to the exported VM.
|
||||
async exportVm (vmId, {
|
||||
compress = true,
|
||||
onlyMetadata = false,
|
||||
} = {}) {
|
||||
const vm = this.getObject(vmId)
|
||||
|
||||
let host
|
||||
let snapshotRef
|
||||
// It's not needed to snapshot the VM to get the metadata
|
||||
if (isVmRunning(vm) && !onlyMetadata) {
|
||||
if (isVmRunning(vm)) {
|
||||
host = vm.$resident_on
|
||||
snapshotRef = (await this._snapshotVm(vm)).$ref
|
||||
}
|
||||
|
||||
const promise = this.getResource(onlyMetadata ? '/export_metadata/' : '/export/', {
|
||||
const promise = this.getResource('/export/', {
|
||||
host,
|
||||
query: {
|
||||
ref: snapshotRef || vm.$ref,
|
||||
@ -1199,11 +1196,9 @@ export default class Xapi extends XapiBase {
|
||||
})))
|
||||
}
|
||||
|
||||
async _importVm (stream, sr, onlyMetadata = false, onVmCreation = undefined) {
|
||||
async _importVm (stream, sr, onVmCreation = undefined) {
|
||||
const taskRef = await this.createTask('VM import')
|
||||
const query = {
|
||||
force: onlyMetadata,
|
||||
}
|
||||
const query = {}
|
||||
|
||||
let host
|
||||
if (sr != null) {
|
||||
@ -1219,7 +1214,7 @@ export default class Xapi extends XapiBase {
|
||||
|
||||
const vmRef = await this.putResource(
|
||||
stream,
|
||||
onlyMetadata ? '/import_metadata/' : '/import/',
|
||||
'/import/',
|
||||
{
|
||||
host,
|
||||
query,
|
||||
@ -1227,14 +1222,6 @@ export default class Xapi extends XapiBase {
|
||||
}
|
||||
).then(extractOpaqueRef)
|
||||
|
||||
// Importing a metadata archive of running VMs is currently
|
||||
// broken: its VBDs are incorrectly seen as attached.
|
||||
//
|
||||
// A call to VM.power_state_reset fixes this problem.
|
||||
if (onlyMetadata) {
|
||||
await this.call('VM.power_state_reset', vmRef)
|
||||
}
|
||||
|
||||
return vmRef
|
||||
}
|
||||
|
||||
@ -1325,7 +1312,6 @@ export default class Xapi extends XapiBase {
|
||||
// TODO: an XVA can contain multiple VMs
|
||||
async importVm (stream, {
|
||||
data,
|
||||
onlyMetadata = false,
|
||||
srId,
|
||||
type = 'xva',
|
||||
} = {}) {
|
||||
@ -1335,7 +1321,6 @@ export default class Xapi extends XapiBase {
|
||||
return /* await */ this._getOrWaitObject(await this._importVm(
|
||||
stream,
|
||||
sr,
|
||||
onlyMetadata
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,6 @@ import {
|
||||
safeDateParse,
|
||||
tmpDir,
|
||||
} from '../utils'
|
||||
import {
|
||||
VDI_FORMAT_VHD,
|
||||
} from '../xapi'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -513,84 +510,6 @@ export default class {
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
async _legacyImportDeltaVdiBackup (xapi, { vmId, handler, dir, vdiInfo }) {
|
||||
const vdi = await xapi.createVdi(vdiInfo.virtual_size, vdiInfo)
|
||||
const vdiId = vdi.$id
|
||||
|
||||
// dir = vm_delta_xxx
|
||||
// xoPath = vdi_xxx/timestamp_(full|delta).vhd
|
||||
// vdiDir = vdi_xxx
|
||||
const { xoPath } = vdiInfo
|
||||
const filePath = `${dir}/${xoPath}`
|
||||
const vdiDir = dirname(xoPath)
|
||||
|
||||
const backups = await this._listDeltaVdiDependencies(handler, filePath)
|
||||
|
||||
for (const backup of backups) {
|
||||
const stream = await handler.createReadStream(`${dir}/${vdiDir}/${backup}`)
|
||||
|
||||
await xapi.importVdiContent(vdiId, stream, {
|
||||
format: VDI_FORMAT_VHD,
|
||||
})
|
||||
}
|
||||
|
||||
return vdiId
|
||||
}
|
||||
|
||||
async _legacyImportDeltaVmBackup (xapi, { remoteId, handler, filePath, info, sr, mapVdisSrs = {} }) {
|
||||
// Import vm metadata.
|
||||
const vm = await (async () => {
|
||||
const stream = await handler.createReadStream(`${filePath}.xva`)
|
||||
return /* await */ xapi.importVm(stream, { onlyMetadata: true })
|
||||
})()
|
||||
|
||||
const vmName = vm.name_label
|
||||
const dir = dirname(filePath)
|
||||
|
||||
// Disable start and change the VM name label during import.
|
||||
await Promise.all([
|
||||
xapi.addForbiddenOperationToVm(vm.$id, 'start', 'Delta backup import...'),
|
||||
xapi._setObjectProperties(vm, { name_label: `[Importing...] ${vmName}` }),
|
||||
])
|
||||
|
||||
// Destroy vbds if necessary. Why ?
|
||||
// Because XenServer creates Vbds linked to the vdis of the backup vm if it exists.
|
||||
await xapi.destroyVbdsFromVm(vm.uuid)
|
||||
|
||||
// Import VDIs.
|
||||
const vdiIds = {}
|
||||
await Promise.all(
|
||||
mapToArray(
|
||||
info.vdis,
|
||||
async vdiInfo => {
|
||||
vdiInfo.sr = mapVdisSrs[vdiInfo.uuid] || sr._xapiId
|
||||
|
||||
const vdiId = await this._legacyImportDeltaVdiBackup(xapi, { vmId: vm.$id, handler, dir, vdiInfo })
|
||||
vdiIds[vdiInfo.uuid] = vdiId
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
await Promise.all(
|
||||
mapToArray(
|
||||
info.vbds,
|
||||
vbdInfo => {
|
||||
xapi.attachVdiToVm(vdiIds[vbdInfo.xoVdi], vm.$id, vbdInfo)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// Import done, reenable start and set real vm name.
|
||||
await Promise.all([
|
||||
xapi.removeForbiddenOperationFromVm(vm.$id, 'start'),
|
||||
xapi._setObjectProperties(vm, { name_label: vmName }),
|
||||
])
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
async _listVdiBackups (handler, dir) {
|
||||
let files
|
||||
|
||||
@ -763,14 +682,10 @@ export default class {
|
||||
const nOldBackups = backups.length - retention
|
||||
|
||||
if (nOldBackups > 0) {
|
||||
await asyncMap(backups.slice(0, nOldBackups), backup => Promise.all([
|
||||
await asyncMap(backups.slice(0, nOldBackups), backup =>
|
||||
// Remove json file.
|
||||
handler.unlink(`${dir}/${backup}`),
|
||||
|
||||
// Remove xva file.
|
||||
// Version 0.0.0 (Legacy) Delta Backup.
|
||||
handler.unlink(`${dir}/${getDeltaBackupNameWithoutExt(backup)}.xva`)::ignoreErrors(),
|
||||
]))
|
||||
handler.unlink(`${dir}/${backup}`)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -925,14 +840,9 @@ export default class {
|
||||
|
||||
const delta = JSON.parse(await handler.readFile(filePath))
|
||||
let vm
|
||||
const { version } = delta
|
||||
const { version = '0.0.0' } = delta
|
||||
|
||||
if (!version) {
|
||||
// Legacy import. (Version 0.0.0)
|
||||
vm = await this._legacyImportDeltaVmBackup(xapi, {
|
||||
remoteId, handler, filePath, info: delta, sr, mapVdisSrs,
|
||||
})
|
||||
} else if (versionSatisfies(delta.version, '^1')) {
|
||||
if (versionSatisfies(version, '^1')) {
|
||||
const basePath = dirname(filePath)
|
||||
const streams = delta.streams = {}
|
||||
|
||||
@ -967,13 +877,13 @@ export default class {
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
async backupVm ({vm, remoteId, file, compress, onlyMetadata}) {
|
||||
async backupVm ({vm, remoteId, file, compress}) {
|
||||
const handler = await this._xo.getRemoteHandler(remoteId)
|
||||
return this._backupVm(vm, handler, file, {compress, onlyMetadata})
|
||||
return this._backupVm(vm, handler, file, {compress})
|
||||
}
|
||||
|
||||
@deferrable
|
||||
async _backupVm ($defer, vm, handler, file, {compress, onlyMetadata}) {
|
||||
async _backupVm ($defer, vm, handler, file, {compress}) {
|
||||
const targetStream = await handler.createOutputStream(file)
|
||||
$defer.onFailure.call(handler, 'unlink', file)
|
||||
$defer.onFailure.call(targetStream, 'close')
|
||||
@ -982,7 +892,6 @@ export default class {
|
||||
|
||||
const sourceStream = await this._xo.getXapi(vm).exportVm(vm._xapiId, {
|
||||
compress,
|
||||
onlyMetadata: onlyMetadata || false,
|
||||
})
|
||||
|
||||
const sizeStream = createSizeStream()
|
||||
@ -998,7 +907,7 @@ export default class {
|
||||
}
|
||||
}
|
||||
|
||||
async rollingBackupVm ({vm, remoteId, tag, retention, compress, onlyMetadata}) {
|
||||
async rollingBackupVm ({vm, remoteId, tag, retention, compress}) {
|
||||
const transferStart = Date.now()
|
||||
const handler = await this._xo.getRemoteHandler(remoteId)
|
||||
|
||||
@ -1010,7 +919,7 @@ export default class {
|
||||
const date = safeDateFormat(new Date())
|
||||
const file = `${date}_${tag}_${vm.name_label}.xva`
|
||||
|
||||
const data = await this._backupVm(vm, handler, file, {compress, onlyMetadata})
|
||||
const data = await this._backupVm(vm, handler, file, {compress})
|
||||
await this._removeOldBackups(backups, handler, undefined, backups.length - (retention - 1))
|
||||
data.transferDuration = Date.now() - transferStart
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user