feat(xo-server-netbox): synchronize VM platform (#6954)

See Zammad#12478
See https://xcp-ng.org/forum/topic/6902
This commit is contained in:
Pierre Donias
2023-07-27 16:59:50 +02:00
committed by GitHub
parent fd4c56c8c2
commit 40e536ba61
4 changed files with 43 additions and 8 deletions

View File

@@ -8,8 +8,9 @@
> Users must be able to say: “Nice enhancement, I'm eager to test it”
- [Backup/Restore] Button to open the raw log in the REST API (PR [#6936](https://github.com/vatesfr/xen-orchestra/pull/6936))
- [Netbox] New major version. BREAKING: in order for this new version to work, you need to assign the type `virtualization > vminterface` to the custom field `UUID` in your Netbox instance. [See documentation](https://xen-orchestra.com/docs/advanced.html#netbox). [#6038](https://github.com/vatesfr/xen-orchestra/issues/6038) [#6135](https://github.com/vatesfr/xen-orchestra/issues/6135) [#6024](https://github.com/vatesfr/xen-orchestra/issues/6024) [#6036](https://github.com/vatesfr/xen-orchestra/issues/6036) [Forum#6070](https://xcp-ng.org/forum/topic/6070) [Forum#6149](https://xcp-ng.org/forum/topic/6149) [Forum#6332](https://xcp-ng.org/forum/topic/6332) (PR [#6950](https://github.com/vatesfr/xen-orchestra/pull/6950))
- [Netbox] New major version. BREAKING: in order for this new version to work, you need to assign the type `virtualization > vminterface` to the custom field `UUID` in your Netbox instance. [See documentation](https://xen-orchestra.com/docs/advanced.html#netbox). [#6038](https://github.com/vatesfr/xen-orchestra/issues/6038) [#6135](https://github.com/vatesfr/xen-orchestra/issues/6135) [#6024](https://github.com/vatesfr/xen-orchestra/issues/6024) [#6036](https://github.com/vatesfr/xen-orchestra/issues/6036) [Forum#6070](https://xcp-ng.org/forum/topic/6070) [Forum#6149](https://xcp-ng.org/forum/topic/6149) [Forum#6332](https://xcp-ng.org/forum/topic/6332) [Forum#6902](https://xcp-ng.org/forum/topic/6902) (PR [#6950](https://github.com/vatesfr/xen-orchestra/pull/6950))
- Synchronize VM description
- Synchronize VM platform
- Fix duplicated VMs in Netbox after disconnecting one pool
- Migrating a VM from one pool to another keeps VM data added manually
- Fix largest IP prefix being picked instead of smallest

View File

@@ -12,7 +12,7 @@ import { compareNames } from './name-dedup'
* @returns {Object|undefined} The patch that needs to be applied to older to get newer
*/
export default function diff(newer, older) {
if (typeof newer !== 'object') {
if (typeof newer !== 'object' || newer === null) {
return newer === older ? undefined : newer
}

View File

@@ -10,6 +10,7 @@ import trimEnd from 'lodash/trimEnd'
import diff from './diff'
import { deduplicateName } from './name-dedup'
import slugify from './slugify'
const log = createLogger('xo:netbox')
@@ -223,7 +224,7 @@ class Netbox {
log.info('Creating cluster type')
clusterType = await this.#request('/virtualization/cluster-types/', 'POST', {
name: CLUSTER_TYPE,
slug: CLUSTER_TYPE.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
slug: slugify(CLUSTER_TYPE),
description: 'Created by Xen Orchestra',
})
} else {
@@ -305,7 +306,7 @@ class Netbox {
log.info('Synchronizing VMs')
const createNetboxVm = (vm, cluster) => {
const createNetboxVm = async (vm, { cluster, platforms }) => {
const netboxVm = {
custom_fields: { uuid: vm.uuid },
name: vm.name_label.slice(0, NAME_MAX_LENGTH).trim(),
@@ -321,6 +322,23 @@ class Netbox {
memory: Math.floor(vm.memory.dynamic[1] / M),
cluster: cluster.id,
status: vm.power_state === 'Running' ? 'active' : 'offline',
platform: null,
}
const distro = vm.os_version?.distro
if (distro != null) {
const slug = slugify(distro)
let platform = find(platforms, { slug })
if (platform === undefined) {
// TODO: Should we also delete/update platforms in Netbox?
platform = await this.#request('/dcim/platforms/', 'POST', {
name: distro,
slug,
})
platforms[platform.id] = platform
}
netboxVm.platform = platform.id
}
// https://netbox.readthedocs.io/en/stable/release-notes/version-2.7/#api-choice-fields-now-use-string-values-3569
@@ -335,12 +353,19 @@ class Netbox {
}
// Some props need to be flattened to satisfy the POST request schema
const flattenNested = vm => ({ ...vm, cluster: vm.cluster?.id, status: vm.status?.value })
const flattenNested = vm => ({
...vm,
cluster: vm.cluster?.id ?? null,
status: vm.status?.value ?? null,
platform: vm.platform?.id ?? null,
})
const platforms = keyBy(await this.#request('/dcim/platforms'), '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
// necessary
const allNetboxVmsList = (await this.#request(`/virtualization/virtual-machines/`)).filter(
const allNetboxVmsList = (await this.#request('/virtualization/virtual-machines/')).filter(
netboxVm => Object.values(allClusters).find(cluster => cluster.id === netboxVm.cluster.id) !== undefined
)
// Then get only the ones from the pools we're synchronizing
@@ -376,7 +401,7 @@ class Netbox {
const netboxVm = allNetboxVms[vm.uuid]
delete poolNetboxVms[vm.uuid]
const updatedVm = createNetboxVm(vm, cluster)
const updatedVm = await createNetboxVm(vm, { cluster, platforms })
if (netboxVm !== undefined) {
// VM found in Netbox: update VM (I.1)
@@ -402,7 +427,7 @@ class Netbox {
const cluster = allClusters[pool?.uuid]
if (cluster !== undefined) {
// If the VM is found in XO: update it if necessary (II.1)
const updatedVm = createNetboxVm(vm, cluster)
const updatedVm = await createNetboxVm(vm, { cluster, platforms })
const patch = diff(updatedVm, flattenNested(netboxVm))
if (patch === undefined) {

View File

@@ -0,0 +1,9 @@
/**
* Transforms a string into a slug that respects the pattern ^[-a-zA-Z0-9_]+$
* required by Netbox
* @param {string} name
* @returns {string}
*/
export default function slugify(name) {
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-')
}