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({
bare: true
}))
// Necessary to correctly compile generators.
.pipe(babel())
.pipe(sourceMaps.write('.'))
.pipe(gulp.dest(DIST_DIR))
})

View File

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

View File

@ -1,12 +1,11 @@
import {coroutine, wait} from '../fibers-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 ref = wait(xapi.call('VDI.create', {
const ref = await xapi.call('VDI.create', {
name_label: name,
other_config: {},
read_only: false,
@ -14,10 +13,10 @@ export const create = coroutine(function ({name, size, sr}) {
SR: sr.ref,
type: 'user',
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'

View File

@ -1,12 +1,12 @@
{$coroutine, $wait} = require '../fibers-utils'
$debug = (require 'debug') 'xo:api:vm'
$request = require('bluebird').promisify(require('request'))
{parseXml} = require '../utils'
$forEach = require 'lodash.foreach'
$find = require 'lodash.find'
$findIndex = require 'lodash.findindex'
startsWith = require 'lodash.startswith'
$forEach = require 'lodash.foreach'
$request = require('bluebird').promisify(require('request'))
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
$wait xapi.call "host.set_#{field}", host.ref, params[param]
yield xapi.call "host.set_#{field}", host.ref, params[param]
return true
@ -48,8 +48,8 @@ exports.set = set
restart = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'host.disable', host.ref
$wait xapi.call 'host.reboot', host.ref
yield xapi.call 'host.disable', host.ref
yield xapi.call 'host.reboot', host.ref
return true
@ -68,7 +68,7 @@ exports.restart = restart
restartAgent = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'host.restart_agent', host.ref
yield xapi.call 'host.restart_agent', host.ref
return true
@ -88,7 +88,7 @@ exports.restart_agent = restartAgent
start = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'host.power_on', host.ref
yield xapi.call 'host.power_on', host.ref
return true
@ -107,8 +107,8 @@ exports.start = start
stop = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'host.disable', host.ref
$wait xapi.call 'host.shutdown', host.ref
yield xapi.call 'host.disable', host.ref
yield xapi.call 'host.shutdown', host.ref
return true
@ -127,7 +127,7 @@ exports.stop = stop
detach = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'pool.eject', host.ref
yield xapi.call 'pool.eject', host.ref
return true
@ -146,7 +146,7 @@ exports.detach = detach
enable = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'host.enable', host.ref
yield xapi.call 'host.enable', host.ref
return true
@ -165,7 +165,7 @@ exports.enable = enable
disable = $coroutine ({host}) ->
xapi = @getXAPI host
$wait xapi.call 'host.disable', host.ref
yield xapi.call 'host.disable', host.ref
return true
@ -186,7 +186,7 @@ createNetwork = $coroutine ({host, name, description, pif, mtu, vlan}) ->
description = description ? 'Created with Xen Orchestra'
network_ref = $wait xapi.call 'network.create', {
network_ref = yield xapi.call 'network.create', {
name_label: name,
name_description: description,
MTU: mtu ? '1500'
@ -196,7 +196,7 @@ createNetwork = $coroutine ({host, name, description, pif, mtu, vlan}) ->
if pif?
vlan = vlan ? '0'
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
@ -256,7 +256,7 @@ stats = $coroutine ({host}) ->
xapi = @getXAPI host
[response, body] = $wait $request {
[response, body] = yield $request {
method: 'get'
rejectUnauthorized: false
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 {coroutine, wait} from '../fibers-utils'
// ===================================================================
export const signIn = coroutine(function (credentials) {
export async function signIn (credentials) {
if (this.session.has('user_id')) {
throw new AlreadyAuthenticated()
}
const user = wait(this.authenticateUser(credentials))
const user = await this.authenticateUser(credentials)
if (!user) {
throw new InvalidCredential()
}
this.session.set('user_id', user.get('id'))
return this.getUserPublicProperties(user)
})
}
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')
return userId === undefined ?
null :
this.getUserPublicProperties(wait(this.getUser(userId)))
})
this.getUserPublicProperties(await this.getUser(userId))
}
getUser.description = 'return the currently connected user'

View File

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

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

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'
]
})
})()
})
})