Merge pull request #208 from vatesfr/pierre-vm-migration-details
Custom VM migration. (See vatesfr/xo-web#567)
This commit is contained in:
commit
7f9c49cbc4
@ -191,69 +191,71 @@ exports.insertCd = insertCd
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
migrate = $coroutine ({vm, host}) ->
|
||||
yield @getXapi(vm).migrateVm(vm._xapiId, @getXapi(host), host._xapiId)
|
||||
return
|
||||
|
||||
migrate.params = {
|
||||
# Identifier of the VM to migrate.
|
||||
id: { type: 'string' }
|
||||
|
||||
# Identifier of the host to migrate to.
|
||||
host_id: { type: 'string' }
|
||||
}
|
||||
|
||||
migrate.resolve = {
|
||||
vm: ['id', 'VM']
|
||||
host: ['host_id', 'host', 'administrate']
|
||||
}
|
||||
|
||||
exports.migrate = migrate
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
migratePool = $coroutine ({
|
||||
migrate = $coroutine ({
|
||||
vm,
|
||||
host
|
||||
sr
|
||||
network
|
||||
host,
|
||||
mapVdisSrs,
|
||||
mapVifsNetworks,
|
||||
migrationNetwork
|
||||
}) ->
|
||||
mapVdisSrsXapi = {}
|
||||
forEach mapVdisSrs, (srId, vdiId) =>
|
||||
vdiXapiId = @getObject(vdiId, 'VDI')._xapiId
|
||||
mapVdisSrsXapi[vdiXapiId] = @getObject(srId, 'SR')._xapiId
|
||||
|
||||
mapVifsNetworksXapi = {}
|
||||
forEach mapVifsNetworks, (networkId, vifId) =>
|
||||
vifXapiId = @getObject(vifId, 'VIF')._xapiId
|
||||
mapVifsNetworksXapi[vifXapiId] = @getObject(networkId, 'network')._xapiId
|
||||
|
||||
permissions = []
|
||||
for vif, network of mapVifsNetworks
|
||||
permissions.push([
|
||||
network,
|
||||
'administrate'
|
||||
])
|
||||
|
||||
for vdi, sr of mapVdisSrs
|
||||
permissions.push([
|
||||
sr,
|
||||
'administrate'
|
||||
])
|
||||
|
||||
unless yield @hasPermissions(@session.get('user_id'), permissions)
|
||||
throw new Unauthorized()
|
||||
|
||||
yield @getXapi(vm).migrateVm(vm._xapiId, @getXapi(host), host._xapiId, {
|
||||
migrationNetworkId: migrationNetwork?._xapiId
|
||||
networkId: network?._xapiId,
|
||||
srId: sr?._xapiId,
|
||||
mapVifsNetworksXapi,
|
||||
mapVdisSrsXapi,
|
||||
})
|
||||
return
|
||||
|
||||
migratePool.params = {
|
||||
migrate.params = {
|
||||
|
||||
# Identifier of the VM to migrate.
|
||||
id: { type: 'string' }
|
||||
vm: { type: 'string' }
|
||||
|
||||
# Identifier of the host to migrate to.
|
||||
target_host_id: { type: 'string' }
|
||||
targetHost: { type: 'string' }
|
||||
|
||||
# Identifier of the target SR
|
||||
target_sr_id: { type: 'string', optional: true }
|
||||
# Map VDIs IDs --> SRs IDs
|
||||
mapVdisSrs: { type: 'object', optional: true }
|
||||
|
||||
# Identifier of the target Network
|
||||
target_network_id: { type: 'string', optional: true }
|
||||
# Map VIFs IDs --> Networks IDs
|
||||
mapVifsNetworks: { type: 'object', optional: true }
|
||||
|
||||
# Identifier of the Network use for the migration
|
||||
migration_network_id: { type: 'string', optional: true }
|
||||
migrationNetwork: { type: 'string', optional: true }
|
||||
}
|
||||
|
||||
migratePool.resolve = {
|
||||
vm: ['id', 'VM', 'administrate'],
|
||||
host: ['target_host_id', 'host', 'administrate'],
|
||||
sr: ['target_sr_id', 'SR', 'administrate'],
|
||||
network: ['target_network_id', 'network', 'administrate'],
|
||||
migrationNetwork: ['migration_network_id', 'network', 'administrate'],
|
||||
migrate.resolve = {
|
||||
vm: ['vm', 'VM', 'administrate'],
|
||||
host: ['targetHost', 'host', 'administrate'],
|
||||
migrationNetwork: ['migrationNetwork', 'network', 'administrate'],
|
||||
}
|
||||
|
||||
# TODO: camel case.
|
||||
exports.migrate_pool = migratePool
|
||||
exports.migrate = migrate
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
|
50
src/xapi.js
50
src/xapi.js
@ -1504,18 +1504,32 @@ export default class Xapi extends XapiBase {
|
||||
return vm
|
||||
}
|
||||
|
||||
async _migrateVMWithStorageMotion (vm, hostXapi, host, {
|
||||
async _migrateVmWithStorageMotion (vm, hostXapi, host, {
|
||||
migrationNetwork = find(host.$PIFs, pif => pif.management).$network, // TODO: handle not found
|
||||
sr = host.$pool.$default_SR, // TODO: handle not found
|
||||
vifsMap = {}
|
||||
mapVdisSrs,
|
||||
mapVifsNetworks
|
||||
}) {
|
||||
// VDIs/SRs mapping
|
||||
const vdis = {}
|
||||
const defaultSrRef = host.$pool.$default_SR.$ref
|
||||
for (const vbd of vm.$VBDs) {
|
||||
if (vbd.type !== 'CD') {
|
||||
vdis[vbd.$VDI.$ref] = sr.$ref
|
||||
const vdi = vbd.$VDI
|
||||
if (vbd.type === 'Disk') {
|
||||
vdis[vdi.$ref] = mapVdisSrs && mapVdisSrs[vdi.$id]
|
||||
? hostXapi.getObject(mapVdisSrs[vdi.$id]).$ref
|
||||
: defaultSrRef
|
||||
}
|
||||
}
|
||||
|
||||
// VIFs/Networks mapping
|
||||
const vifsMap = {}
|
||||
const defaultNetworkRef = find(host.$PIFs, pif => pif.management).$network.$ref
|
||||
for (const vif of vm.$VIFs) {
|
||||
vifsMap[vif.$ref] = mapVifsNetworks && mapVifsNetworks[vif.$id]
|
||||
? hostXapi.getObject(mapVifsNetworks[vif.$id]).$ref
|
||||
: defaultNetworkRef
|
||||
}
|
||||
|
||||
const token = await hostXapi.call(
|
||||
'host.migrate_receive',
|
||||
host.$ref,
|
||||
@ -1596,8 +1610,8 @@ export default class Xapi extends XapiBase {
|
||||
|
||||
async migrateVm (vmId, hostXapi, hostId, {
|
||||
migrationNetworkId,
|
||||
networkId,
|
||||
srId
|
||||
mapVifsNetworks,
|
||||
mapVdisSrs
|
||||
} = {}) {
|
||||
const vm = this.getObject(vmId)
|
||||
if (!isVmRunning(vm)) {
|
||||
@ -1610,25 +1624,15 @@ export default class Xapi extends XapiBase {
|
||||
const useStorageMotion = (
|
||||
accrossPools ||
|
||||
migrationNetworkId ||
|
||||
networkId ||
|
||||
srId
|
||||
mapVifsNetworks ||
|
||||
mapVdisSrs
|
||||
)
|
||||
|
||||
if (useStorageMotion) {
|
||||
const vifsMap = {}
|
||||
if (accrossPools || networkId) {
|
||||
const {$ref: networkRef} = networkId
|
||||
? hostXapi.getObject(networkId)
|
||||
: find(host.$PIFs, pif => pif.management).$network
|
||||
for (const vif of vm.$VIFs) {
|
||||
vifsMap[vif.$ref] = networkRef
|
||||
}
|
||||
}
|
||||
|
||||
await this._migrateVMWithStorageMotion(vm, hostXapi, host, {
|
||||
await this._migrateVmWithStorageMotion(vm, hostXapi, host, {
|
||||
migrationNetwork: migrationNetworkId && hostXapi.getObject(migrationNetworkId),
|
||||
sr: srId && hostXapi.getObject(srId),
|
||||
vifsMap
|
||||
mapVdisSrs,
|
||||
mapVifsNetworks
|
||||
})
|
||||
} else {
|
||||
try {
|
||||
@ -1639,7 +1643,7 @@ export default class Xapi extends XapiBase {
|
||||
}
|
||||
|
||||
// Retry using motion storage.
|
||||
await this._migrateVMWithStorageMotion(vm, hostXapi, host, {})
|
||||
await this._migrateVmWithStorageMotion(vm, hostXapi, host, {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user