@@ -1,4 +1,5 @@
|
||||
export { default as host } from './host.mjs'
|
||||
export { default as pool } from './pool.mjs'
|
||||
export { default as SR } from './sr.mjs'
|
||||
export { default as task } from './task.mjs'
|
||||
export { default as VBD } from './vbd.mjs'
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"@vates/async-each": "^1.0.0",
|
||||
"@vates/decorate-with": "^2.0.0",
|
||||
"@vates/nbd-client": "^3.0.0",
|
||||
"@vates/task": "^0.2.0",
|
||||
"@xen-orchestra/async-map": "^0.1.2",
|
||||
"@xen-orchestra/log": "^0.6.0",
|
||||
"d3-time-format": "^4.1.0",
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import { asyncEach } from '@vates/async-each'
|
||||
import { createLogger } from '@xen-orchestra/log'
|
||||
import { Task } from '@vates/task'
|
||||
|
||||
import { getCurrentVmUuid } from './_XenStore.mjs'
|
||||
|
||||
const noop = Function.prototype
|
||||
|
||||
async function pCatch(p, code, cb) {
|
||||
try {
|
||||
return await p
|
||||
} catch (error) {
|
||||
if (error.code === code) {
|
||||
return cb(error)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const { warn } = createLogger('xo:xapi:pool')
|
||||
|
||||
export default class Pool {
|
||||
async emergencyShutdown() {
|
||||
const poolMasterRef = this.pool.master
|
||||
|
||||
let currentVmRef
|
||||
try {
|
||||
currentVmRef = await this.call('VM.get_by_uuid', await getCurrentVmUuid())
|
||||
|
||||
// try to move current VM on pool master
|
||||
const hostRef = await this.call('VM.get_resident_on', currentVmRef)
|
||||
if (hostRef !== poolMasterRef) {
|
||||
await Task.run(
|
||||
{
|
||||
properties: {
|
||||
name: 'Migrating current VM to pool master',
|
||||
currentVm: { $ref: currentVmRef },
|
||||
poolMaster: { $ref: poolMasterRef },
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
await this.callAsync('VM.pool_migrate', currentVmRef, poolMasterRef, {})
|
||||
}
|
||||
).catch(noop)
|
||||
}
|
||||
} catch (error) {
|
||||
warn(error)
|
||||
}
|
||||
|
||||
await pCatch(this.call('pool.disable_ha'), 'HA_NOT_ENABLED', noop)
|
||||
|
||||
const hostRefs = await this.call('host.get_all')
|
||||
|
||||
// disable all hosts and suspend all VMs
|
||||
await asyncEach(hostRefs, async hostRef => {
|
||||
await this.call('host.disable', hostRef).catch(warn)
|
||||
|
||||
const [controlDomainRef, vmRefs] = await Promise.all([
|
||||
this.call('host.get_control_domain', hostRef),
|
||||
this.call('host.get_resident_VMs', hostRef),
|
||||
])
|
||||
|
||||
await asyncEach(vmRefs, vmRef => {
|
||||
// never stop current VM otherwise the emergencyShutdown process would be interrupted
|
||||
if (vmRef !== currentVmRef && vmRef !== controlDomainRef) {
|
||||
return Task.run(
|
||||
{
|
||||
properties: {
|
||||
name: 'suspending VM',
|
||||
host: { $ref: hostRef },
|
||||
vm: { $ref: vmRef },
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
await pCatch(this.callAsync('VM.suspend', vmRef), 'VM_BAD_POWER_STATE', noop)
|
||||
}
|
||||
).catch(noop)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const shutdownHost = ref =>
|
||||
Task.run(
|
||||
{
|
||||
properties: {
|
||||
name: 'shutting down host',
|
||||
host: { $ref: ref },
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
await this.callAsync('host.shutdown', ref)
|
||||
}
|
||||
).catch(noop)
|
||||
|
||||
// shutdown all non-pool master hosts
|
||||
await asyncEach(hostRefs, hostRef => {
|
||||
// pool master will be shutdown at the end
|
||||
if (hostRef !== poolMasterRef) {
|
||||
return shutdownHost(hostRef)
|
||||
}
|
||||
})
|
||||
|
||||
// shutdown pool master
|
||||
await shutdownHost(poolMasterRef)
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
<!--packages-start-->
|
||||
|
||||
- @xen-orchestra/backups patch
|
||||
- @xen-orchestra/xapi patch
|
||||
- @xen-orchestra/xapi minor
|
||||
- xen-api patch
|
||||
- xo-server patch
|
||||
- xo-server-load-balancer patch
|
||||
|
||||
Reference in New Issue
Block a user