feat(xo-server-netbox): synchronize VM tags
Fixes #5899 See Zammad#12478 See https://xcp-ng.org/forum/topic/6902
This commit is contained in:
parent
155be7fd95
commit
3081810450
@ -7,6 +7,8 @@
|
||||
|
||||
> Users must be able to say: “Nice enhancement, I'm eager to test it”
|
||||
|
||||
- [Netbox] Synchronize VM tags [#5899](https://github.com/vatesfr/xen-orchestra/issues/5899) [Forum#6902](https://xcp-ng.org/forum/topic/6902) (PR [#6957](https://github.com/vatesfr/xen-orchestra/pull/6957))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
> Users must be able to say: “I had this issue, happy to know it's fixed”
|
||||
@ -34,6 +36,7 @@
|
||||
- xen-api patch
|
||||
- xo-server patch
|
||||
- xo-server-auth-ldap patch
|
||||
- xo-server-netbox minor
|
||||
- xo-web patch
|
||||
|
||||
<!--packages-end-->
|
||||
|
@ -16,6 +16,16 @@ export default function diff(newer, older) {
|
||||
return newer === older ? undefined : newer
|
||||
}
|
||||
|
||||
// For arrays, they must be exactly the same or we pass the new one entirely
|
||||
if (Array.isArray(newer)) {
|
||||
if (newer.length !== older.length || newer.some((value, index) => diff(value, older[index]) !== undefined)) {
|
||||
return newer
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// For objects, we only need to pass the properties that are different
|
||||
newer = { ...newer }
|
||||
Object.keys(newer).forEach(key => {
|
||||
if ((key === 'name' && compareNames(newer[key], older[key])) || diff(newer[key], older?.[key]) === undefined) {
|
||||
|
@ -308,7 +308,7 @@ class Netbox {
|
||||
|
||||
log.info('Synchronizing VMs')
|
||||
|
||||
const createNbVm = async (xoVm, { nbCluster, nbPlatforms }) => {
|
||||
const createNbVm = async (xoVm, { nbCluster, nbPlatforms, nbTags }) => {
|
||||
const nbVm = {
|
||||
custom_fields: { uuid: xoVm.uuid },
|
||||
name: xoVm.name_label.slice(0, NAME_MAX_LENGTH).trim(),
|
||||
@ -325,6 +325,7 @@ class Netbox {
|
||||
cluster: nbCluster.id,
|
||||
status: xoVm.power_state === 'Running' ? 'active' : 'offline',
|
||||
platform: null,
|
||||
tags: [],
|
||||
}
|
||||
|
||||
const distro = xoVm.os_version?.distro
|
||||
@ -343,6 +344,32 @@ class Netbox {
|
||||
nbVm.platform = nbPlatform.id
|
||||
}
|
||||
|
||||
const nbVmTags = []
|
||||
for (const tag of xoVm.tags) {
|
||||
const slug = slugify(tag)
|
||||
let nbTag = find(nbTags, { slug })
|
||||
if (nbTag === undefined) {
|
||||
// TODO: Should we also delete/update tags in Netbox?
|
||||
nbTag = await this.#request('/extras/tags/', 'POST', {
|
||||
name: tag,
|
||||
slug,
|
||||
color: '2598d9',
|
||||
description: 'XO tag',
|
||||
})
|
||||
nbTags[nbTag.id] = nbTag
|
||||
}
|
||||
|
||||
// Edge case: tags "foo" and "Foo" would have the same slug. It's
|
||||
// allowed in XO but not in Netbox so in that case, we only add it once
|
||||
// to Netbox.
|
||||
if (find(nbVmTags, { id: nbTag.id }) === undefined) {
|
||||
nbVmTags.push({ id: nbTag.id })
|
||||
}
|
||||
}
|
||||
|
||||
// Sort them so that they can be compared by diff()
|
||||
nbVm.tags = nbVmTags.sort(({ id: id1 }, { id: id2 }) => (id1 < id2 ? -1 : 1))
|
||||
|
||||
// https://netbox.readthedocs.io/en/stable/release-notes/version-2.7/#api-choice-fields-now-use-string-values-3569
|
||||
if (
|
||||
this.#netboxApiVersion !== undefined &&
|
||||
@ -360,9 +387,12 @@ class Netbox {
|
||||
cluster: nbVm.cluster?.id ?? null,
|
||||
status: nbVm.status?.value ?? null,
|
||||
platform: nbVm.platform?.id ?? null,
|
||||
// Sort them so that they can be compared by diff()
|
||||
tags: nbVm.tags.map(nbTag => ({ id: nbTag.id })).sort(({ id: id1 }, { id: id2 }) => (id1 < id2 ? -1 : 1)),
|
||||
})
|
||||
|
||||
const nbPlatforms = keyBy(await this.#request('/dcim/platforms/'), 'id')
|
||||
const nbTags = keyBy(await this.#request('/extras/tags/'), 'id')
|
||||
|
||||
// Get all the VMs in the cluster type "XCP-ng Pool" even from clusters
|
||||
// we're not synchronizing right now, so we can "migrate" them back if
|
||||
@ -401,7 +431,7 @@ class Netbox {
|
||||
const nbVm = allNbVms[xoVm.uuid]
|
||||
delete xoPoolNbVms[xoVm.uuid]
|
||||
|
||||
const updatedVm = await createNbVm(xoVm, { nbCluster, nbPlatforms })
|
||||
const updatedVm = await createNbVm(xoVm, { nbCluster, nbPlatforms, nbTags })
|
||||
|
||||
if (nbVm !== undefined) {
|
||||
// VM found in Netbox: update VM (I.1)
|
||||
@ -427,7 +457,7 @@ class Netbox {
|
||||
const nbCluster = allNbClusters[xoPool?.uuid]
|
||||
if (nbCluster !== undefined) {
|
||||
// If the VM is found in XO: update it if necessary (II.1)
|
||||
const updatedVm = await createNbVm(xoVm, { nbCluster, nbPlatforms })
|
||||
const updatedVm = await createNbVm(xoVm, { nbCluster, nbPlatforms, nbTags })
|
||||
const patch = diff(updatedVm, flattenNested(nbVm))
|
||||
|
||||
if (patch === undefined) {
|
||||
|
Loading…
Reference in New Issue
Block a user