Revert "feat(xen-api): implement fallback addresses (#6061)" (#6198)

This reverts commit 6b8a345241.
This commit is contained in:
Julien Fontanet 2022-04-20 11:58:15 +02:00 committed by GitHub
parent b1429e1df3
commit 1646c50a94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 133 deletions

View File

@ -44,7 +44,7 @@ const usage = 'Usage: xen-api <url> [<user> [<password>]]'
async function main(createClient) {
const opts = minimist(process.argv.slice(2), {
string: ['session-id', 'fallback-addresses'],
string: ['session-id'],
boolean: ['allow-unauthorized', 'help', 'read-only', 'verbose'],
alias: {
@ -82,10 +82,6 @@ async function main(createClient) {
})
}
let fallBackAddresses = []
if (opts['fallback-addresses']) {
fallBackAddresses = opts['fallback-addresses'].split(',')
}
const xapi = createClient({
url: opts._[0],
allowUnauthorized: opts.au,
@ -93,7 +89,6 @@ async function main(createClient) {
debounce: opts.debounce != null ? +opts.debounce : null,
readOnly: opts.ro,
syncStackTraces: true,
fallBackAddresses,
})
await xapi.connect()

View File

@ -8,7 +8,6 @@ import noop from 'lodash/noop'
import omit from 'lodash/omit'
import ProxyAgent from 'proxy-agent'
import { coalesceCalls } from '@vates/coalesce-calls'
import { synchronized } from 'decorator-synchronized'
import { Collection } from 'xo-collection'
import { EventEmitter } from 'events'
import { Index } from 'xo-collection/index'
@ -121,7 +120,7 @@ export class Xapi extends EventEmitter {
delete url.username
delete url.password
}
this._fallBackAddresses = opts.fallBackAddresses ?? []
this._allowUnauthorized = opts.allowUnauthorized
if (opts.httpProxy !== undefined) {
this._httpAgent = new ProxyAgent(this._httpProxy)
@ -682,85 +681,6 @@ export class Xapi extends EventEmitter {
// Private
// ===========================================================================
@synchronized()
async _updateUrlFromFallbackAdresses(method, args, startTime) {
debug('%s: will try to find a new master', this._humanId)
const hostAddresses = this._fallBackAddresses
// there can be a master only if there is more than 1 host
if (hostAddresses.length < 2) {
return false
}
// another call to _updateUrlFromFallbackAdresses has already connected us to the right host
try {
await this._transport('session.get_auth_user_name', [])
debug('%s: host was already ok', this._humanId)
// host is ok, nothing to do here
return true
} catch (error) {
if (!['EHOSTUNREACH', 'HOST_IS_SLAVE', 'ENOTFOUND', 'MESSAGE_PARAMETER_COUNT_MISMATCH'].includes(error.code)) {
throw this._augmentCallError(error, method, args, startTime)
}
}
for (const hostAdress of hostAddresses) {
// we already tested the current master
if (hostAdress === this._url.hostname) {
debug(`%s: don't recheck currrent host`, this._humanId)
continue
}
// since this method is @syncrhonized , there can be only on call at once
this._setUrl({ ...this._url, hostname: hostAdress })
try {
// will not succeed without sessionId, but I only want to know if this host is entitled to answer (he's the master)
await this._transport('session.get_auth_user_name', [])
// success
return true
} catch (error) {
// this host is also down, try the next one
if (error.code === 'EHOSTUNREACH' || error.code === 'ENOTFOUND') {
debug(`%s: slave %s is alsoa unreachable`, this._humanId, hostAdress)
continue
}
if (error.code === 'HOST_IS_SLAVE') {
debug('%s: slave %s told us the master is %s', this._humanId, hostAdress, error.params[0])
this._setUrl({ ...this._url, hostname: hostAdress })
return true // we found the master no need to check for the other slave
}
if (error.code === 'MESSAGE_PARAMETER_COUNT_MISMATCH') {
debug('%s: found new master %s master', this._humanId, hostAdress)
// lucky : we found the master with the first host answering
return true // we found the master no need to check for the other slave
}
// any other error should be reported
throw this._augmentCallError(error, method, args, startTime)
}
}
return false
}
_augmentCallError(error, method, args, startTime) {
// do not log the session ID
//
// TODO: should log at the session level to avoid logging sensitive
// values?
const params = args[0] === this._sessionId ? args.slice(1) : args
error.call = {
method,
params:
// it pass server's credentials as param
method === 'session.login_with_password' ? '* obfuscated *' : replaceSensitiveValues(params, '* obfuscated *'),
}
debug('%s: %s(...) [%s] =!> %s', this._humanId, method, ms(Date.now() - startTime), error)
return error
}
async _call(method, args, timeout = this._callTimeout(method, args)) {
const startTime = Date.now()
try {
@ -768,14 +688,24 @@ export class Xapi extends EventEmitter {
debug('%s: %s(...) [%s] ==> %s', this._humanId, method, ms(Date.now() - startTime), kindOf(result))
return result
} catch (error) {
if (this._fallBackAddresses?.length > 1 && ['EHOSTUNREACH', 'HOST_IS_SLAVE', 'ENOTFOUND'].includes(error.code)) {
const updatedHostUrl = await this._updateUrlFromFallbackAdresses(method, args, startTime)
if (updatedHostUrl) {
// try again
return this._call(method, args, timeout)
}
// do not log the session ID
//
// TODO: should log at the session level to avoid logging sensitive
// values?
const params = args[0] === this._sessionId ? args.slice(1) : args
error.call = {
method,
params:
// it pass server's credentials as param
method === 'session.login_with_password'
? '* obfuscated *'
: replaceSensitiveValues(params, '* obfuscated *'),
}
throw this._augmentCallError(error, method, args, startTime)
debug('%s: %s(...) [%s] =!> %s', this._humanId, method, ms(Date.now() - startTime), error)
throw error
}
}
@ -852,8 +782,8 @@ export class Xapi extends EventEmitter {
// unnecessary renewal
_sessionOpenRetryOptions = {
tries: 2,
when: [{ code: 'HOST_IS_SLAVE' }],
onRetry: async error => {
when: { code: 'HOST_IS_SLAVE' },
onRetry: error => {
this._setUrl({ ...this._url, hostname: error.params[0] })
},
}
@ -1120,6 +1050,7 @@ export class Xapi extends EventEmitter {
delete taskWatchers[ref]
}
}
// read-only call, automatically retry in case of connection issues
_roCall(method, args) {
return pRetry(() => this._sessionCall(method, args), this._roCallRetryOptions)
@ -1160,7 +1091,6 @@ export class Xapi extends EventEmitter {
await this._refreshCachedRecords(types)
this._resolveObjectsFetched()
this._resolveObjectsFetched = undefined
this.emit('eventFetchedSuccess')
// event loop
const debounce = this._debounce
@ -1192,10 +1122,6 @@ export class Xapi extends EventEmitter {
// eslint-disable-next-line no-labels
continue mainLoop
}
if (code === 'EHOSTUNREACH') {
// maybe the master has been demoted
await this._findCurrentMaster()
}
this.emit('eventFetchingError', error)
this._watchEventsError = error

View File

@ -112,10 +112,6 @@ set.params = {
optional: true,
type: ['string', 'null'],
},
fallbackAddresses: {
type: ['string', 'null'],
optional: true,
},
}
// -------------------------------------------------------------------

View File

@ -14,7 +14,7 @@ import * as XenStore from '../_XenStore.mjs'
import Xapi from '../xapi/index.mjs'
import xapiObjectToXo from '../xapi-object-to-xo.mjs'
import XapiStats from '../xapi-stats.mjs'
import { camelToSnakeCase, forEach, isEmpty, noop, popProperty } from '../utils.mjs'
import { camelToSnakeCase, forEach, isEmpty, popProperty } from '../utils.mjs'
import { Servers } from '../models/server.mjs'
// ===================================================================
@ -133,7 +133,7 @@ export default class {
async updateXenServer(
id,
{ allowUnauthorized, enabled, error, host, label, password, readOnly, username, httpProxy, fallbackAddresses }
{ allowUnauthorized, enabled, error, host, label, password, readOnly, username, httpProxy }
) {
const server = await this._getXenServer(id)
const xapi = this._xapis[id]
@ -176,9 +176,6 @@ export default class {
// if value is null, pass undefined to the model , so it will delete this optionnal property from the Server object
server.set('httpProxy', httpProxy === null ? undefined : httpProxy)
}
if (fallbackAddresses !== undefined) {
server.set('fallBackAddresses', fallbackAddresses === null ? undefined : JSON.stringify(fallbackAddresses))
}
await this._servers.update(server)
}
@ -300,14 +297,6 @@ export default class {
})
}
async _updateFallBackAdresses(xapi) {
const hosts = await xapi.getAllRecords('host')
const fallbackAddresses = hosts.map(({ address }) => address)
for (const host of hosts) {
await this.updateXenServer(host.id, { fallbackAddresses })
}
}
async connectXenServer(id) {
const server = await this.getXenServer(id)
@ -316,10 +305,7 @@ export default class {
}
const { config } = this._app
let fallBackAddresses
try {
fallBackAddresses = JSON.parse(server.fallBackAddresses)
} catch (e) {}
let { poolMarkingInterval, poolMarkingMaxAge, poolMarkingPrefix, ...xapiOptions } = config.get('xapiOptions')
poolMarkingInterval = parseDuration(poolMarkingInterval)
poolMarkingMaxAge = parseDuration(poolMarkingMaxAge)
@ -330,7 +316,6 @@ export default class {
...xapiOptions,
httpProxy: server.httpProxy,
fallBackAddresses,
guessVhdSizeOnImport: config.get('guessVhdSizeOnImport'),
auth: {
@ -356,8 +341,6 @@ export default class {
throw new PoolAlreadyConnected(poolId, serverIdsByPool[poolId], server.id)
}
await this._updateFallBackAdresses(xapi).catch(noop)
serverIdsByPool[poolId] = server.id
xapi.xo = (() => {
@ -486,14 +469,6 @@ export default class {
this.updateXenServer(id, { error: null })::ignoreErrors()
const xo = this
// when the data are loaded, update the fall back adresses of all the hosts of this pool
xapi.once('eventFetchedSuccess', async function eventFetchedSuccessListener() {
const hosts = await this.getAllRecords('host')
const hostAddresses = hosts.map(({ address }) => address).join(';')
await xo.updateXenServer(server.id, { fallbackAddresses: hostAddresses })
})
xapi.once('eventFetchingError', function eventFetchingErrorListener() {
const timeout = setTimeout(() => {
xapi.xo.uninstall()