More code in Xapi.
This commit is contained in:
parent
510897f672
commit
b55764db56
@ -637,7 +637,8 @@ exports.convert = convert
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
snapshot = $coroutine ({vm, name}) ->
|
||||
return $wait @getXAPI(vm).call 'VM.snapshot', vm.ref, name
|
||||
snapshot = $wait @getXAPI(vm).snapshotVm(vm.ref, name)
|
||||
return snapshot.$id
|
||||
|
||||
snapshot.params = {
|
||||
id: { type: 'string' }
|
||||
@ -768,68 +769,24 @@ exports.revert = revert
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
handleExport = (req, res, {stream, response: upstream}) ->
|
||||
res.writeHead(
|
||||
upstream.statusCode,
|
||||
upstream.statusMessage ? '',
|
||||
upstream.headers
|
||||
)
|
||||
stream.pipe(res)
|
||||
return
|
||||
|
||||
# TODO: integrate in xapi.js
|
||||
export_ = $coroutine ({vm, compress}) ->
|
||||
compress ?= true
|
||||
|
||||
xapi = @getXAPI vm
|
||||
|
||||
# if the VM is running, we can't export it directly
|
||||
# that's why we export the snapshot
|
||||
exportRef = if vm.power_state is 'Running'
|
||||
$debug 'VM is running, creating temp snapshot...'
|
||||
snapshotRef = $wait xapi.call 'VM.snapshot', vm.ref, vm.name_label
|
||||
# convert the template to a VM
|
||||
$wait xapi.call 'VM.set_is_a_template', snapshotRef, false
|
||||
|
||||
snapshotRef
|
||||
else
|
||||
vm.ref
|
||||
|
||||
host = @getObject vm.$container
|
||||
do (type = host.type) =>
|
||||
if type is 'pool'
|
||||
host = @getObject host.master, 'host'
|
||||
else unless type is 'host'
|
||||
throw new Error "unexpected type: got #{type} instead of host"
|
||||
|
||||
task = $wait xapi._createTask(
|
||||
'VM export via Xen Orchestra',
|
||||
'Export VM ' + vm.name_label
|
||||
)
|
||||
pFinally(
|
||||
xapi._watchTask(task)
|
||||
.then((result) ->
|
||||
$debug 'export succeeded'
|
||||
return
|
||||
)
|
||||
.catch((error) ->
|
||||
$debug 'export failed: %j', error
|
||||
return
|
||||
)
|
||||
,
|
||||
->
|
||||
if snapshotRef?
|
||||
$debug 'deleting temp snapshot...'
|
||||
xapi.deleteVm(snapshotRef, true)
|
||||
|
||||
return
|
||||
)
|
||||
|
||||
url = $wait @registerProxyRequest {
|
||||
method: 'get'
|
||||
hostname: host.address
|
||||
pathname: '/export/'
|
||||
query: {
|
||||
session_id: xapi.sessionId
|
||||
ref: exportRef
|
||||
task_id: task.$ref
|
||||
use_compression: if compress then 'true' else false
|
||||
}
|
||||
}
|
||||
stream = $wait @getXAPI(vm).exportVm(vm.id, compress ? true)
|
||||
|
||||
return {
|
||||
$getFrom: url
|
||||
$getFrom: $wait @registerHttpRequest(handleExport, {
|
||||
stream,
|
||||
$wait stream.response
|
||||
})
|
||||
}
|
||||
|
||||
export_.params = {
|
||||
|
59
src/xapi.js
59
src/xapi.js
@ -211,8 +211,8 @@ export default class Xapi extends XapiBase {
|
||||
// Create a task.
|
||||
//
|
||||
// Returns the task object from the Xapi.
|
||||
async _createTask (name, description = '') {
|
||||
const ref = await this.call('task.create', name, description)
|
||||
async _createTask (name = 'untitled task', description = '') {
|
||||
const ref = await this.call('task.create', `[XO] ${name}`, description)
|
||||
debug('task created: %s', name)
|
||||
|
||||
pFinally(this._watchTask(ref), () => {
|
||||
@ -393,7 +393,7 @@ export default class Xapi extends XapiBase {
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
async uploadPoolPatch (stream, length) {
|
||||
const task = await this._createTask('Patch upload from XO')
|
||||
const task = await this._createTask('Patch upload')
|
||||
|
||||
// TODO: Update when xen-api >= 0.5
|
||||
const poolMaster = this.objects.all[this._refsToUuids[this.pool.master]]
|
||||
@ -472,6 +472,15 @@ export default class Xapi extends XapiBase {
|
||||
await this.call('VDI.destroy', vdi.$ref)
|
||||
}
|
||||
|
||||
async _snapshotVm (vm, nameLabel = vm.name_label) {
|
||||
const ref = await this.call('VM.snapshot', vm.$ref, nameLabel)
|
||||
|
||||
// Convert the template to a VM.
|
||||
await this.call('VM.set_is_a_template', ref, false)
|
||||
|
||||
return ref
|
||||
}
|
||||
|
||||
async deleteVm (vmId, deleteDisks = false) {
|
||||
const vm = this.getObject(vmId)
|
||||
|
||||
@ -491,6 +500,50 @@ export default class Xapi extends XapiBase {
|
||||
await this.call('VM.destroy', vm.$ref)
|
||||
}
|
||||
|
||||
// Returns a stream to the exported VM.
|
||||
async exportVm (vmId, {compress = true} = {}) {
|
||||
const vm = this.getObject(vmId)
|
||||
|
||||
let host
|
||||
let snapshotRef
|
||||
if (isVmRunning(vm)) {
|
||||
host = this.getObject(vm.resident_on)
|
||||
snapshotRef = await this._snapshotVm(vm)
|
||||
} else {
|
||||
host = this.getObject(this.pool.master)
|
||||
}
|
||||
|
||||
const task = await this._createTask('VM Snapshot', vm.name_label)
|
||||
pFinally(this._watchTask(task), () => {
|
||||
if (snapshotRef) {
|
||||
this.deleteVm(snapshotRef, true)
|
||||
}
|
||||
})
|
||||
|
||||
const stream = got({
|
||||
hostname: host.address,
|
||||
path: '/export/'
|
||||
}, {
|
||||
query: {
|
||||
ref: snapshotRef || vm.$ref,
|
||||
session_id: this.sessionId,
|
||||
task_id: task.$ref,
|
||||
use_compression: compress ? 'true' : 'false'
|
||||
}
|
||||
})
|
||||
stream.response = eventToPromise(stream, 'response')
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
async snapshotVm (vmId) {
|
||||
return await this._getOrWaitObject(
|
||||
await this._snapshotVm(
|
||||
this.getObject(vmId)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
|
||||
async _doDockerAction (vmId, action, containerId) {
|
||||
|
Loading…
Reference in New Issue
Block a user