Various cleanings & minor fix (xapi.js).

This commit is contained in:
Julien Fontanet 2013-12-14 15:37:09 +01:00
parent 7eb0c36a8e
commit 49fcefbf2d
6 changed files with 78 additions and 75 deletions

View File

@ -1,27 +1,28 @@
# Low level tools.
$_ = require 'underscore' $_ = require 'underscore'
###################################################################### #=====================================================================
class DynamicProperty class $DynamicProperty
constructor: (@value, @hooks) -> constructor: (@value, @hooks) ->
#--------------------------------------------------------------------- #=====================================================================
noop = -> $noop = ->
copyDeep = (value) -> $copyDeep = (value) ->
if value instanceof Array if value instanceof Array
return (copyDeep item for item in value) return ($copyDeep item for item in value)
if value instanceof Object if value instanceof Object
result = {} result = {}
result[key] = copyDeep item for key, item of value result[key] = $copyDeep item for key, item of value
return result return result
return value return value
getDeep = (obj, path) -> $getDeep = (obj, path) ->
return obj if path.length is 0 return obj if path.length is 0
current = obj current = obj
@ -34,7 +35,7 @@ getDeep = (obj, path) ->
current[path[i]] current[path[i]]
setDeep = (obj, path, value) -> $setDeep = (obj, path, value) ->
throw new Error 'invalid path' if path.length is 0 throw new Error 'invalid path' if path.length is 0
current = obj current = obj
@ -50,7 +51,7 @@ setDeep = (obj, path, value) ->
# @param rule Rule of the current item. # @param rule Rule of the current item.
# @param item Current item. # @param item Current item.
# @param value Value of the generator item. # @param value Value of the generator item.
computeValue = (rule, item, value) -> $computeValue = (rule, item, value) ->
# @param parent The parent object of this entry (necessary for # @param parent The parent object of this entry (necessary for
# assignment). # assignment).
@ -61,8 +62,8 @@ computeValue = (rule, item, value) ->
helper = (parent, name, spec) -> helper = (parent, name, spec) ->
if not $_.isObject spec if not $_.isObject spec
parent[name] = spec parent[name] = spec
else if spec instanceof DynamicProperty else if spec instanceof $DynamicProperty
# If there was no previous value use DynamicProperty.value, # If there was no previous value use $DynamicProperty.value,
# otherwise, just keep the previous value. # otherwise, just keep the previous value.
if parent[name] is undefined if parent[name] is undefined
# Helper is re-called for the initial value. # Helper is re-called for the initial value.
@ -85,7 +86,7 @@ computeValue = (rule, item, value) ->
###################################################################### ######################################################################
class MappedCollection class $MappedCollection
constructor: (spec) -> constructor: (spec) ->
@ -94,8 +95,8 @@ class MappedCollection
if $_.isFunction spec if $_.isFunction spec
ctx = ctx =
dynamic: (initialValue, hooks) -> dynamic: (initialValue, hooks) ->
new DynamicProperty initialValue, hooks new $DynamicProperty initialValue, hooks
noop: noop noop: $noop
spec = spec.call ctx spec = spec.call ctx
@ -114,7 +115,7 @@ class MappedCollection
spec.rules or= {} spec.rules or= {}
# Rules are the core of MappedCollection, they allow to categorize # Rules are the core of $MappedCollection, they allow to categorize
# objects and to treat them differently. # objects and to treat them differently.
@_rules = {} @_rules = {}
@ -198,7 +199,7 @@ class MappedCollection
# If the value is a dynamic property, grabs the initial value # If the value is a dynamic property, grabs the initial value
# and registers its hooks. # and registers its hooks.
if value instanceof DynamicProperty if value instanceof $DynamicProperty
hooks = value.hooks hooks = value.hooks
# Browse hooks for each rules. # Browse hooks for each rules.
@ -220,7 +221,7 @@ class MappedCollection
# current rule. # current rule.
for key, item of items for key, item of items
# Value of the current field. # Value of the current field.
field = getDeep item.value, path field = $getDeep item.value, path
ctx = {rule, field} ctx = {rule, field}
ctx.__proto__ = item # Links to the current item. ctx.__proto__ = item # Links to the current item.
@ -228,7 +229,7 @@ class MappedCollection
hook.call ctx, value, key hook.call ctx, value, key
# Updates the value if it changed. # Updates the value if it changed.
setDeep item.value, path if ctx.field isnt field $setDeep item.value, path if ctx.field isnt field
# Checks each hook is correctly defined. # Checks each hook is correctly defined.
{enter, update, exit} = hooks_ {enter, update, exit} = hooks_
@ -273,7 +274,7 @@ class MappedCollection
value: undefined value: undefined
# Computes the value. # Computes the value.
computeValue rule, item $computeValue rule, item
# No events for static items. # No events for static items.
@ -306,11 +307,10 @@ class MappedCollection
# Adds, updates or removes items from the collections. Items not # Adds, updates or removes items from the collections. Items not
# present are added, present are updated, and present in the # present are added, present are updated, and present in the
# generated collection but not in the generator are removed. # generated collection but not in the generator are removed.
set: (items, options = {}) -> set: (items, {add, update, remove} = {}) ->
{add, update, remove} = options
add = true if add is undefined add = true if add is undefined
update = true if update is undefined update = true if update is undefined
remove = true if remove is undefined remove = false if remove is undefined
itemsToRemove = {} itemsToRemove = {}
if remove if remove
@ -329,7 +329,7 @@ class MappedCollection
rule = @_rules[item._ruleName] rule = @_rules[item._ruleName]
# Compute the new value. # Compute the new value.
computeValue rule, item, value $computeValue rule, item, value
# Runs related hooks. # Runs related hooks.
for hook in @_hooks[rule.name]?.update or [] for hook in @_hooks[rule.name]?.update or []
@ -351,7 +351,7 @@ class MappedCollection
value: undefined value: undefined
# Computes the value. # Computes the value.
computeValue rule, item, value $computeValue rule, item, value
# Runs related hooks. # Runs related hooks.
for hook in @_hooks[rule.name]?.enter or [] for hook in @_hooks[rule.name]?.enter or []
@ -369,6 +369,6 @@ class MappedCollection
# Removes effectively the item. # Removes effectively the item.
delete @_byKey[key] @_byRule[ruleName][key] delete @_byKey[key] @_byRule[ruleName][key]
###################################################################### #=====================================================================
module.exports = MappedCollection module.exports = $MappedCollection

View File

@ -1,3 +1,6 @@
# Low level tools.
$_ = require 'underscore'
# Async code is easier with fibers (light threads)! # Async code is easier with fibers (light threads)!
$fiber = require 'fibers' $fiber = require 'fibers'
@ -8,15 +11,26 @@ $fiberize = (fn) ->
(args...) -> (args...) ->
$fiber(-> fn args...).run() $fiber(-> fn args...).run()
# Makes the fiber waits for a number of miliseconds.
$sleep = (ms) ->
fiber = $fiber.current
setTimeout (-> fiber.run()), ms
$fiber.yield()
# Makes an asynchrouneous function synchrouneous (in a fiber). # Makes an asynchrouneous function synchrouneous (in a fiber).
$synchronize = (fn) -> $synchronize = (fn, ctx) ->
fn = ctx[fn] if $_.isString fn
(args...) -> (args...) ->
fiber = $fiber.current fiber = $fiber.current
fn args..., (error, result) ->
args.push (error, result) ->
if error? if error?
fiber.throwInto error fiber.throwInto error
else else
fiber.run result fiber.run result
fn.apply ctx, args
$fiber.yield() $fiber.yield()
# TODO: remove promises ASAP. # TODO: remove promises ASAP.
@ -32,6 +46,7 @@ $waitForPromise = (promise) ->
module.exports = { module.exports = {
$fiberize $fiberize
$sleep
$synchronize $synchronize
$waitForPromise $waitForPromise
} }

View File

@ -13,9 +13,6 @@ $_ = require 'underscore'
# HTTP(s) middleware framework. # HTTP(s) middleware framework.
$connect = require 'connect' $connect = require 'connect'
# Async code is easier with fibers (light threads)!
$fiber = require 'fibers'
# Configuration handling. # Configuration handling.
$nconf = require 'nconf' $nconf = require 'nconf'

View File

@ -199,7 +199,10 @@ module.exports = (refsToUUIDs) ->
iSCSI_name: (value) -> value.other_config?.iscsi_iqn iSCSI_name: (value) -> value.other_config?.iscsi_iqn
memory: {} # TODO memory: { # TODO
usage: 0
size: 0
}
power_state: 'Running' # TODO power_state: 'Running' # TODO

View File

@ -1,20 +1,13 @@
# Async code is easier with fibers (light threads) and futures! $xmlrpc = require 'xmlrpc'
Fiber = require 'fibers'
Future = require 'fibers/future'
xmlrpc = require 'xmlrpc' #---------------------------------------------------------------------
# Helpers for dealing with fibers.
{$sleep, $synchronize} = require './fibers-utils'
#===================================================================== #=====================================================================
sleep = (ms) -> # Note: All methods are synchroneous (using fibers).
fiber = Fiber.current;
setTimeout (-> fiber.run()), ms
Fiber.yield()
#=====================================================================
# Note: All methods are synchroneous (using fibers), `.future()` may
# be used to make them asynchroneous.
class XAPI class XAPI
constructor: ({@host, @username, @password}) -> constructor: ({@host, @username, @password}) ->
@ -28,12 +21,16 @@ class XAPI
# Makes sure there is not session id left. # Makes sure there is not session id left.
delete @sessionId delete @sessionId
@xmlrpc = xmlrpc.createSecureClient { @xmlrpc = $xmlrpc.createSecureClient {
hostname: @host hostname: @host
port: '443' port: '443'
rejectUnauthorized: false rejectUnauthorized: false
} }
# Make `methodCall()` synchroneous.
@xmlrpc.methodCall = $synchronize 'methodCall', @xmlrpc
# Logs in.
@logIn() @logIn()
call: (method, args...) -> call: (method, args...) ->
@ -42,11 +39,8 @@ class XAPI
args.unshift @sessionId if @sessionId args.unshift @sessionId if @sessionId
do helper = => do helper = =>
future = new Future()
@xmlrpc.methodCall method, args, future.resolver()
try try
result = future.wait() result = @xmlrpc.methodCall method, args
# Returns the plain result if it does not have a valid XAPI format. # Returns the plain result if it does not have a valid XAPI format.
return result unless result.Status? return result unless result.Status?
@ -80,7 +74,7 @@ class XAPI
# I would like to be able to use a shorter delay but for some # I would like to be able to use a shorter delay but for some
# reason, when we connect to XAPI at a give moment, the # reason, when we connect to XAPI at a give moment, the
# connection hangs. # connection hangs.
Fiber.sleep(500) $sleep 500
helper() helper()
# XAPI is sometimes reinitialized and sessions are lost. # XAPI is sometimes reinitialized and sessions are lost.

View File

@ -9,9 +9,6 @@ $_ = require 'underscore'
# Password hasing. # Password hasing.
$hashy = require 'hashy' $hashy = require 'hashy'
# Async code is easier with fibers (light threads)!
$fiber = require 'fibers'
# Redis. # Redis.
$createRedisClient = (require 'then-redis').createClient $createRedisClient = (require 'then-redis').createClient
@ -21,9 +18,6 @@ $createRedisClient = (require 'then-redis').createClient
# specification. # specification.
$MappedCollection = require './MappedCollection' $MappedCollection = require './MappedCollection'
# Collection where models are stored in memory.
$MemoryCollection = require './collection/memory'
# Collection where models are stored in a Redis DB. # Collection where models are stored in a Redis DB.
$RedisCollection = require './collection/redis' $RedisCollection = require './collection/redis'
@ -38,34 +32,34 @@ $XAPI = require './xapi'
#===================================================================== #=====================================================================
$randomBytes = $synchronize $crypto.randomBytes $randomBytes = $synchronize 'randomBytes', $crypto
#===================================================================== #=====================================================================
# Models and collections. # Models and collections.
class Server extends $Model class $Server extends $Model
validate: -> # TODO validate: -> # TODO
class Servers extends $RedisCollection class $Servers extends $RedisCollection
model: Server model: $Server
#--------------------------------------------------------------------- #---------------------------------------------------------------------
class Token extends $Model class $Token extends $Model
@generate: (userId) -> @generate: (userId) ->
new Token { new $Token {
id: ($randomBytes 32).toString 'base64' id: ($randomBytes 32).toString 'base64'
user_id: userId user_id: userId
} }
validate: -> # TODO validate: -> # TODO
class Tokens extends $RedisCollection class $Tokens extends $RedisCollection
model: Token model: $Token
#--------------------------------------------------------------------- #---------------------------------------------------------------------
class User extends $Model class $User extends $Model
default: { default: {
permission: 'none' permission: 'none'
} }
@ -97,11 +91,11 @@ class User extends $Model
perms[@get 'permission'] => perms[permission] perms[@get 'permission'] => perms[permission]
class Users extends $RedisCollection class $Users extends $RedisCollection
model: User model: $User
create: (email, password, permission) -> create: (email, password, permission) ->
user = new User { user = new $User {
email: email email: email
} }
user.setPassword password user.setPassword password
@ -111,24 +105,24 @@ class Users extends $RedisCollection
#===================================================================== #=====================================================================
class XO class $XO
start: (config) -> start: (config) ->
# Connects to Redis. # Connects to Redis.
redis = $createRedisClient config.redis.uri redis = $createRedisClient config.redis.uri
# Creates persistent collections. # Creates persistent collections.
@servers = new Servers { @servers = new $Servers {
connection: redis connection: redis
prefix: 'xo:server' prefix: 'xo:server'
indexes: ['host'] indexes: ['host']
} }
@tokens = new Tokens { @tokens = new $Tokens {
connection: redis connection: redis
prefix: 'xo:token' prefix: 'xo:token'
indexes: ['host'] indexes: ['host']
} }
@users = new Users { @users = new $Users {
connection: redis connection: redis
prefix: 'xo:user' prefix: 'xo:user'
indexes: ['host'] indexes: ['host']
@ -277,4 +271,4 @@ class XO
#===================================================================== #=====================================================================
module.exports = XO module.exports = $XO