From 5f20091f247e5c851a253434f47162e3f98c73e1 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Mon, 29 Feb 2016 18:50:10 +0100 Subject: [PATCH] Xapi#migrateVm(): handle TOO_MANY_STORAGE_MIGRATES (fix vatesfr/xo-web#783). When this error occurs, simply wait 10 seconds and retry. --- package.json | 2 +- src/collection/redis.js | 20 ++++++++++---------- src/utils.js | 2 ++ src/xapi.js | 17 ++++++++++++----- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index de2d7d627..6510416a2 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "partial-stream": "0.0.0", "passport": "^0.3.0", "passport-local": "^1.0.0", - "promise-toolbox": "^0.1.0", + "promise-toolbox": "^0.2.0", "proxy-agent": "^2.0.0", "proxy-http-request": "0.1.0", "redis": "^2.0.1", diff --git a/src/collection/redis.js b/src/collection/redis.js index acf4d716e..e0668c1a1 100644 --- a/src/collection/redis.js +++ b/src/collection/redis.js @@ -50,7 +50,7 @@ export default class Redis extends Collection { const models = [] return Promise.all(mapToArray(ids, id => { - return redis.hgetallAsync(prefix + id).then(model => { + return redis.hgetall(prefix + id).then(model => { // If empty, consider it a no match. if (isEmpty(model)) { return @@ -73,10 +73,10 @@ export default class Redis extends Collection { return Promise.all(mapToArray(models, async model => { // Generate a new identifier if necessary. if (model.id === undefined) { - model.id = idPrefix + String(await redis.incrAsync(prefix + '_id')) + model.id = idPrefix + String(await redis.incr(prefix + '_id')) } - const success = await redis.saddAsync(prefix + '_ids', model.id) + const success = await redis.sadd(prefix + '_ids', model.id) // The entry already exists an we are not in replace mode. if (!success && !replace) { @@ -97,8 +97,8 @@ export default class Redis extends Collection { const key = `${prefix}:${model.id}` const promises = [ - redis.delAsync(key), - redis.hmsetAsync(key, ...params) + redis.del(key), + redis.hmset(key, ...params) ] // Update indexes. @@ -109,7 +109,7 @@ export default class Redis extends Collection { } const key = prefix + '_' + index + ':' + value - promises.push(redis.saddAsync(key, model.id)) + promises.push(redis.sadd(key, model.id)) }) await Promise.all(promises) @@ -122,7 +122,7 @@ export default class Redis extends Collection { const {prefix, redis} = this if (isEmpty(properties)) { - return redis.smembersAsync(prefix + '_ids').then(ids => this._extract(ids)) + return redis.smembers(prefix + '_ids').then(ids => this._extract(ids)) } // Special treatment for the identifier. @@ -145,7 +145,7 @@ export default class Redis extends Collection { } const keys = mapToArray(properties, (value, index) => `${prefix}_${index}:${value}`) - return redis.sinterAsync(...keys).then(ids => this._extract(ids)) + return redis.sinter(...keys).then(ids => this._extract(ids)) } _remove (ids) { @@ -155,10 +155,10 @@ export default class Redis extends Collection { return Promise.all([ // Remove the identifiers from the main index. - redis.sremAsync(prefix + '_ids', ...ids), + redis.srem(prefix + '_ids', ...ids), // Remove the models. - redis.delAsync(mapToArray(ids, id => `${prefix}:${id}`)) + redis.del(mapToArray(ids, id => `${prefix}:${id}`)) ]) } diff --git a/src/utils.js b/src/utils.js index c40cd4888..d04e5438e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -308,6 +308,8 @@ export function pSettle (promises) { export { all as pAll, + catchPlus as pCatch, + delay as pDelay, fromCallback as pFromCallback, isPromise, lastly as pFinally, diff --git a/src/xapi.js b/src/xapi.js index b9fad2ea7..ead1022d9 100644 --- a/src/xapi.js +++ b/src/xapi.js @@ -38,6 +38,8 @@ import { noop, pAll, parseXml, + pCatch, + pDelay, pFinally, promisifyAll, pSettle @@ -1561,7 +1563,7 @@ export default class Xapi extends XapiBase { {} ) - await this.call( + const loop = () => this.call( 'VM.migrate_send', vm.$ref, token, @@ -1571,7 +1573,12 @@ export default class Xapi extends XapiBase { { force: 'true' } + )::pCatch( + { code: 'TOO_MANY_STORAGE_MIGRATES' }, + () => pDelay(1e4).then(loop) ) + + return loop() } async _importVm (stream, sr, onlyMetadata = false, onVmCreation = undefined) { @@ -2286,12 +2293,12 @@ export default class Xapi extends XapiBase { // Then, generate a FAT fs const fs = fatfs.createFileSystem(fatfsBuffer(buffer))::promisifyAll() // Create Cloud config folders - await fs.mkdirAsync('openstack') - await fs.mkdirAsync('openstack/latest') + await fs.mkdir('openstack') + await fs.mkdir('openstack/latest') // Create the meta_data file - await fs.writeFileAsync('openstack/latest/meta_data.json', '{\n "uuid": "' + vm.uuid + '"\n}\n') + await fs.writeFile('openstack/latest/meta_data.json', '{\n "uuid": "' + vm.uuid + '"\n}\n') // Create the user_data file - await fs.writeFileAsync('openstack/latest/user_data', config) + await fs.writeFile('openstack/latest/user_data', config) // Transform the buffer into a stream const stream = bufferToStream(buffer)