feat(xo-server-netbox): synchronize VM platform (#6954)
See Zammad#12478 See https://xcp-ng.org/forum/topic/6902
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
9
packages/xo-server-netbox/src/slugify.js
Normal file
9
packages/xo-server-netbox/src/slugify.js
Normal 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, '-')
|
||||
}
|
||||
Reference in New Issue
Block a user