No longer use fibers.

This commit is contained in:
Julien Fontanet 2015-06-05 18:34:04 +02:00
parent 934949c514
commit 5cd22b41d6
21 changed files with 340 additions and 666 deletions

View File

@ -42,6 +42,10 @@ gulp.task(function buildCoffee () {
.pipe(coffee({ .pipe(coffee({
bare: true bare: true
})) }))
// Necessary to correctly compile generators.
.pipe(babel())
.pipe(sourceMaps.write('.')) .pipe(sourceMaps.write('.'))
.pipe(gulp.dest(DIST_DIR)) .pipe(gulp.dest(DIST_DIR))
}) })

View File

@ -37,7 +37,6 @@
"debug": "^2.1.3", "debug": "^2.1.3",
"event-to-promise": "^0.3.2", "event-to-promise": "^0.3.2",
"exec-promise": "^0.5.1", "exec-promise": "^0.5.1",
"fibers": "~1.0.5",
"fs-promise": "^0.3.1", "fs-promise": "^0.3.1",
"got": "^3.2.0", "got": "^3.2.0",
"graceful-fs": "^3.0.6", "graceful-fs": "^3.0.6",

View File

@ -1,12 +1,11 @@
import {coroutine, wait} from '../fibers-utils'
import {parseSize} from '../utils' import {parseSize} from '../utils'
// =================================================================== // ===================================================================
export const create = coroutine(function ({name, size, sr}) { export async function create ({name, size, sr}) {
const xapi = this.getXAPI(sr) const xapi = this.getXAPI(sr)
const ref = wait(xapi.call('VDI.create', { const ref = await xapi.call('VDI.create', {
name_label: name, name_label: name,
other_config: {}, other_config: {},
read_only: false, read_only: false,
@ -14,10 +13,10 @@ export const create = coroutine(function ({name, size, sr}) {
SR: sr.ref, SR: sr.ref,
type: 'user', type: 'user',
virtual_size: String(parseSize(size)) virtual_size: String(parseSize(size))
})) })
return wait(xapi.call('VDI.get_record', ref)).uuid return (await xapi.call('VDI.get_record', ref)).uuid
}) }
create.description = 'create a new disk on a SR' create.description = 'create a new disk on a SR'

View File

@ -1,12 +1,12 @@
{$coroutine, $wait} = require '../fibers-utils'
$debug = (require 'debug') 'xo:api:vm' $debug = (require 'debug') 'xo:api:vm'
$request = require('bluebird').promisify(require('request'))
{parseXml} = require '../utils'
$forEach = require 'lodash.foreach'
$find = require 'lodash.find' $find = require 'lodash.find'
$findIndex = require 'lodash.findindex' $findIndex = require 'lodash.findindex'
startsWith = require 'lodash.startswith' $forEach = require 'lodash.foreach'
$request = require('bluebird').promisify(require('request'))
endsWith = require 'lodash.endswith' endsWith = require 'lodash.endswith'
startsWith = require 'lodash.startswith'
{coroutine: $coroutine} = require 'bluebird'
{parseXml} = require '../utils'
#===================================================================== #=====================================================================
@ -21,7 +21,7 @@ set = $coroutine (params) ->
} }
continue unless param of params continue unless param of params
$wait xapi.call "host.set_#{field}", host.ref, params[param] yield xapi.call "host.set_#{field}", host.ref, params[param]
return true return true
@ -48,8 +48,8 @@ exports.set = set
restart = $coroutine ({host}) -> restart = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'host.disable', host.ref yield xapi.call 'host.disable', host.ref
$wait xapi.call 'host.reboot', host.ref yield xapi.call 'host.reboot', host.ref
return true return true
@ -68,7 +68,7 @@ exports.restart = restart
restartAgent = $coroutine ({host}) -> restartAgent = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'host.restart_agent', host.ref yield xapi.call 'host.restart_agent', host.ref
return true return true
@ -88,7 +88,7 @@ exports.restart_agent = restartAgent
start = $coroutine ({host}) -> start = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'host.power_on', host.ref yield xapi.call 'host.power_on', host.ref
return true return true
@ -107,8 +107,8 @@ exports.start = start
stop = $coroutine ({host}) -> stop = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'host.disable', host.ref yield xapi.call 'host.disable', host.ref
$wait xapi.call 'host.shutdown', host.ref yield xapi.call 'host.shutdown', host.ref
return true return true
@ -127,7 +127,7 @@ exports.stop = stop
detach = $coroutine ({host}) -> detach = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'pool.eject', host.ref yield xapi.call 'pool.eject', host.ref
return true return true
@ -146,7 +146,7 @@ exports.detach = detach
enable = $coroutine ({host}) -> enable = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'host.enable', host.ref yield xapi.call 'host.enable', host.ref
return true return true
@ -165,7 +165,7 @@ exports.enable = enable
disable = $coroutine ({host}) -> disable = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
$wait xapi.call 'host.disable', host.ref yield xapi.call 'host.disable', host.ref
return true return true
@ -186,7 +186,7 @@ createNetwork = $coroutine ({host, name, description, pif, mtu, vlan}) ->
description = description ? 'Created with Xen Orchestra' description = description ? 'Created with Xen Orchestra'
network_ref = $wait xapi.call 'network.create', { network_ref = yield xapi.call 'network.create', {
name_label: name, name_label: name,
name_description: description, name_description: description,
MTU: mtu ? '1500' MTU: mtu ? '1500'
@ -196,7 +196,7 @@ createNetwork = $coroutine ({host, name, description, pif, mtu, vlan}) ->
if pif? if pif?
vlan = vlan ? '0' vlan = vlan ? '0'
pif = @getObject pif, 'PIF' pif = @getObject pif, 'PIF'
$wait xapi.call 'pool.create_VLAN_from_PIF', pif.ref, network_ref, vlan yield xapi.call 'pool.create_VLAN_from_PIF', pif.ref, network_ref, vlan
return true return true
@ -256,7 +256,7 @@ stats = $coroutine ({host}) ->
xapi = @getXAPI host xapi = @getXAPI host
[response, body] = $wait $request { [response, body] = yield $request {
method: 'get' method: 'get'
rejectUnauthorized: false rejectUnauthorized: false
url: 'https://'+host.address+'/host_rrd?session_id='+xapi.sessionId url: 'https://'+host.address+'/host_rrd?session_id='+xapi.sessionId

View File

@ -1,20 +0,0 @@
{$coroutine, $wait} = require '../fibers-utils'
#=====================================================================
delete_ = $coroutine ({message}) ->
xapi = @getXAPI message
$wait xapi.call 'message.destroy', message.ref
return true
delete_.params = {
id: { type: 'string' },
}
delete_.resolve = {
message: ['id', 'message', 'administrate']
}
exports.delete = delete_

12
src/api/message.js Normal file
View File

@ -0,0 +1,12 @@
async function delete_ ({message}) {
await this.getXAPI(message).call('message.destroy', message.ref)
}
export {delete_ as delete}
delete_.params = {
id: { type: 'string' }
}
delete_.resolve = {
message: ['id', 'message', 'administrate']
}

View File

@ -1,54 +0,0 @@
# FIXME: too low level, should be removed.
{$coroutine, $wait} = require '../fibers-utils'
#=====================================================================
# Delete
exports.delete = $coroutine ({PBD}) ->
xapi = @getXAPI PBD
# TODO: check if PBD is attached before
$wait xapi.call 'PBD.destroy', PBD.ref
return true
exports.delete.params = {
id: { type: 'string' }
}
exports.delete.resolve = {
PBD: ['id', 'PBD', 'administrate']
}
#=====================================================================
# Disconnect
exports.disconnect = $coroutine ({PBD}) ->
xapi = @getXAPI PBD
# TODO: check if PBD is attached before
$wait xapi.call 'PBD.unplug', PBD.ref
return true
exports.disconnect.params = {
id: { type: 'string' }
}
exports.disconnect.resolve = {
PBD: ['id', 'PBD', 'administrate']
}
#=====================================================================
# Connect
exports.connect = $coroutine ({PBD}) ->
xapi = @getXAPI PBD
# TODO: check if PBD is attached before
$wait xapi.call 'PBD.plug', PBD.ref
return true
exports.connect.params = {
id: { type: 'string' }
}
exports.connect.resolve = {
PBD: ['id', 'PBD', 'administrate']
}

50
src/api/pbd.js Normal file
View File

@ -0,0 +1,50 @@
// FIXME: too low level, should be removed.
// ===================================================================
// Delete
async function delete_ ({PBD}) {
// TODO: check if PBD is attached before
await this.getXAPI(PBD).call('PBD.destroy', PBD.ref)
}
export {delete_ as delete}
delete_.params = {
id: { type: 'string' }
}
delete_.resolve = {
PBD: ['id', 'PBD', 'administrate']
}
// ===================================================================
// Disconnect
export async function disconnect ({PBD}) {
// TODO: check if PBD is attached before
await this.getXAPI(PBD).call('PBD.unplug', PBD.ref)
}
disconnect.params = {
id: { type: 'string' }
}
disconnect.resolve = {
PBD: ['id', 'PBD', 'administrate']
}
// ===================================================================
// Connect
export async function connect ({PBD}) {
// TODO: check if PBD is attached before
await this.getXAPI(PBD).call('PBD.plug', PBD.ref)
}
connect.params = {
id: { type: 'string' }
}
connect.resolve = {
PBD: ['id', 'PBD', 'administrate']
}

View File

@ -1,51 +0,0 @@
{$coroutine, $wait} = require '../fibers-utils'
#=====================================================================
# Delete
exports.delete = $coroutine ({PIF}) ->
xapi = @getXAPI PIF
# TODO: check if PIF is attached before
$wait xapi.call 'PIF.destroy', PIF.ref
return true
exports.delete.params = {
id: { type: 'string' }
}
exports.delete.resolve = {
PIF: ['id', 'PIF', 'administrate']
}
#=====================================================================
# Disconnect
exports.disconnect = $coroutine ({PIF}) ->
xapi = @getXAPI PIF
# TODO: check if PIF is attached before
$wait xapi.call 'PIF.unplug', PIF.ref
return true
exports.disconnect.params = {
id: { type: 'string' }
}
exports.disconnect.resolve = {
PIF: ['id', 'PIF', 'administrate']
}
#=====================================================================
# Connect
exports.connect = $coroutine ({PIF}) ->
xapi = @getXAPI PIF
# TODO: check if PIF is attached before
$wait xapi.call 'PIF.plug', PIF.ref
return true
exports.connect.params = {
id: { type: 'string' }
}
exports.connect.resolve = {
PIF: ['id', 'PIF', 'administrate']
}

47
src/api/pif.js Normal file
View File

@ -0,0 +1,47 @@
// ===================================================================
// Delete
async function delete_ ({PIF}) {
// TODO: check if PIF is attached before
await this.getXAPI(PIF).call('PIF.destroy', PIF.ref)
}
export {delete_ as delete}
delete_.params = {
id: { type: 'string' }
}
delete_.resolve = {
PIF: ['id', 'PIF', 'administrate']
}
// ===================================================================
// Disconnect
export async function disconnect ({PIF}) {
// TODO: check if PIF is attached before
await this.getXAPI(PIF).call('PIF.unplug', PIF.ref)
}
disconnect.params = {
id: { type: 'string' }
}
disconnect.resolve = {
PIF: ['id', 'PIF', 'administrate']
}
// ===================================================================
// Connect
export async function connect ({PIF}) {
// TODO: check if PIF is attached before
await this.getXAPI(PIF).call('PIF.plug', PIF.ref)
}
connect.params = {
id: { type: 'string' }
}
connect.resolve = {
PIF: ['id', 'PIF', 'administrate']
}

View File

@ -2,23 +2,21 @@ import {deprecate} from 'util'
import {InvalidCredential, AlreadyAuthenticated} from '../api-errors' import {InvalidCredential, AlreadyAuthenticated} from '../api-errors'
import {coroutine, wait} from '../fibers-utils'
// =================================================================== // ===================================================================
export const signIn = coroutine(function (credentials) { export async function signIn (credentials) {
if (this.session.has('user_id')) { if (this.session.has('user_id')) {
throw new AlreadyAuthenticated() throw new AlreadyAuthenticated()
} }
const user = wait(this.authenticateUser(credentials)) const user = await this.authenticateUser(credentials)
if (!user) { if (!user) {
throw new InvalidCredential() throw new InvalidCredential()
} }
this.session.set('user_id', user.get('id')) this.session.set('user_id', user.get('id'))
return this.getUserPublicProperties(user) return this.getUserPublicProperties(user)
}) }
signIn.description = 'sign in' signIn.description = 'sign in'
@ -52,12 +50,12 @@ signOut.permission = ''
// ------------------------------------------------------------------- // -------------------------------------------------------------------
export const getUser = coroutine(function () { export async function getUser () {
const userId = this.session.get('user_id') const userId = this.session.get('user_id')
return userId === undefined ? return userId === undefined ?
null : null :
this.getUserPublicProperties(wait(this.getUser(userId))) this.getUserPublicProperties(await this.getUser(userId))
}) }
getUser.description = 'return the currently connected user' getUser.description = 'return the currently connected user'

View File

@ -1,5 +1,4 @@
import forEach from 'lodash.foreach' import forEach from 'lodash.foreach'
import {coroutine, wait} from '../fibers-utils'
import {ensureArray, parseXml} from '../utils' import {ensureArray, parseXml} from '../utils'
// =================================================================== // ===================================================================
@ -25,13 +24,9 @@ set.resolve = {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
export const scan = coroutine(function ({SR}) { export async function scan ({SR}) {
const xapi = this.getXAPI(SR) await this.getXAPI(SR).call('SR.scan', SR.ref)
}
wait(xapi.call('SR.scan', SR.ref))
return true
})
scan.params = { scan.params = {
id: { type: 'string' } id: { type: 'string' }
@ -44,13 +39,9 @@ scan.resolve = {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// TODO: find a way to call this "delete" and not destroy // TODO: find a way to call this "delete" and not destroy
export const destroy = coroutine(function ({SR}) { export async function destroy ({SR}) {
const xapi = this.getXAPI(SR) await this.getXAPI(SR).call('SR.destroy', SR.ref)
}
wait(xapi.call('SR.destroy', SR.ref))
return true
})
destroy.params = { destroy.params = {
id: { type: 'string' } id: { type: 'string' }
@ -62,13 +53,9 @@ destroy.resolve = {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
export const forget = coroutine(function ({SR}) { export async function forget ({SR}) {
const xapi = this.getXAPI(SR) await this.getXAPI(SR).call('SR.forget', SR.ref)
}
wait(xapi.call('SR.forget', SR.ref))
return true
})
forget.params = { forget.params = {
id: { type: 'string' } id: { type: 'string' }
@ -80,7 +67,7 @@ forget.resolve = {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
export const createIso = coroutine(function ({ export async function createIso ({
host, host,
nameLabel, nameLabel,
nameDescription, nameDescription,
@ -95,7 +82,7 @@ export const createIso = coroutine(function ({
// TODO: legacy will be removed in XAPI soon by FileSR // TODO: legacy will be removed in XAPI soon by FileSR
deviceConfig.legacy_mode = 'true' deviceConfig.legacy_mode = 'true'
} }
const srRef = wait(xapi.call( const srRef = await xapi.call(
'SR.create', 'SR.create',
host.ref, host.ref,
deviceConfig, deviceConfig,
@ -106,11 +93,11 @@ export const createIso = coroutine(function ({
'iso', // SR content type ISO 'iso', // SR content type ISO
true, true,
{} {}
)) )
const sr = wait(xapi.call('SR.get_record', srRef)) const sr = await xapi.call('SR.get_record', srRef)
return sr.uuid return sr.uuid
}) }
createIso.params = { createIso.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -128,7 +115,7 @@ createIso.resolve = {
// This functions creates a NFS SR // This functions creates a NFS SR
export const createNfs = coroutine(function ({ export async function createNfs ({
host, host,
nameLabel, nameLabel,
nameDescription, nameDescription,
@ -148,7 +135,7 @@ export const createNfs = coroutine(function ({
deviceConfig.nfsversion = nfsVersion deviceConfig.nfsversion = nfsVersion
} }
const srRef = wait(xapi.call( const srRef = await xapi.call(
'SR.create', 'SR.create',
host.ref, host.ref,
deviceConfig, deviceConfig,
@ -159,11 +146,11 @@ export const createNfs = coroutine(function ({
'user', // recommended by Citrix 'user', // recommended by Citrix
true, true,
{} {}
)) )
const sr = wait(xapi.call('SR.get_record', srRef)) const sr = await xapi.call('SR.get_record', srRef)
return sr.uuid return sr.uuid
}) }
createNfs.params = { createNfs.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -183,7 +170,7 @@ createNfs.resolve = {
// This functions creates a local LVM SR // This functions creates a local LVM SR
export const createLvm = coroutine(function ({ export async function createLvm ({
host, host,
nameLabel, nameLabel,
nameDescription, nameDescription,
@ -195,7 +182,7 @@ export const createLvm = coroutine(function ({
device device
} }
const srRef = wait(xapi.call( const srRef = await xapi.call(
'SR.create', 'SR.create',
host.ref, host.ref,
deviceConfig, deviceConfig,
@ -206,11 +193,11 @@ export const createLvm = coroutine(function ({
'user', // recommended by Citrix 'user', // recommended by Citrix
false, false,
{} {}
)) )
const sr = wait(xapi.call('SR.get_record', srRef)) const sr = await xapi.call('SR.get_record', srRef)
return sr.uuid return sr.uuid
}) }
createLvm.params = { createLvm.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -227,7 +214,7 @@ createLvm.resolve = {
// This function helps to detect all NFS shares (exports) on a NFS server // This function helps to detect all NFS shares (exports) on a NFS server
// Return a table of exports with their paths and ACLs // Return a table of exports with their paths and ACLs
export const probeNfs = coroutine(function ({ export async function probeNfs ({
host, host,
server server
}) { }) {
@ -240,13 +227,13 @@ export const probeNfs = coroutine(function ({
let xml let xml
try { try {
wait(xapi.call( await xapi.call(
'SR.probe', 'SR.probe',
host.ref, host.ref,
deviceConfig, deviceConfig,
'nfs', 'nfs',
{} {}
)) )
throw new Error('the call above should have thrown an error') throw new Error('the call above should have thrown an error')
} catch (error) { } catch (error) {
@ -266,7 +253,7 @@ export const probeNfs = coroutine(function ({
}) })
return nfsExports return nfsExports
}) }
probeNfs.params = { probeNfs.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -282,7 +269,7 @@ probeNfs.resolve = {
// This functions creates a iSCSI SR // This functions creates a iSCSI SR
export const createIscsi = coroutine(function ({ export async function createIscsi ({
host, host,
nameLabel, nameLabel,
nameDescription, nameDescription,
@ -313,7 +300,7 @@ export const createIscsi = coroutine(function ({
deviceConfig.port = port deviceConfig.port = port
} }
const srRef = wait(xapi.call( const srRef = await xapi.call(
'SR.create', 'SR.create',
host.ref, host.ref,
deviceConfig, deviceConfig,
@ -324,11 +311,11 @@ export const createIscsi = coroutine(function ({
'user', // recommended by Citrix 'user', // recommended by Citrix
true, true,
{} {}
)) )
const sr = wait(xapi.call('SR.get_record', srRef)) const sr = await xapi.call('SR.get_record', srRef)
return sr.uuid return sr.uuid
}) }
createIscsi.params = { createIscsi.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -350,7 +337,7 @@ createIscsi.resolve = {
// This function helps to detect all iSCSI IQN on a Target (iSCSI "server") // This function helps to detect all iSCSI IQN on a Target (iSCSI "server")
// Return a table of IQN or empty table if no iSCSI connection to the target // Return a table of IQN or empty table if no iSCSI connection to the target
export const probeIscsiIqns = coroutine(function ({ export async function probeIscsiIqns ({
host, host,
target: targetIp, target: targetIp,
port, port,
@ -377,13 +364,13 @@ export const probeIscsiIqns = coroutine(function ({
let xml let xml
try { try {
wait(xapi.call( await xapi.call(
'SR.probe', 'SR.probe',
host.ref, host.ref,
deviceConfig, deviceConfig,
'lvmoiscsi', 'lvmoiscsi',
{} {}
)) )
throw new Error('the call above should have thrown an error') throw new Error('the call above should have thrown an error')
} catch (error) { } catch (error) {
@ -409,7 +396,7 @@ export const probeIscsiIqns = coroutine(function ({
}) })
return targets return targets
}) }
probeIscsiIqns.params = { probeIscsiIqns.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -426,7 +413,7 @@ probeIscsiIqns.resolve = {
// This function helps to detect all iSCSI ID and LUNs on a Target // This function helps to detect all iSCSI ID and LUNs on a Target
// It will return a LUN table // It will return a LUN table
export const probeIscsiLuns = coroutine(function ({ export async function probeIscsiLuns ({
host, host,
target: targetIp, target: targetIp,
port, port,
@ -455,13 +442,13 @@ export const probeIscsiLuns = coroutine(function ({
let xml let xml
try { try {
wait(xapi.call( await xapi.call(
'SR.probe', 'SR.probe',
host.ref, host.ref,
deviceConfig, deviceConfig,
'lvmoiscsi', 'lvmoiscsi',
{} {}
)) )
throw new Error('the call above should have thrown an error') throw new Error('the call above should have thrown an error')
} catch (error) { } catch (error) {
@ -484,7 +471,7 @@ export const probeIscsiLuns = coroutine(function ({
}) })
return luns return luns
}) }
probeIscsiLuns.params = { probeIscsiLuns.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -503,7 +490,7 @@ probeIscsiLuns.resolve = {
// This function helps to detect if this target already exists in XAPI // This function helps to detect if this target already exists in XAPI
// It returns a table of SR UUID, empty if no existing connections // It returns a table of SR UUID, empty if no existing connections
export const probeIscsiExists = coroutine(function ({ export async function probeIscsiExists ({
host, host,
target: targetIp, target: targetIp,
port, port,
@ -531,7 +518,7 @@ export const probeIscsiExists = coroutine(function ({
deviceConfig.port = port deviceConfig.port = port
} }
const xml = parseXml(wait(xapi.call('SR.probe', host.ref, deviceConfig, 'lvmoiscsi', {}))) const xml = parseXml(await xapi.call('SR.probe', host.ref, deviceConfig, 'lvmoiscsi', {}))
const srs = [] const srs = []
forEach(ensureArray(xml['SRlist'].SR), sr => { forEach(ensureArray(xml['SRlist'].SR), sr => {
@ -540,7 +527,7 @@ export const probeIscsiExists = coroutine(function ({
}) })
return srs return srs
}) }
probeIscsiExists.params = { probeIscsiExists.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -560,7 +547,7 @@ probeIscsiExists.resolve = {
// This function helps to detect if this NFS SR already exists in XAPI // This function helps to detect if this NFS SR already exists in XAPI
// It returns a table of SR UUID, empty if no existing connections // It returns a table of SR UUID, empty if no existing connections
export const probeNfsExists = coroutine(function ({ export async function probeNfsExists ({
host, host,
server, server,
serverPath, serverPath,
@ -572,7 +559,7 @@ export const probeNfsExists = coroutine(function ({
serverpath: serverPath serverpath: serverPath
} }
const xml = parseXml(wait(xapi.call('SR.probe', host.ref, deviceConfig, 'nfs', {}))) const xml = parseXml(await xapi.call('SR.probe', host.ref, deviceConfig, 'nfs', {}))
const srs = [] const srs = []
@ -582,7 +569,7 @@ export const probeNfsExists = coroutine(function ({
}) })
return srs return srs
}) }
probeNfsExists.params = { probeNfsExists.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -597,7 +584,7 @@ probeNfsExists.resolve = {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// This function helps to reattach a forgotten NFS/iSCSI SR // This function helps to reattach a forgotten NFS/iSCSI SR
export const reattach = coroutine(function ({ export async function reattach ({
host, host,
uuid, uuid,
nameLabel, nameLabel,
@ -610,7 +597,7 @@ export const reattach = coroutine(function ({
type = 'lvmoiscsi' // the internal XAPI name type = 'lvmoiscsi' // the internal XAPI name
} }
const srRef = wait(xapi.call( const srRef = await xapi.call(
'SR.introduce', 'SR.introduce',
uuid, uuid,
nameLabel, nameLabel,
@ -619,11 +606,11 @@ export const reattach = coroutine(function ({
'user', 'user',
true, true,
{} {}
)) )
const sr = wait(xapi.call('SR.get_record', srRef)) const sr = await xapi.call('SR.get_record', srRef)
return sr.uuid return sr.uuid
}) }
reattach.params = { reattach.params = {
host: { type: 'string' }, host: { type: 'string' },
@ -640,7 +627,7 @@ reattach.resolve = {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// This function helps to reattach a forgotten ISO SR // This function helps to reattach a forgotten ISO SR
export const reattachIso = coroutine(function ({ export async function reattachIso ({
host, host,
uuid, uuid,
nameLabel, nameLabel,
@ -653,7 +640,7 @@ export const reattachIso = coroutine(function ({
type = 'lvmoiscsi' // the internal XAPI name type = 'lvmoiscsi' // the internal XAPI name
} }
const srRef = wait(xapi.call( const srRef = await xapi.call(
'SR.introduce', 'SR.introduce',
uuid, uuid,
nameLabel, nameLabel,
@ -662,11 +649,11 @@ export const reattachIso = coroutine(function ({
'iso', 'iso',
true, true,
{} {}
)) )
const sr = wait(xapi.call('SR.get_record', srRef)) const sr = await xapi.call('SR.get_record', srRef)
return sr.uuid return sr.uuid
}) }
reattachIso.params = { reattachIso.params = {
host: { type: 'string' }, host: { type: 'string' },

View File

@ -1,38 +0,0 @@
{$coroutine, $wait} = require '../fibers-utils'
#=====================================================================
cancel = $coroutine ({task}) ->
xapi = @getXAPI task
$wait xapi.call 'task.cancel', task.ref
return true
cancel.params = {
id: { type: 'string' },
}
cancel.resolve = {
task: ['id', 'task', 'administrate'],
}
exports.cancel = cancel
#---------------------------------------------------------------------
destroy = $coroutine ({task}) ->
xapi = @getXAPI task
$wait xapi.call 'task.destroy', task.ref
return true
destroy.params = {
id: { type: 'string' },
}
destroy.resolve = {
task: ['id', 'task', 'administrate'],
}
exports.destroy = destroy

25
src/api/task.js Normal file
View File

@ -0,0 +1,25 @@
export async function cancel ({task}) {
await this.getXAPI(task).call('task.cancel', task.ref)
}
cancel.params = {
id: { type: 'string' }
}
cancel.resolve = {
task: ['id', 'task', 'administrate']
}
// -------------------------------------------------------------------
export async function destroy ({task}) {
await this.getXAPI(task).call('task.destroy', task.ref)
}
destroy.params = {
id: { type: 'string' }
}
destroy.resolve = {
task: ['id', 'task', 'administrate']
}

View File

@ -1,6 +1,6 @@
# FIXME: too low level, should be removed. # FIXME: too low level, should be removed.
{$coroutine, $wait} = require '../fibers-utils' {coroutine: $coroutine} = require 'bluebird'
#===================================================================== #=====================================================================
@ -8,7 +8,7 @@ delete_ = $coroutine ({vbd}) ->
xapi = @getXAPI vbd xapi = @getXAPI vbd
# TODO: check if VBD is attached before # TODO: check if VBD is attached before
$wait xapi.call 'VBD.destroy', vbd.ref yield xapi.call 'VBD.destroy', vbd.ref
return true return true
@ -28,7 +28,7 @@ disconnect = $coroutine ({vbd}) ->
xapi = @getXAPI vbd xapi = @getXAPI vbd
# TODO: check if VBD is attached before # TODO: check if VBD is attached before
$wait xapi.call 'VBD.unplug_force', vbd.ref yield xapi.call 'VBD.unplug_force', vbd.ref
return true return true
@ -48,7 +48,7 @@ connect = $coroutine ({vbd}) ->
xapi = @getXAPI vbd xapi = @getXAPI vbd
# TODO: check if VBD is attached before # TODO: check if VBD is attached before
$wait xapi.call 'VBD.plug', vbd.ref yield xapi.call 'VBD.plug', vbd.ref
return true return true
@ -72,7 +72,7 @@ set = $coroutine (params) ->
# VBD position # VBD position
if 'position' of params if 'position' of params
$wait xapi.call 'VBD.set_userdevice', ref, params.position yield xapi.call 'VBD.set_userdevice', ref, params.position
set.params = { set.params = {
# Identifier of the VBD to update. # Identifier of the VBD to update.

View File

@ -4,7 +4,7 @@ $isArray = require 'lodash.isarray'
#--------------------------------------------------------------------- #---------------------------------------------------------------------
{$coroutine, $wait} = require '../fibers-utils' {coroutine: $coroutine} = require 'bluebird'
#===================================================================== #=====================================================================
@ -12,7 +12,7 @@ delete_ = $coroutine ({vdi}) ->
xapi = @getXAPI vdi xapi = @getXAPI vdi
# TODO: check if VDI is attached before # TODO: check if VDI is attached before
$wait xapi.call 'VDI.destroy', vdi.ref yield xapi.call 'VDI.destroy', vdi.ref
return true return true
@ -45,7 +45,7 @@ set = $coroutine (params) ->
"cannot set new size below the current size (#{vdi.size})" "cannot set new size below the current size (#{vdi.size})"
) )
$wait xapi.call 'VDI.resize_online', ref, "#{size}" yield xapi.call 'VDI.resize_online', ref, "#{size}"
# Other fields. # Other fields.
for param, fields of { for param, fields of {
@ -55,7 +55,7 @@ set = $coroutine (params) ->
continue unless param of params continue unless param of params
for field in (if $isArray fields then fields else [fields]) for field in (if $isArray fields then fields else [fields])
$wait xapi.call "VDI.set_#{field}", ref, "#{params[param]}" yield xapi.call "VDI.set_#{field}", ref, "#{params[param]}"
return true return true
@ -83,7 +83,7 @@ migrate = $coroutine ({vdi, sr}) ->
xapi = @getXAPI vdi xapi = @getXAPI vdi
# TODO: check if VDI is attached before # TODO: check if VDI is attached before
$wait xapi.call 'VDI.pool_migrate', vdi.ref, sr.ref, {} yield xapi.call 'VDI.pool_migrate', vdi.ref, sr.ref, {}
return true return true

View File

@ -1,61 +0,0 @@
{$coroutine, $wait} = require '../fibers-utils'
#=====================================================================
delete_ = $coroutine ({vif}) ->
xapi = @getXAPI vif
# TODO: check if VIF is attached before
$wait xapi.call 'VIF.destroy', vif.ref
return true
delete_.params = {
id: { type: 'string' }
}
delete_.resolve = {
vif: ['id', 'VIF', 'administrate']
}
exports.delete = delete_
#---------------------------------------------------------------------
disconnect = $coroutine ({vif}) ->
xapi = @getXAPI vif
# TODO: check if VIF is attached before
$wait xapi.call 'VIF.unplug_force', vif.ref
return true
disconnect.params = {
id: { type: 'string' }
}
disconnect.resolve = {
vif: ['id', 'VIF', 'operate']
}
exports.disconnect = disconnect
#---------------------------------------------------------------------
connect = $coroutine ({vif}) ->
xapi = @getXAPI vif
# TODO: check if VIF is attached before
$wait xapi.call 'VIF.plug', vif.ref
return true
connect.params = {
id: { type: 'string' }
}
connect.resolve = {
vif: ['id', 'VIF', 'operate']
}
exports.connect = connect

43
src/api/vif.js Normal file
View File

@ -0,0 +1,43 @@
async function delete_ ({vif}) {
// TODO: check if VIF is attached before
await this.getXAPI(vif).call('VIF.destroy', vif.ref)
}
export {delete_ as delete}
delete_.params = {
id: { type: 'string' }
}
delete_.resolve = {
vif: ['id', 'VIF', 'administrate']
}
// -------------------------------------------------------------------
export async function disconnect ({vif}) {
// TODO: check if VIF is attached before
await this.getXAPI(vif).call('VIF.unplug_force', vif.ref)
}
disconnect.params = {
id: { type: 'string' }
}
disconnect.resolve = {
vif: ['id', 'VIF', 'operate']
}
// -------------------------------------------------------------------
export async function connect ({vif}) {
// TODO: check if VIF is attached before
await this.getXAPI(vif).call('VIF.plug', vif.ref)
}
connect.params = {
id: { type: 'string' }
}
connect.resolve = {
vif: ['id', 'VIF', 'operate']
}

View File

@ -1,14 +1,14 @@
$debug = (require 'debug') 'xo:api:vm' $debug = (require 'debug') 'xo:api:vm'
$findIndex = require 'lodash.findindex'
$findWhere = require 'lodash.find' $findWhere = require 'lodash.find'
$result = require 'lodash.result'
$forEach = require 'lodash.foreach' $forEach = require 'lodash.foreach'
$isArray = require 'lodash.isarray' $isArray = require 'lodash.isarray'
$findIndex = require 'lodash.findindex'
startsWith = require 'lodash.startswith'
endsWith = require 'lodash.endswith'
$request = require('bluebird').promisify(require('request')) $request = require('bluebird').promisify(require('request'))
$result = require 'lodash.result'
endsWith = require 'lodash.endswith'
startsWith = require 'lodash.startswith'
{coroutine: $coroutine} = require 'bluebird'
{$coroutine, $wait} = require '../fibers-utils'
{ {
formatXml: $js2xml, formatXml: $js2xml,
parseXml, parseXml,
@ -38,7 +38,7 @@ create = $coroutine ({
xapi = @getXAPI template xapi = @getXAPI template
# Clones the VM from the template. # Clones the VM from the template.
ref = $wait xapi.call 'VM.clone', template.ref, name_label ref = yield xapi.call 'VM.clone', template.ref, name_label
# TODO: if there is an error from now, removes this VM. # TODO: if there is an error from now, removes this VM.
@ -51,7 +51,7 @@ create = $coroutine ({
$forEach VIFs, (VIF) => $forEach VIFs, (VIF) =>
network = @getObject VIF.network, 'network' network = @getObject VIF.network, 'network'
$wait xapi.call 'VIF.create', { yield xapi.call 'VIF.create', {
device: String(deviceId++) device: String(deviceId++)
MAC: VIF.MAC ? '' MAC: VIF.MAC ? ''
@ -65,11 +65,11 @@ create = $coroutine ({
return return
# TODO: ? $wait xapi.call 'VM.set_PV_args', ref, 'noninteractive' # TODO: ? yield xapi.call 'VM.set_PV_args', ref, 'noninteractive'
# Updates the number of existing vCPUs. # Updates the number of existing vCPUs.
if CPUs? if CPUs?
$wait xapi.call 'VM.set_VCPUs_at_startup', ref, CPUs yield xapi.call 'VM.set_VCPUs_at_startup', ref, CPUs
# TODO: remove existing VDIs (o make sure we have only those we # TODO: remove existing VDIs (o make sure we have only those we
# asked. # asked.
@ -96,10 +96,10 @@ create = $coroutine ({
} }
# Replace the existing entry in the VM object. # Replace the existing entry in the VM object.
try $wait xapi.call 'VM.remove_from_other_config', ref, 'disks' try yield xapi.call 'VM.remove_from_other_config', ref, 'disks'
$wait xapi.call 'VM.add_to_other_config', ref, 'disks', VDIs yield xapi.call 'VM.add_to_other_config', ref, 'disks', VDIs
try $wait xapi.call( try yield xapi.call(
'VM.remove_from_other_config' 'VM.remove_from_other_config'
ref ref
'install-repository' 'install-repository'
@ -107,12 +107,12 @@ create = $coroutine ({
if installation if installation
switch installation.method switch installation.method
when 'cdrom' when 'cdrom'
$wait xapi.call( yield xapi.call(
'VM.add_to_other_config', ref 'VM.add_to_other_config', ref
'install-repository', 'cdrom' 'install-repository', 'cdrom'
) )
when 'ftp', 'http', 'nfs' when 'ftp', 'http', 'nfs'
$wait xapi.call( yield xapi.call(
'VM.add_to_other_config', ref 'VM.add_to_other_config', ref
'install-repository', installation.repository 'install-repository', installation.repository
) )
@ -124,10 +124,10 @@ create = $coroutine ({
# Creates the VDIs and executes the initial steps of the # Creates the VDIs and executes the initial steps of the
# installation. # installation.
$wait xapi.call 'VM.provision', ref yield xapi.call 'VM.provision', ref
# Gets the VM record. # Gets the VM record.
VM = $wait xapi.call 'VM.get_record', ref VM = yield xapi.call 'VM.get_record', ref
if installation.method is 'cdrom' if installation.method is 'cdrom'
# Gets the VDI containing the ISO to mount. # Gets the VDI containing the ISO to mount.
@ -140,7 +140,7 @@ create = $coroutine ({
# CD. # CD.
CD_drive = null CD_drive = null
$forEach VM.VBDs, (ref) -> $forEach VM.VBDs, (ref) ->
VBD = $wait xapi.call 'VBD.get_record', ref VBD = yield xapi.call 'VBD.get_record', ref
# TODO: Checks it has been correctly retrieved. # TODO: Checks it has been correctly retrieved.
if VBD.type is 'CD' if VBD.type is 'CD'
CD_drive = VBD.ref CD_drive = VBD.ref
@ -150,7 +150,7 @@ create = $coroutine ({
# No CD drives have been found, creates one. # No CD drives have been found, creates one.
unless CD_drive unless CD_drive
# See: https://github.com/xenserver/xenadmin/blob/da00b13bb94603b369b873b0a555d44f15fa0ca5/XenModel/Actions/VM/CreateVMAction.cs#L370 # See: https://github.com/xenserver/xenadmin/blob/da00b13bb94603b369b873b0a555d44f15fa0ca5/XenModel/Actions/VM/CreateVMAction.cs#L370
CD_drive = $wait xapi.call 'VBD.create', { CD_drive = yield xapi.call 'VBD.create', {
bootable: true bootable: true
device: '' device: ''
empty: true empty: true
@ -160,7 +160,7 @@ create = $coroutine ({
qos_algorithm_type: '' qos_algorithm_type: ''
type: 'CD' type: 'CD'
unpluggable: true unpluggable: true
userdevice: ($wait xapi.call 'VM.get_allowed_VBD_devices', ref)[0] userdevice: (yield xapi.call 'VM.get_allowed_VBD_devices', ref)[0]
VDI: 'OpaqueRef:NULL' VDI: 'OpaqueRef:NULL'
VM: ref VM: ref
} }
@ -169,10 +169,10 @@ create = $coroutine ({
@throw 'NO_SUCH_OBJECT' unless CD_drive @throw 'NO_SUCH_OBJECT' unless CD_drive
# Mounts the VDI into the VBD. # Mounts the VDI into the VBD.
$wait xapi.call 'VBD.insert', CD_drive, VDIref yield xapi.call 'VBD.insert', CD_drive, VDIref
else else
$wait xapi.call 'VM.provision', ref yield xapi.call 'VM.provision', ref
VM = $wait xapi.call 'VM.get_record', ref VM = yield xapi.call 'VM.get_record', ref
# The VM should be properly created. # The VM should be properly created.
return VM.uuid return VM.uuid
@ -272,7 +272,7 @@ ejectCd = $coroutine ({vm}) ->
return return
if cdDriveRef if cdDriveRef
$wait xapi.call 'VBD.eject', cdDriveRef yield xapi.call 'VBD.eject', cdDriveRef
# Silently attempts to destroy the VBD. # Silently attempts to destroy the VBD.
xapi.call('VBD.destroy', cdDriveRef).catch(->) xapi.call('VBD.destroy', cdDriveRef).catch(->)
@ -306,9 +306,9 @@ insertCd = $coroutine ({vm, vdi, force}) ->
if cdDrive.VDI if cdDrive.VDI
@throw 'INVALID_PARAMS' unless force @throw 'INVALID_PARAMS' unless force
$wait xapi.call 'VBD.eject', cdDriveRef yield xapi.call 'VBD.eject', cdDriveRef
else else
cdDriveRef = $wait xapi.call 'VBD.create', { cdDriveRef = yield xapi.call 'VBD.create', {
bootable: true bootable: true
device: '' device: ''
empty: true empty: true
@ -318,12 +318,12 @@ insertCd = $coroutine ({vm, vdi, force}) ->
qos_algorithm_type: '' qos_algorithm_type: ''
type: 'CD' type: 'CD'
unpluggable: true unpluggable: true
userdevice: ($wait xapi.call 'VM.get_allowed_VBD_devices', vm.ref)[0] userdevice: (yield xapi.call 'VM.get_allowed_VBD_devices', vm.ref)[0]
VDI: 'OpaqueRef:NULL' VDI: 'OpaqueRef:NULL'
VM: vm.ref VM: vm.ref
} }
$wait xapi.call 'VBD.insert', cdDriveRef, vdi.ref yield xapi.call 'VBD.insert', cdDriveRef, vdi.ref
return true return true
@ -347,7 +347,7 @@ migrate = $coroutine ({vm, host}) ->
xapi = @getXAPI vm xapi = @getXAPI vm
$wait xapi.call 'VM.pool_migrate', vm.ref, host.ref, {'force': 'true'} yield xapi.call 'VM.pool_migrate', vm.ref, host.ref, {'force': 'true'}
return true return true
@ -411,14 +411,14 @@ migratePool = $coroutine ({
VIF = @getObject vifId, 'VIF' VIF = @getObject vifId, 'VIF'
vifMap[VIF.ref] = network.ref vifMap[VIF.ref] = network.ref
token = $wait (@getXAPI host).call( token = yield (@getXAPI host).call(
'host.migrate_receive' 'host.migrate_receive'
host.ref host.ref
migrationNetwork.ref migrationNetwork.ref
{} # Other parameters {} # Other parameters
) )
$wait (@getXAPI VM).call( yield (@getXAPI VM).call(
'VM.migrate_send' 'VM.migrate_send'
VM.ref VM.ref
token token
@ -486,10 +486,10 @@ set = $coroutine (params) ->
) )
if memory < VM.memory.dynamic[0] if memory < VM.memory.dynamic[0]
$wait xapi.call 'VM.set_memory_dynamic_min', ref, "#{memory}" yield xapi.call 'VM.set_memory_dynamic_min', ref, "#{memory}"
else if memory > VM.memory.static[1] else if memory > VM.memory.static[1]
$wait xapi.call 'VM.set_memory_static_max', ref, "#{memory}" yield xapi.call 'VM.set_memory_static_max', ref, "#{memory}"
$wait xapi.call 'VM.set_memory_dynamic_max', ref, "#{memory}" yield xapi.call 'VM.set_memory_dynamic_max', ref, "#{memory}"
# Number of CPUs. # Number of CPUs.
if 'CPUs' of params if 'CPUs' of params
@ -502,11 +502,11 @@ set = $coroutine (params) ->
"cannot set CPUs above the static maximum (#{VM.CPUs.max}) "+ "cannot set CPUs above the static maximum (#{VM.CPUs.max}) "+
"for a running VM" "for a running VM"
) )
$wait xapi.call 'VM.set_VCPUs_number_live', ref, "#{CPUs}" yield xapi.call 'VM.set_VCPUs_number_live', ref, "#{CPUs}"
else else
if CPUs > VM.CPUs.max if CPUs > VM.CPUs.max
$wait xapi.call 'VM.set_VCPUs_max', ref, "#{CPUs}" yield xapi.call 'VM.set_VCPUs_max', ref, "#{CPUs}"
$wait xapi.call 'VM.set_VCPUs_at_startup', ref, "#{CPUs}" yield xapi.call 'VM.set_VCPUs_at_startup', ref, "#{CPUs}"
# HA policy # HA policy
# TODO: also handle "best-effort" case # TODO: also handle "best-effort" case
@ -514,17 +514,17 @@ set = $coroutine (params) ->
{high_availability} = params {high_availability} = params
if high_availability if high_availability
$wait xapi.call 'VM.set_ha_restart_priority', ref, "restart" yield xapi.call 'VM.set_ha_restart_priority', ref, "restart"
else else
$wait xapi.call 'VM.set_ha_restart_priority', ref, "" yield xapi.call 'VM.set_ha_restart_priority', ref, ""
if 'auto_poweron' of params if 'auto_poweron' of params
{auto_poweron} = params {auto_poweron} = params
if auto_poweron if auto_poweron
$wait xapi.call 'VM.add_to_other_config', ref, 'auto_poweron', 'true' yield xapi.call 'VM.add_to_other_config', ref, 'auto_poweron', 'true'
else else
$wait xapi.call 'VM.remove_from_other_config', ref, 'auto_poweron' yield xapi.call 'VM.remove_from_other_config', ref, 'auto_poweron'
# Other fields. # Other fields.
for param, fields of { for param, fields of {
@ -534,7 +534,7 @@ set = $coroutine (params) ->
continue unless param of params continue unless param of params
for field in (if $isArray fields then fields else [fields]) for field in (if $isArray fields then fields else [fields])
$wait xapi.call "VM.set_#{field}", ref, "#{params[param]}" yield xapi.call "VM.set_#{field}", ref, "#{params[param]}"
return true return true
@ -573,9 +573,9 @@ restart = $coroutine ({vm, force}) ->
xapi = @getXAPI(vm) xapi = @getXAPI(vm)
if force if force
$wait xapi.call 'VM.hard_reboot', vm.ref yield xapi.call 'VM.hard_reboot', vm.ref
else else
$wait xapi.call 'VM.clean_reboot', vm.ref yield xapi.call 'VM.clean_reboot', vm.ref
return true return true
@ -595,9 +595,9 @@ exports.restart = restart
clone = $coroutine ({vm, name, full_copy}) -> clone = $coroutine ({vm, name, full_copy}) ->
xapi = @getXAPI vm xapi = @getXAPI vm
if full_copy if full_copy
$wait xapi.call 'VM.copy', vm.ref, name, '' yield xapi.call 'VM.copy', vm.ref, name, ''
else else
$wait xapi.call 'VM.clone', vm.ref, name yield xapi.call 'VM.clone', vm.ref, name
return true return true
@ -621,7 +621,7 @@ exports.clone = clone
# TODO: rename convertToTemplate() # TODO: rename convertToTemplate()
convert = $coroutine ({vm}) -> convert = $coroutine ({vm}) ->
$wait @getXAPI(vm).call 'VM.set_is_a_template', vm.ref, true yield @getXAPI(vm).call 'VM.set_is_a_template', vm.ref, true
return true return true
@ -638,7 +638,7 @@ exports.convert = convert
#--------------------------------------------------------------------- #---------------------------------------------------------------------
snapshot = $coroutine ({vm, name}) -> snapshot = $coroutine ({vm, name}) ->
snapshot = $wait @getXAPI(vm).snapshotVm(vm.ref, name) snapshot = yield @getXAPI(vm).snapshotVm(vm.ref, name)
return snapshot.$id return snapshot.$id
snapshot.params = { snapshot.params = {
@ -655,7 +655,7 @@ exports.snapshot = snapshot
#--------------------------------------------------------------------- #---------------------------------------------------------------------
start = $coroutine ({vm}) -> start = $coroutine ({vm}) ->
$wait @getXAPI(vm).call( yield @getXAPI(vm).call(
'VM.start', vm.ref 'VM.start', vm.ref
false # Start paused? false # Start paused?
false # Skips the pre-boot checks? false # Skips the pre-boot checks?
@ -684,12 +684,12 @@ stop = $coroutine ({vm, force}) ->
# Hard shutdown # Hard shutdown
if force if force
$wait xapi.call 'VM.hard_shutdown', vm.ref yield xapi.call 'VM.hard_shutdown', vm.ref
return true return true
# Clean shutdown # Clean shutdown
try try
$wait xapi.call 'VM.clean_shutdown', vm.ref yield xapi.call 'VM.clean_shutdown', vm.ref
catch error catch error
if error.code is 'VM_MISSING_PV_DRIVERS' if error.code is 'VM_MISSING_PV_DRIVERS'
# TODO: Improve reporting: this message is unclear. # TODO: Improve reporting: this message is unclear.
@ -713,7 +713,7 @@ exports.stop = stop
#--------------------------------------------------------------------- #---------------------------------------------------------------------
suspend = $coroutine ({vm}) -> suspend = $coroutine ({vm}) ->
$wait @getXAPI(vm).call 'VM.suspend', vm.ref yield @getXAPI(vm).call 'VM.suspend', vm.ref
return true return true
@ -733,7 +733,7 @@ resume = $coroutine ({vm, force}) ->
if not force if not force
force = true force = true
$wait @getXAPI(vm).call 'VM.resume', vm.ref, false, force yield @getXAPI(vm).call 'VM.resume', vm.ref, false, force
return true return true
@ -752,7 +752,7 @@ exports.resume = resume
# revert a snapshot to its parent VM # revert a snapshot to its parent VM
revert = $coroutine ({snapshot}) -> revert = $coroutine ({snapshot}) ->
# Attempts a revert from this snapshot to its parent VM # Attempts a revert from this snapshot to its parent VM
$wait @getXAPI(snapshot).call 'VM.revert', snapshot.ref yield @getXAPI(snapshot).call 'VM.revert', snapshot.ref
return true return true
@ -778,12 +778,12 @@ handleExport = (req, res, {stream, response: upstream}) ->
# TODO: integrate in xapi.js # TODO: integrate in xapi.js
export_ = $coroutine ({vm, compress}) -> export_ = $coroutine ({vm, compress}) ->
stream = $wait @getXAPI(vm).exportVm(vm.id, compress ? true) stream = yield @getXAPI(vm).exportVm(vm.id, compress ? true)
return { return {
$getFrom: $wait @registerHttpRequest(handleExport, { $getFrom: yield @registerHttpRequest(handleExport, {
stream, stream,
response: $wait stream.response response: yield stream.response
}) })
} }
@ -805,7 +805,7 @@ import_ = $coroutine ({host}) ->
{sessionId} = @getXAPI(host) {sessionId} = @getXAPI(host)
url = $wait @registerProxyRequest { url = yield @registerProxyRequest {
# Receive a POST but send a PUT. # Receive a POST but send a PUT.
method: 'put' method: 'put'
proxyMethod: 'post' proxyMethod: 'post'
@ -834,7 +834,7 @@ exports.import = import_
# FIXME: if position is used, all other disks after this position # FIXME: if position is used, all other disks after this position
# should be shifted. # should be shifted.
attachDisk = $coroutine ({vm, vdi, position, mode, bootable}) -> attachDisk = $coroutine ({vm, vdi, position, mode, bootable}) ->
$wait @getXAPI(vm).attachVdiToVm(vdi.id, vm.id, {bootable, mode, position}) yield @getXAPI(vm).attachVdiToVm(vdi.id, vm.id, {bootable, mode, position})
return return
attachDisk.params = { attachDisk.params = {
@ -859,7 +859,7 @@ exports.attachDisk = attachDisk
# FIXME: position should be optional and default to last. # FIXME: position should be optional and default to last.
createInterface = $coroutine ({vm, network, position, mtu, mac}) -> createInterface = $coroutine ({vm, network, position, mtu, mac}) ->
vif = $wait @getXAPI(vm).createVirtualInterface(vm.id, network.id, { vif = yield @getXAPI(vm).createVirtualInterface(vm.id, network.id, {
mac, mac,
mtu, mtu,
position position
@ -886,7 +886,7 @@ exports.createInterface = createInterface
attachPci = $coroutine ({vm, pciId}) -> attachPci = $coroutine ({vm, pciId}) ->
xapi = @getXAPI vm xapi = @getXAPI vm
$wait xapi.call 'VM.add_to_other_config', vm.ref, 'pci', pciId yield xapi.call 'VM.add_to_other_config', vm.ref, 'pci', pciId
return true return true
@ -906,7 +906,7 @@ exports.attachPci = attachPci
detachPci = $coroutine ({vm}) -> detachPci = $coroutine ({vm}) ->
xapi = @getXAPI vm xapi = @getXAPI vm
$wait xapi.call 'VM.remove_from_other_config', vm.ref, 'pci' yield xapi.call 'VM.remove_from_other_config', vm.ref, 'pci'
return true return true
@ -933,7 +933,7 @@ stats = $coroutine ({vm}) ->
else unless type is 'host' else unless type is 'host'
throw new Error "unexpected type: got #{type} instead of host" throw new Error "unexpected type: got #{type} instead of host"
[response, body] = $wait $request { [response, body] = yield $request {
method: 'get' method: 'get'
rejectUnauthorized: false rejectUnauthorized: false
url: 'https://'+host.address+'/vm_rrd?session_id='+xapi.sessionId+'&uuid='+vm.id url: 'https://'+host.address+'/vm_rrd?session_id='+xapi.sessionId+'&uuid='+vm.id
@ -1031,7 +1031,7 @@ bootOrder = $coroutine ({vm, order}) ->
order = {order: order} order = {order: order}
$wait xapi.call 'VM.set_HVM_boot_params', vm.ref, order yield xapi.call 'VM.set_HVM_boot_params', vm.ref, order
return true return true

View File

@ -1,115 +0,0 @@
import Bluebird from 'bluebird'
import Fiber from 'fibers'
import forEach from 'lodash.foreach'
import isArray from 'lodash.isarray'
import isFunction from 'lodash.isfunction'
import isObject from 'lodash.isobject'
// ===================================================================
export const isPromise = (obj) => obj && isFunction(obj.then)
// The value is guarantee to resolve asynchronously.
const runAsync = (value, resolve, reject) => {
if (isPromise(value)) {
return value.then(resolve, reject)
}
if (isFunction(value)) { // Continuable
throw new Error('continuable are no longer supported')
}
if (!isObject(value)) {
return process.nextTick(() => {
resolve(value)
})
}
let left = 0
let results = isArray(value) ?
new Array(value.length) :
Object.create(null)
forEach(value, (value, index) => {
++left
runAsync(
value,
(result) => {
// Returns if already rejected.
if (!results) {
return
}
results[index] = result
if (!--left) {
resolve(results)
}
},
(error) => {
// Returns if already rejected.
if (!results) {
return
}
// Frees the reference ASAP.
results = null
reject(error)
}
)
})
if (!left) {
process.nextTick(() => {
resolve(value)
})
}
}
// ===================================================================
// Makes a function run in its own fiber and returns a promise.
export function coroutine (fn) {
return function (...args) {
return new Bluebird((resolve, reject) => {
new Fiber(() => {
try {
resolve(fn.apply(this, args))
} catch (error) {
reject(error)
}
}).run()
})
}
}
// Waits for a promise or a continuable to end.
//
// If value is composed (array or map), every asynchronous value is
// resolved before returning (parallelization).
export const wait = (value) => {
const fiber = Fiber.current
if (!fiber) {
throw new Error('not running in a fiber')
}
runAsync(
value,
(value) => {
fiber.run(value)
},
(error) => {
fiber.throwInto(error)
}
)
return Fiber.yield()
}
// ===================================================================
// Compatibility.
export {
coroutine as $coroutine,
wait as $wait
}

View File

@ -1,151 +0,0 @@
/* eslint-env mocha */
import {expect} from 'chai'
// -------------------------------------------------------------------
import Bluebird from 'bluebird'
// -------------------------------------------------------------------
import {$coroutine, $wait} from './fibers-utils'
// Enable source maps support for traces.
import sourceMapSupport from 'source-map-support'
sourceMapSupport.install()
// ===================================================================
describe('$coroutine', function () {
it('creates a function which returns promises', function () {
const fn = $coroutine(function () {})
expect(fn().then).to.be.a('function')
})
it('creates a function which runs in a new fiber', function () {
const previous = require('fibers').current
const fn = $coroutine(function () {
const current = require('fibers').current
expect(current).to.exists
expect(current).to.not.equal(previous)
})
return fn()
})
it('forwards all arguments (even this)', function () {
const self = {}
const arg1 = {}
const arg2 = {}
return $coroutine(function (arg1_, arg2_) {
expect(this).to.equal(self)
expect(arg1_).to.equal(arg1)
expect(arg2_).to.equal(arg2)
}).call(self, arg1, arg2)
})
})
// -------------------------------------------------------------------
describe('$wait', function () {
it('waits for a promise', function () {
return $coroutine(function () {
const value = {}
const promise = Bluebird.resolve(value)
expect($wait(promise)).to.equal(value)
})()
})
it('handles promise rejection', function () {
return $coroutine(function () {
const promise = Bluebird.reject('an exception')
expect(function () {
$wait(promise)
}).to.throw('an exception')
})()
})
it('forwards scalar values', function () {
return $coroutine(function () {
let value = 'a scalar value'
expect($wait(value)).to.equal(value)
value = [
'foo',
'bar',
'baz'
]
expect($wait(value)).to.deep.equal(value)
value = []
expect($wait(value)).to.deep.equal(value)
value = {
foo: 'foo',
bar: 'bar',
baz: 'baz'
}
expect($wait(value)).to.deep.equal(value)
value = {}
expect($wait(value)).to.deep.equal(value)
})()
})
it('handles arrays of promises', function () {
return $coroutine(function () {
const value1 = {}
const value2 = {}
const promise1 = Bluebird.resolve(value1)
const promise2 = Bluebird.resolve(value2)
const results = $wait([promise1, promise2])
expect(results[0]).to.equal(value1)
expect(results[1]).to.equal(value2)
})()
})
it('handles maps of promises', function () {
return $coroutine(function () {
const value1 = {}
const value2 = {}
const promise1 = Bluebird.resolve(value1)
const promise2 = Bluebird.resolve(value2)
const results = $wait({
foo: promise1,
bar: promise2
})
expect(results.foo).to.equal(value1)
expect(results.bar).to.equal(value2)
})()
})
it('handles nested arrays/maps', function () {
const promise1 = Bluebird.resolve('promise 1')
const promise2 = Bluebird.resolve('promise 2')
return $coroutine(function () {
expect($wait({
foo: promise1,
bar: [
promise2,
'a scalar'
]
})).to.deep.equal({
foo: 'promise 1',
bar: [
'promise 2',
'a scalar'
]
})
})()
})
})