feat(xapi/pool_emergencyShutdown): new method

Related to #7277
This commit is contained in:
Julien Fontanet
2024-01-10 15:55:14 +01:00
parent 80097ea777
commit 0bbb0c289d
4 changed files with 109 additions and 1 deletions
+1
View File
@@ -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'
+1
View File
@@ -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",
+106
View File
@@ -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)
}
}
+1 -1
View File
@@ -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