fix(xen-api): correct $type for records from event

XenApi event system returns lowercased types which things difficult, for
instance, `Record#set_name_label` methods did not work for some VM
because the lib called `vm.set_name_label` instead of
`VM.set_name_label`.

To work-around this problem, a map of types from lowercased is
constructed at connection.
This commit is contained in:
Julien Fontanet 2019-02-24 14:40:30 +01:00
parent 685355c6fb
commit 12a7000e36

View File

@ -7,7 +7,6 @@ import { BaseError } from 'make-error'
import { EventEmitter } from 'events'
import { fibonacci } from 'iterable-backoff'
import {
filter,
forEach,
isArray,
isInteger,
@ -403,42 +402,55 @@ export class Xapi extends EventEmitter {
)
}
connect() {
async connect() {
const { status } = this
if (status === CONNECTED) {
return Promise.reject(new Error('already connected'))
throw new Error('already connected')
}
if (status === CONNECTING) {
return Promise.reject(new Error('already connecting'))
throw new Error('already connecting')
}
const auth = this._auth
if (auth === undefined) {
return Promise.reject(new Error('missing credentials'))
throw new Error('missing credentials')
}
this._sessionId = CONNECTING
return this._transportCall('session.login_with_password', [
try {
const [methods, sessionId] = await Promise.all([
this._transportCall('system.listMethods'),
this._transportCall('session.login_with_password', [
auth.user,
auth.password,
]).then(
async sessionId => {
]),
])
// Uses introspection to list available types.
const types = (this._types = methods
.filter(isGetAllRecordsMethod)
.map(method => method.slice(0, method.indexOf('.'))))
this._lcToTypes = { __proto__: null }
types.forEach(type => {
const lcType = type.toLowerCase()
if (lcType !== type) {
this._lcToTypes[lcType] = type
}
})
this._sessionId = sessionId
this._pool = (await this.getAllRecords('pool'))[0]
debug('%s: connected', this._humanId)
this.emit(CONNECTED)
},
error => {
} catch (error) {
this._sessionId = null
throw error
}
)
}
disconnect() {
@ -911,7 +923,12 @@ export class Xapi extends EventEmitter {
_processEvents(events) {
forEach(events, event => {
const { class: type, ref } = event
let type = event.class
const lcToTypes = this._lcToTypes
if (type in lcToTypes) {
type = lcToTypes[type]
}
const { ref } = event
if (event.operation === 'del') {
this._removeObject(type, ref)
} else {
@ -996,17 +1013,11 @@ export class Xapi extends EventEmitter {
//
// It also has to manually get all objects first.
_watchEventsLegacy() {
const getAllObjects = () => {
return this._sessionCall('system.listMethods').then(methods => {
// Uses introspection to determine the methods to use to get
// all objects.
const getAllRecordsMethods = filter(methods, isGetAllRecordsMethod)
const getAllObjects = async () => {
return Promise.all(
map(getAllRecordsMethods, method =>
this._sessionCall(method).then(
this._types.map(type =>
this._sessionCall(`${type}.get_all_records`).then(
objects => {
const type = method.slice(0, method.indexOf('.')).toLowerCase()
forEach(objects, (object, ref) => {
this._addObject(type, ref, object)
})
@ -1019,7 +1030,6 @@ export class Xapi extends EventEmitter {
)
)
)
})
}
const watchEvents = () =>