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:
@@ -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
|
||||
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user