From 0dbe70f5affec1c13ea38cd3ce60aafabd29811f Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Thu, 12 Nov 2015 11:01:53 +0100 Subject: [PATCH] vm.copy() handles running VMs and compression can be disabled. --- src/api/vm.coffee | 20 +++++++++++++++---- src/xapi.js | 51 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/api/vm.coffee b/src/api/vm.coffee index fc01ea904..67d9df342 100644 --- a/src/api/vm.coffee +++ b/src/api/vm.coffee @@ -411,17 +411,29 @@ exports.clone = clone #--------------------------------------------------------------------- -copy = ({ vm, sr, name }) -> +copy = $coroutine ({ vm, sr, name: nameLabel }) -> if vm.$poolId == sr.$poolId - return @getXAPI(vm).copyVm(vm.id, sr.id, name).then((vm) -> vm.$id) + if vm.power_state is 'Running' + yield checkPermissionsForSnapshot.call(this, vm) - return @getXAPI(vm).remoteCopyVm(vm.id, @getXAPI(sr), sr.id, name).then((vm) -> vm.$id) + return @getXAPI(vm).copyVm(vm.id, sr.id, { + nameLabel + }).then((vm) -> vm.$id) + + return @getXAPI(vm).remoteCopyVm(vm.id, @getXAPI(sr), sr.id, { + compress, + nameLabel + }).then((vm) -> vm.$id) copy.params = { + compress: { + type: 'boolean', + optional: true + }, name: { type: 'string', optional: true - } + }, vm: { type: 'string' }, sr: { type: 'string' } } diff --git a/src/xapi.js b/src/xapi.js index 6bcdc068c..b68ee57a3 100644 --- a/src/xapi.js +++ b/src/xapi.js @@ -563,7 +563,26 @@ export default class Xapi extends XapiBase { // If a SR is specified, it will contains the copies of the VDIs, // otherwise they will use the SRs they are on. async _copyVm (vm, nameLabel = vm.nameLabel, sr = undefined) { - return await this.call('VM.copy', nameLabel, sr ? sr.$ref : '') + let snapshotRef + if (isVmRunning(vm)) { + snapshotRef = await this._snapshotVm(vm) + } + + try { + return await this.call( + 'VM.copy', + snapshotRef || vm.$ref, + nameLabel, + sr ? sr.$ref : '' + ) + } finally { + if (snapshotRef) { + await this.deleteVm( + await this._getOrWaitObject(snapshotRef), + true + ) + } + } } async _snapshotVm (vm, nameLabel = vm.name_label) { @@ -590,7 +609,9 @@ export default class Xapi extends XapiBase { return await this._getOrWaitObject(cloneRef) } - async copyVm (vmId, srId, nameLabel = undefined) { + async copyVm (vmId, srId, { + nameLabel = undefined + } = {}) { return await this._getOrWaitObject( await this._copyVm( this.getObject(vmId), @@ -600,9 +621,15 @@ export default class Xapi extends XapiBase { ) } - async remoteCopyVm (vmId, targetXapi, targetSrId, nameLabel = undefined) { + async remoteCopyVm (vmId, targetXapi, targetSrId, { + compress = true, + nameLabel = undefined + }) { const sr = targetXapi.getObject(targetSrId) - const stream = await this.exportVm(vmId) + const stream = await this.exportVm(vmId, { + compress, + onlyMetadata: false + }) const vm = await targetXapi._getOrWaitObject( await targetXapi._importVm(stream, stream.length, sr) @@ -750,9 +777,7 @@ export default class Xapi extends XapiBase { return vm } - async deleteVm (vmId, deleteDisks = false) { - const vm = this.getObject(vmId) - + async _deleteVm (vm, deleteDisks) { if (isVmRunning(vm)) { throw new Error('running VMs cannot be deleted') } @@ -773,6 +798,13 @@ export default class Xapi extends XapiBase { await this.call('VM.destroy', vm.$ref) } + async deleteVm (vmId, deleteDisks = false) { + return await this._deleteVm( + this.getObject(vmId), + deleteDisks + ) + } + getVmConsole (vmId) { const vm = this.getObject(vmId) @@ -785,7 +817,10 @@ export default class Xapi extends XapiBase { } // Returns a stream to the exported VM. - async exportVm (vmId, {compress = true, onlyMetadata = false} = {}) { + async exportVm (vmId, { + compress = true, + onlyMetadata = false + } = {}) { const vm = this.getObject(vmId) let host