feat(xo-server/xen-servers): auto-connect to ejected host (#3738)
See #2238
This commit is contained in:
parent
e08d03687e
commit
7faff824ff
@ -9,6 +9,7 @@
|
||||
- [Users] Display user groups [#3719](https://github.com/vatesfr/xen-orchestra/issues/3719) (PR [#3740](https://github.com/vatesfr/xen-orchestra/pull/3740))
|
||||
- [VDI] Display VDI's SR [3021](https://github.com/vatesfr/xen-orchestra/issues/3021) (PR [#3285](https://github.com/vatesfr/xen-orchestra/pull/3285))
|
||||
- [Health, VM/disks] Display SR's container [#3021](https://github.com/vatesfr/xen-orchestra/issues/3021) (PRs [#3747](https://github.com/vatesfr/xen-orchestra/pull/3747), [#3751](https://github.com/vatesfr/xen-orchestra/pull/3751))
|
||||
- [Servers] Auto-connect to ejected host [#2238](https://github.com/vatesfr/xen-orchestra/issues/2238) (PR [#3738](https://github.com/vatesfr/xen-orchestra/pull/3738))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -71,6 +71,7 @@
|
||||
"http-server-plus": "^0.10.0",
|
||||
"human-format": "^0.10.0",
|
||||
"is-redirect": "^1.0.0",
|
||||
"iterable-backoff": "^0.0.0",
|
||||
"jest-worker": "^23.0.0",
|
||||
"js-yaml": "^3.10.0",
|
||||
"json-rpc-peer": "^0.15.3",
|
||||
|
@ -2,7 +2,7 @@ import { format } from 'json-rpc-peer'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export function set ({
|
||||
export function set({
|
||||
host,
|
||||
|
||||
// TODO: use camel case.
|
||||
@ -37,7 +37,7 @@ set.resolve = {
|
||||
|
||||
// FIXME: set force to false per default when correctly implemented in
|
||||
// UI.
|
||||
export function restart ({ host, force = true }) {
|
||||
export function restart({ host, force = true }) {
|
||||
return this.getXapi(host).rebootHost(host._xapiId, force)
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ restart.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function restartAgent ({ host }) {
|
||||
export function restartAgent({ host }) {
|
||||
return this.getXapi(host).restartHostAgent(host._xapiId)
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ export { restartAgent as restart_agent } // eslint-disable-line camelcase
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function setRemoteSyslogHost ({ host, syslogDestination }) {
|
||||
export function setRemoteSyslogHost({ host, syslogDestination }) {
|
||||
return this.getXapi(host).setRemoteSyslogHost(host._xapiId, syslogDestination)
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ setRemoteSyslogHost.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function start ({ host }) {
|
||||
export function start({ host }) {
|
||||
return this.getXapi(host).powerOnHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ start.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function stop ({ host }) {
|
||||
export function stop({ host }) {
|
||||
return this.getXapi(host).shutdownHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -123,8 +123,8 @@ stop.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function detach ({ host }) {
|
||||
return this.getXapi(host).ejectHostFromPool(host._xapiId)
|
||||
export function detach({ host }) {
|
||||
return this.detachHostFromPool(host._xapiId)
|
||||
}
|
||||
|
||||
detach.description = 'eject the host of a pool'
|
||||
@ -139,7 +139,7 @@ detach.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function enable ({ host }) {
|
||||
export function enable({ host }) {
|
||||
return this.getXapi(host).enableHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ enable.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function disable ({ host }) {
|
||||
export function disable({ host }) {
|
||||
return this.getXapi(host).disableHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ disable.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function forget ({ host }) {
|
||||
export function forget({ host }) {
|
||||
return this.getXapi(host).forgetHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ forget.resolve = {
|
||||
// Returns an array of missing new patches in the host
|
||||
// Returns an empty array if up-to-date
|
||||
// Throws an error if the host is not running the latest XS version
|
||||
export function listMissingPatches ({ host }) {
|
||||
export function listMissingPatches({ host }) {
|
||||
return this.getXapi(host).listMissingPoolPatchesOnHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -207,7 +207,7 @@ listMissingPatches.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function installPatch ({ host, patch: patchUuid }) {
|
||||
export function installPatch({ host, patch: patchUuid }) {
|
||||
return this.getXapi(host).installPoolPatchOnHost(patchUuid, host._xapiId)
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ installPatch.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function installAllPatches ({ host }) {
|
||||
export function installAllPatches({ host }) {
|
||||
return this.getXapi(host).installAllPoolPatchesOnHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ installAllPatches.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function emergencyShutdownHost ({ host }) {
|
||||
export function emergencyShutdownHost({ host }) {
|
||||
return this.getXapi(host).emergencyShutdownHost(host._xapiId)
|
||||
}
|
||||
|
||||
@ -256,7 +256,7 @@ emergencyShutdownHost.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function stats ({ host, granularity }) {
|
||||
export function stats({ host, granularity }) {
|
||||
return this.getXapiHostStats(host._xapiId, granularity)
|
||||
}
|
||||
|
||||
@ -276,7 +276,7 @@ stats.resolve = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
async function handleInstallSupplementalPack (req, res, { hostId }) {
|
||||
async function handleInstallSupplementalPack(req, res, { hostId }) {
|
||||
const xapi = this.getXapi(hostId)
|
||||
|
||||
// Timeout seems to be broken in Node 4.
|
||||
@ -293,7 +293,7 @@ async function handleInstallSupplementalPack (req, res, { hostId }) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function installSupplementalPack ({ host }) {
|
||||
export async function installSupplementalPack({ host }) {
|
||||
return {
|
||||
$sendTo: await this.registerHttpRequest(handleInstallSupplementalPack, {
|
||||
hostId: host.id,
|
||||
|
@ -1,6 +1,8 @@
|
||||
import createLogger from '@xen-orchestra/log'
|
||||
import { BaseError } from 'make-error'
|
||||
import { pDelay, ignoreErrors } from 'promise-toolbox'
|
||||
import { fibonacci } from 'iterable-backoff'
|
||||
import { findKey } from 'lodash'
|
||||
import { ignoreErrors } from 'promise-toolbox'
|
||||
import { noSuchObject } from 'xo-common/api-errors'
|
||||
|
||||
import Xapi from '../xapi'
|
||||
@ -18,6 +20,12 @@ import { Servers } from '../models/server'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PoolAlreadyConnected extends BaseError {
|
||||
constructor() {
|
||||
super("the server's pool is already connected")
|
||||
}
|
||||
}
|
||||
|
||||
const log = createLogger('xo:xo-mixins:xen-servers')
|
||||
|
||||
export default class {
|
||||
@ -260,7 +268,7 @@ export default class {
|
||||
const xapisByPool = this._xapisByPool
|
||||
const [{ $id: poolId }] = await xapi.getAllRecords('pool')
|
||||
if (xapisByPool[poolId] !== undefined) {
|
||||
throw new Error("the server's pool is already connected")
|
||||
throw new PoolAlreadyConnected()
|
||||
}
|
||||
|
||||
this._xapis[server.id] = xapisByPool[poolId] = xapi
|
||||
@ -464,4 +472,38 @@ export default class {
|
||||
findKey(this._xapis, candidate => candidate === sourceXapi)
|
||||
)::ignoreErrors()
|
||||
}
|
||||
|
||||
async detachHostFromPool(hostId) {
|
||||
const xapi = this.getXapi(hostId)
|
||||
const { address } = xapi.getObject(hostId)
|
||||
|
||||
await xapi.ejectHostFromPool(hostId)
|
||||
|
||||
this._getXenServer(findKey(this._xapis, candidate => candidate === xapi))
|
||||
.then(async ({ properties }) => {
|
||||
const { id } = await this.registerXenServer({
|
||||
...properties,
|
||||
host: address,
|
||||
})
|
||||
|
||||
for (const delay of fibonacci()
|
||||
.take(5)
|
||||
.toMs()
|
||||
.map(d => d * 60)) {
|
||||
await pDelay(delay)
|
||||
try {
|
||||
await this.connectXenServer(id)
|
||||
break
|
||||
} catch (error) {
|
||||
if (
|
||||
!(error instanceof PoolAlreadyConnected) &&
|
||||
error.code !== 'EHOSTUNREACH'
|
||||
) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
::ignoreErrors()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user