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