fix(vm.create): correctly compute limits usage (#389)
Fixes vatesfr/xo-web#1365
This commit is contained in:
parent
66d63e0546
commit
08e392bb46
@ -61,6 +61,21 @@ extract = (obj, prop) ->
|
|||||||
|
|
||||||
# TODO: Implement ACLs
|
# TODO: Implement ACLs
|
||||||
create = $coroutine (params) ->
|
create = $coroutine (params) ->
|
||||||
|
console.log(params)
|
||||||
|
|
||||||
|
checkLimits = limits = null
|
||||||
|
|
||||||
|
{ user } = this
|
||||||
|
resourceSet = extract(params, 'resourceSet')
|
||||||
|
if resourceSet
|
||||||
|
yield this.checkResourceSetConstraints(resourceSet, user.id, objectIds)
|
||||||
|
checkLimits = $coroutine (limits2) =>
|
||||||
|
console.log('limits', limits, limits2)
|
||||||
|
yield this.allocateLimitsInResourceSet(limits, resourceSet)
|
||||||
|
yield this.allocateLimitsInResourceSet(limits2, resourceSet)
|
||||||
|
else unless user.permission is 'admin'
|
||||||
|
throw new Unauthorized()
|
||||||
|
|
||||||
template = extract(params, 'template')
|
template = extract(params, 'template')
|
||||||
params.template = template._xapiId
|
params.template = template._xapiId
|
||||||
|
|
||||||
@ -81,7 +96,7 @@ create = $coroutine (params) ->
|
|||||||
vbd.type is 'Disk' and
|
vbd.type is 'Disk' and
|
||||||
(vdi = vbd.$VDI)
|
(vdi = vbd.$VDI)
|
||||||
)
|
)
|
||||||
vdiSizesByDevice[vbd.device] = +vdi.virtual_size
|
vdiSizesByDevice[vbd.userdevice] = +vdi.virtual_size
|
||||||
|
|
||||||
return
|
return
|
||||||
)
|
)
|
||||||
@ -95,7 +110,7 @@ create = $coroutine (params) ->
|
|||||||
limits.disk += size
|
limits.disk += size
|
||||||
|
|
||||||
return $assign({}, vdi, {
|
return $assign({}, vdi, {
|
||||||
device: vdi.device ? vdi.position,
|
device: vdi.userdevice ? vdi.device ? vdi.position,
|
||||||
size,
|
size,
|
||||||
SR: sr._xapiId,
|
SR: sr._xapiId,
|
||||||
type: vdi.type
|
type: vdi.type
|
||||||
@ -103,10 +118,10 @@ create = $coroutine (params) ->
|
|||||||
)
|
)
|
||||||
|
|
||||||
existingVdis = extract(params, 'existingDisks')
|
existingVdis = extract(params, 'existingDisks')
|
||||||
params.existingVdis = existingVdis and map(existingVdis, (vdi, device) =>
|
params.existingVdis = existingVdis and map(existingVdis, (vdi, userdevice) =>
|
||||||
if vdi.size?
|
if vdi.size?
|
||||||
size = parseSize(vdi.size)
|
size = parseSize(vdi.size)
|
||||||
vdiSizesByDevice[device] = size
|
vdiSizesByDevice[userdevice] = size
|
||||||
|
|
||||||
if vdi.$SR
|
if vdi.$SR
|
||||||
sr = @getObject(vdi.$SR)
|
sr = @getObject(vdi.$SR)
|
||||||
@ -118,6 +133,7 @@ create = $coroutine (params) ->
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
console.log(vdiSizesByDevice)
|
||||||
forEach(vdiSizesByDevice, (size) => limits.disk += size)
|
forEach(vdiSizesByDevice, (size) => limits.disk += size)
|
||||||
|
|
||||||
vifs = extract(params, 'VIFs')
|
vifs = extract(params, 'VIFs')
|
||||||
@ -135,18 +151,9 @@ create = $coroutine (params) ->
|
|||||||
installation = extract(params, 'installation')
|
installation = extract(params, 'installation')
|
||||||
params.installRepository = installation && installation.repository
|
params.installRepository = installation && installation.repository
|
||||||
|
|
||||||
resourceSet = extract(params, 'resourceSet')
|
xapiVm = yield xapi.createVm(template._xapiId, params, checkLimits)
|
||||||
|
|
||||||
xapiVm = yield xapi.createVm(template._xapiId, params)
|
|
||||||
vm = xapi.xo.addObject(xapiVm)
|
vm = xapi.xo.addObject(xapiVm)
|
||||||
|
|
||||||
{ user } = this
|
|
||||||
if resourceSet
|
|
||||||
yield this.checkResourceSetConstraints(resourceSet, user.id, objectIds)
|
|
||||||
yield this.allocateLimitsInResourceSet(limits, resourceSet)
|
|
||||||
else unless user.permission is 'admin'
|
|
||||||
throw new Unauthorized()
|
|
||||||
|
|
||||||
if resourceSet
|
if resourceSet
|
||||||
yield Promise.all([
|
yield Promise.all([
|
||||||
@addAcl(user.id, vm.id, 'admin')
|
@addAcl(user.id, vm.id, 'admin')
|
||||||
|
@ -2,6 +2,9 @@ import find from 'lodash/find'
|
|||||||
import gte from 'lodash/gte'
|
import gte from 'lodash/gte'
|
||||||
import lte from 'lodash/lte'
|
import lte from 'lodash/lte'
|
||||||
|
|
||||||
|
import {
|
||||||
|
deferrable
|
||||||
|
} from '../../decorators'
|
||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
@ -18,7 +21,8 @@ import {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
// TODO: clean up on error.
|
// TODO: clean up on error.
|
||||||
async createVm (templateId, {
|
@deferrable.onFailure
|
||||||
|
async createVm ($onFailure, templateId, {
|
||||||
name_label, // deprecated
|
name_label, // deprecated
|
||||||
nameLabel = name_label, // eslint-disable-line camelcase
|
nameLabel = name_label, // eslint-disable-line camelcase
|
||||||
|
|
||||||
@ -34,7 +38,7 @@ export default {
|
|||||||
cloudConfig = undefined,
|
cloudConfig = undefined,
|
||||||
|
|
||||||
...props
|
...props
|
||||||
} = {}) {
|
} = {}, checkLimits) {
|
||||||
const installMethod = (() => {
|
const installMethod = (() => {
|
||||||
if (installRepository == null) {
|
if (installRepository == null) {
|
||||||
return 'none'
|
return 'none'
|
||||||
@ -50,23 +54,23 @@ export default {
|
|||||||
const template = this.getObject(templateId)
|
const template = this.getObject(templateId)
|
||||||
|
|
||||||
// Clones the template.
|
// Clones the template.
|
||||||
let vm = await this._getOrWaitObject(
|
const vmRef = await this[clone ? '_cloneVm' : '_copyVm'](template, nameLabel)
|
||||||
await this[clone ? '_cloneVm' : '_copyVm'](template, nameLabel)
|
$onFailure(() => this.deleteVm(vmRef, true)::pCatch(noop))
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: copy BIOS strings?
|
// TODO: copy BIOS strings?
|
||||||
|
|
||||||
// Removes disks from the provision XML, we will create them by
|
// Removes disks from the provision XML, we will create them by
|
||||||
// ourselves.
|
// ourselves.
|
||||||
await this.call('VM.remove_from_other_config', vm.$ref, 'disks')::pCatch(noop)
|
await this.call('VM.remove_from_other_config', vmRef, 'disks')::pCatch(noop)
|
||||||
|
|
||||||
// Creates the VDIs and executes the initial steps of the
|
// Creates the VDIs and executes the initial steps of the
|
||||||
// installation.
|
// installation.
|
||||||
await this.call('VM.provision', vm.$ref)
|
await this.call('VM.provision', vmRef)
|
||||||
|
|
||||||
|
let vm = await this._getOrWaitObject(vmRef)
|
||||||
|
|
||||||
// Set VMs params.
|
// Set VMs params.
|
||||||
// TODO: checkLimits
|
await this._editVm(vm, props, checkLimits)
|
||||||
this._editVm(vm, props)
|
|
||||||
|
|
||||||
// Sets boot parameters.
|
// Sets boot parameters.
|
||||||
{
|
{
|
||||||
@ -243,7 +247,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cpuCap: {
|
cpuCap: {
|
||||||
addToLimits: true,
|
|
||||||
get: vm => vm.VCPUs_params.cap && +vm.VCPUs_params.cap,
|
get: vm => vm.VCPUs_params.cap && +vm.VCPUs_params.cap,
|
||||||
set (cap, vm) {
|
set (cap, vm) {
|
||||||
return this._updateObjectMapProperty(vm, 'VCPUs_params', { cap })
|
return this._updateObjectMapProperty(vm, 'VCPUs_params', { cap })
|
||||||
@ -260,7 +263,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cpuWeight: {
|
cpuWeight: {
|
||||||
addToLimits: true,
|
|
||||||
get: vm => vm.VCPUs_params.weight && +vm.VCPUs_params.weight,
|
get: vm => vm.VCPUs_params.weight && +vm.VCPUs_params.weight,
|
||||||
set (weight, vm) {
|
set (weight, vm) {
|
||||||
return this._updateObjectMapProperty(vm, 'VCPUs_params', { weight })
|
return this._updateObjectMapProperty(vm, 'VCPUs_params', { weight })
|
||||||
@ -285,6 +287,7 @@ export default {
|
|||||||
memory: 'memoryMax',
|
memory: 'memoryMax',
|
||||||
memoryMax: {
|
memoryMax: {
|
||||||
addToLimits: true,
|
addToLimits: true,
|
||||||
|
limitName: 'memory',
|
||||||
constraints: {
|
constraints: {
|
||||||
memoryMin: lte,
|
memoryMin: lte,
|
||||||
memoryStaticMax: gte
|
memoryStaticMax: gte
|
||||||
|
@ -224,6 +224,9 @@ export const makeEditObject = specs => {
|
|||||||
if (spec.addToLimits === true) {
|
if (spec.addToLimits === true) {
|
||||||
spec.addToLimits = _DEFAULT_ADD_TO_LIMITS
|
spec.addToLimits = _DEFAULT_ADD_TO_LIMITS
|
||||||
}
|
}
|
||||||
|
if (!spec.limitName) {
|
||||||
|
spec.limitName = name
|
||||||
|
}
|
||||||
|
|
||||||
forEach(spec.constraints, (constraint, constraintName) => {
|
forEach(spec.constraints, (constraint, constraintName) => {
|
||||||
if (!isFunction(constraint)) {
|
if (!isFunction(constraint)) {
|
||||||
@ -302,7 +305,8 @@ export const makeEditObject = specs => {
|
|||||||
|
|
||||||
let addToLimits
|
let addToLimits
|
||||||
if (limits && (addToLimits = spec.addToLimits)) {
|
if (limits && (addToLimits = spec.addToLimits)) {
|
||||||
limits[name] = addToLimits(value, current)
|
console.log(spec.limitName, value, current, addToLimits(value, current))
|
||||||
|
limits[spec.limitName] = addToLimits(value, current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user