Density mode test.

This commit is contained in:
wescoeur 2016-03-23 16:52:05 +01:00
parent 99e046ddea
commit 5a825bd459
2 changed files with 163 additions and 48 deletions

View File

@ -33,6 +33,7 @@
"babel-runtime": "^5.8.34", "babel-runtime": "^5.8.34",
"cron": "^1.1.0", "cron": "^1.1.0",
"event-to-promise": "^0.6.0", "event-to-promise": "^0.6.0",
"lodash.clonedeep": "^4.3.1",
"lodash.differenceby": "^4.2.1", "lodash.differenceby": "^4.2.1",
"lodash.filter": "^4.2.0", "lodash.filter": "^4.2.0",
"lodash.includes": "^4.1.0", "lodash.includes": "^4.1.0",

View File

@ -1,5 +1,6 @@
import EventEmitter from 'events' import EventEmitter from 'events'
import clone from 'lodash.clonedeep'
import differenceBy from 'lodash.differenceby' import differenceBy from 'lodash.differenceby'
import eventToPromise from 'event-to-promise' import eventToPromise from 'event-to-promise'
import filter from 'lodash.filter' import filter from 'lodash.filter'
@ -157,23 +158,6 @@ function searchObject (objects, fun) {
return object return object
} }
function sortHostsByPool (hosts) {
const struct = {}
for (const host of hosts) {
const poolId = host.$poolId
let pool = struct[poolId]
if (pool === undefined) {
pool = struct[poolId] = []
}
pool.push(host)
}
return struct
}
// =================================================================== // ===================================================================
// Averages. // Averages.
// =================================================================== // ===================================================================
@ -203,15 +187,15 @@ function computeRessourcesAverage (objects, objectsStats, nPoints) {
for (const object of objects) { for (const object of objects) {
const { id } = object const { id } = object
const { stats } = objectsStats[id] const { stats } = objectsStats[id]
const objectAverages = averages[id] = {}
objectAverages.cpu = computeAverage( averages[id] = {
mapToArray(stats.cpus, cpu => computeAverage(cpu, nPoints)) cpu: computeAverage(
) mapToArray(stats.cpus, cpu => computeAverage(cpu, nPoints))
objectAverages.nCpus = stats.cpus.length ),
nCpus: stats.cpus.length,
objectAverages.memoryFree = computeAverage(stats.memoryFree, nPoints) memoryFree: computeAverage(stats.memoryFree, nPoints),
objectAverages.memory = computeAverage(stats.memory, nPoints) memory: computeAverage(stats.memory, nPoints)
}
} }
return averages return averages
@ -521,7 +505,7 @@ class DensityPlan extends Plan {
_checkRessourcesThresholds (objects, averages) { _checkRessourcesThresholds (objects, averages) {
return filter(objects, object => return filter(objects, object =>
averages[object.id].cpu < this._thresholds.cpu.high averages[object.id].memoryFree > this._thresholds.memoryFree.low
) )
} }
@ -533,37 +517,167 @@ class DensityPlan extends Plan {
} }
const { const {
averages: hostsAverages, hosts,
hosts toOptimize
} = results
let {
averages: hostsAverages
} = results } = results
let { toOptimize } = results
const pools = await this._getPlanPools() const pools = await this._getPlanPools()
const hostsByPool = sortHostsByPool(hosts)
// Remove masters from toOptimize and hosts. for (const hostToOptimize of toOptimize) {
for (const poolId in hostsByPool) { const {
const pool = hostsByPool[poolId] id: hostId,
hostsByPool[poolId] = filter(pool, host => host.id !== pool.master) $poolId: poolId
} } = hostToOptimize
toOptimize = differenceBy(toOptimize, pools, object => {
object.type === 'host' ? object.id : object.master
})
// Optimize all masters. const {
await Promise.all( master: masterId
mapToArray(hostsByPool, (hosts, poolId) => { } = pools[poolId]
this._optimizeMaster({ toOptimize, pool: pools[poolId], hosts, hostsAverages })
// Avoid master optimization.
if (masterId === hostId) {
continue
}
let poolMaster // Pool master.
const poolHosts = [] // Without master.
const masters = [] // Without the master of this loop.
const otherHosts = []
for (const dest of hosts) {
const {
id: destId,
$poolId: destPoolId
} = dest
// Destination host != Host to optimize!
if (destId === hostId) {
continue
}
if (destPoolId === poolId) {
if (destId === masterId) {
poolMaster = dest
} else {
poolHosts.push(dest)
}
} else if (destId === pools[destPoolId].master) {
masters.push(dest)
} else {
otherHosts.push(dest)
}
}
const simulResults = await this._simulate({
host: hostToOptimize,
destinations: [
[ poolMaster ],
poolHosts,
masters,
otherHosts
],
hostsAverages: clone(hostsAverages)
}) })
)
// Optimize master. if (simulResults) {
console.log(hosts) // Update stats.
hostsAverages = simulResults.hostsAverages
// Migrate.
await this._migrate(simulResults.moves)
}
}
} }
async _optimizeMaster ({ toOptimize, pool, hosts, hostsAverages }) { async _simulate ({ host, destinations, hostsAverages }) {
// TODO const { id: hostId } = host
throw new Error('Not yet implemented')
debug(`Try to optimize Host (${hostId}).`)
const vms = await this._getVms(hostId)
const vmsAverages = await this._getVmsAverages(vms, host)
// Sort vms by amount of memory. (+ -> -)
vms.sort((a, b) =>
vmsAverages[b.id].memory - vmsAverages[a.id].memory
)
const simulResults = {
hostsAverages,
moves: []
}
// Try to find a destination for each VM.
for (const vm of vms) {
let move
// Simulate the VM move on a destinations set.
for (const subDestinations of destinations) {
move = this._testMigration({
vm,
destinations: subDestinations,
hostsAverages,
vmsAverages
})
// Destination found.
if (move) {
simulResults.moves.push(move)
break
}
}
// Unable to move a VM.
if (!move) {
return
}
}
// Done.
return simulResults
}
// Test if a VM migration on a destination (of a destinations set) is possible.
_testMigration ({ vm, destinations, hostsAverages, vmsAverages }) {
const {
_thresholds: {
critical: criticalThreshold
}
} = this
// Sort the destinations by available memory. (- -> +)
destinations.sort((a, b) =>
hostsAverages[a.id].memoryFree - hostsAverages[b.id].memoryFree
)
for (const destination of destinations) {
const destinationAverages = hostsAverages[destination.id]
const vmAverages = vmsAverages[vm.id]
// Unable to move the VM.
if (
destinationAverages.cpu + vmAverages.cpu >= criticalThreshold ||
destinationAverages.memoryFree - vmAverages.memory <= criticalThreshold
) {
continue
}
destinationAverages.cpu += vmAverages.cpu
destinationAverages.memoryFree -= vmAverages.memory
// Available movement.
return {
vm,
destination
}
}
}
async _migrate (moves) {
console.log(moves)
} }
} }