More code in Xapi.
This commit is contained in:
parent
510897f672
commit
b55764db56
@ -637,7 +637,8 @@ exports.convert = convert
|
|||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
|
|
||||||
snapshot = $coroutine ({vm, name}) ->
|
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 = {
|
snapshot.params = {
|
||||||
id: { type: 'string' }
|
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
|
# TODO: integrate in xapi.js
|
||||||
export_ = $coroutine ({vm, compress}) ->
|
export_ = $coroutine ({vm, compress}) ->
|
||||||
compress ?= true
|
stream = $wait @getXAPI(vm).exportVm(vm.id, 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
$getFrom: url
|
$getFrom: $wait @registerHttpRequest(handleExport, {
|
||||||
|
stream,
|
||||||
|
$wait stream.response
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export_.params = {
|
export_.params = {
|
||||||
|
59
src/xapi.js
59
src/xapi.js
@ -211,8 +211,8 @@ export default class Xapi extends XapiBase {
|
|||||||
// Create a task.
|
// Create a task.
|
||||||
//
|
//
|
||||||
// Returns the task object from the Xapi.
|
// Returns the task object from the Xapi.
|
||||||
async _createTask (name, description = '') {
|
async _createTask (name = 'untitled task', description = '') {
|
||||||
const ref = await this.call('task.create', name, description)
|
const ref = await this.call('task.create', `[XO] ${name}`, description)
|
||||||
debug('task created: %s', name)
|
debug('task created: %s', name)
|
||||||
|
|
||||||
pFinally(this._watchTask(ref), () => {
|
pFinally(this._watchTask(ref), () => {
|
||||||
@ -393,7 +393,7 @@ export default class Xapi extends XapiBase {
|
|||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
async uploadPoolPatch (stream, length) {
|
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
|
// TODO: Update when xen-api >= 0.5
|
||||||
const poolMaster = this.objects.all[this._refsToUuids[this.pool.master]]
|
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)
|
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) {
|
async deleteVm (vmId, deleteDisks = false) {
|
||||||
const vm = this.getObject(vmId)
|
const vm = this.getObject(vmId)
|
||||||
|
|
||||||
@ -491,6 +500,50 @@ export default class Xapi extends XapiBase {
|
|||||||
await this.call('VM.destroy', vm.$ref)
|
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) {
|
async _doDockerAction (vmId, action, containerId) {
|
||||||
|
Loading…
Reference in New Issue
Block a user