feat(xo-server/xen-servers): auto-connect to ejected host (#3738)

See #2238
This commit is contained in:
badrAZ 2018-12-04 13:28:52 +01:00 committed by Julien Fontanet
parent e08d03687e
commit 7faff824ff
4 changed files with 64 additions and 20 deletions

View File

@ -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

View File

@ -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",

View File

@ -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,

View File

@ -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()
}
}