fix(xo-server-netbox): better handle missing uuid custom field (#5909)

Fixes #5905
See #5806
See #5834
See xoa-support#3812

- Check if `uuid` custom field has correctly been configured before synchronizing
- Delete VMs that don't have a UUID before synchronizing VMs to avoid conflicts
This commit is contained in:
Pierre Donias
2021-09-22 18:08:09 +02:00
committed by GitHub
parent ffb6a8fa3f
commit a995276d1e
2 changed files with 46 additions and 11 deletions

View File

@@ -13,6 +13,7 @@
- [SSH keys] Allow SSH key to be broken anywhere to avoid breaking page formatting (Thanks @tstivers1990!) [#5891](https://github.com/vatesfr/xen-orchestra/issues/5891) (PR [#5892](https://github.com/vatesfr/xen-orchestra/pull/5892))
- [Netbox] Handle nested prefixes by always assigning an IP to the smallest prefix it matches (PR [#5908](https://github.com/vatesfr/xen-orchestra/pull/5908))
- [Netbox] Better handling and error messages when encountering issues due to UUID custom field not being configured correctly [#5905](https://github.com/vatesfr/xen-orchestra/issues/5905) [#5806](https://github.com/vatesfr/xen-orchestra/issues/5806) [#5834](https://github.com/vatesfr/xen-orchestra/issues/5834) (PR [#5909](https://github.com/vatesfr/xen-orchestra/pull/5909))
### Packages to release

View File

@@ -167,7 +167,23 @@ class Netbox {
return results
}
async #checkCustomFields() {
const customFields = await this.#makeRequest('/extras/custom-fields/', 'GET')
const uuidCustomField = customFields.find(field => field.name === 'uuid')
if (uuidCustomField === undefined) {
throw new Error('UUID custom field was not found. Please create it manually from your Netbox interface.')
}
const { content_types: types } = uuidCustomField
if (!types.includes('virtualization.cluster') || !types.includes('virtualization.virtualmachine')) {
throw new Error(
'UUID custom field must be assigned to types virtualization.cluster and virtualization.virtualmachine'
)
}
}
async #synchronize(pools = this.#pools) {
await this.#checkCustomFields()
const xo = this.#xo
log.debug('synchronizing')
// Cluster type
@@ -218,6 +234,10 @@ class Netbox {
}
}
// FIXME: Should we deduplicate cluster names even though it also fails when
// a cluster within another cluster type has the same name?
// FIXME: Should we delete clusters from this cluster type that don't have a
// UUID?
Object.assign(
clusters,
keyBy(
@@ -237,20 +257,32 @@ class Netbox {
// VMs
const vms = xo.getObjects({ filter: object => object.type === 'VM' && pools.includes(object.$pool) })
const oldNetboxVms = keyBy(
flatten(
// FIXME: It should be doable with one request:
// `cluster_id=1&cluster_id=2` but it doesn't work
// https://netbox.readthedocs.io/en/stable/rest-api/filtering/#filtering-objects
await Promise.all(
pools.map(poolId =>
this.#makeRequest(`/virtualization/virtual-machines/?cluster_id=${clusters[poolId].id}`, 'GET')
)
let oldNetboxVms = flatten(
// FIXME: It should be doable with one request:
// `cluster_id=1&cluster_id=2` but it doesn't work
// https://netbox.readthedocs.io/en/stable/rest-api/filtering/#filtering-objects
await Promise.all(
pools.map(poolId =>
this.#makeRequest(`/virtualization/virtual-machines/?cluster_id=${clusters[poolId].id}`, 'GET')
)
),
'custom_fields.uuid'
)
)
const vmsWithNoUuid = oldNetboxVms.filter(vm => vm.custom_fields.uuid === null)
oldNetboxVms = omit(keyBy(oldNetboxVms, 'custom_fields.uuid'), null)
// Delete VMs that don't have a UUID custom field. This can happen if they
// were created manually or if the custom field config was changed after
// their creation
if (vmsWithNoUuid !== undefined) {
log.warn(`Found ${vmsWithNoUuid.length} VMs with no UUID. Deleting them.`)
await this.#makeRequest(
'/virtualization/virtual-machines/',
'DELETE',
vmsWithNoUuid.map(vm => ({ id: vm.id }))
)
}
// Build collections for later
const netboxVms = {} // VM UUID → Netbox VM
const vifsByVm = {} // VM UUID → VIF UUID[]
@@ -632,6 +664,8 @@ class Netbox {
'GET'
)
await this.#checkCustomFields()
if (clusterTypes.length !== 1) {
throw new Error('Could not properly write and read Netbox')
}