summaryrefslogtreecommitdiffstats
path: root/server/lib/external-backends/backends/idoit-backend.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/external-backends/backends/idoit-backend.js')
-rw-r--r--server/lib/external-backends/backends/idoit-backend.js1113
1 files changed, 695 insertions, 418 deletions
diff --git a/server/lib/external-backends/backends/idoit-backend.js b/server/lib/external-backends/backends/idoit-backend.js
index 1d3ac6f..0a8b164 100644
--- a/server/lib/external-backends/backends/idoit-backend.js
+++ b/server/lib/external-backends/backends/idoit-backend.js
@@ -166,10 +166,7 @@ class IdoitBackend extends ExternalBackends {
*
* credentials: <BACKEND_CREDENTIALS>
* The client parameters are all optional.
- * client: {
- * title: <CLIENT_TITLE>, parentId: <PARENT_ID>,
- * network: { mac: <MAC_ADDRESS>, ip: <IP_ADDRESS> }
- * }
+ * If given, the values will get updated after the client is createdö
*/
async addClient (credentials, client) {
const c = this.mapCredentials(credentials)
@@ -183,200 +180,14 @@ class IdoitBackend extends ExternalBackends {
}
client.parentId = parseInt(client.parentId)
+ // Hardcoded id from the Freiburg idoit, should be set in the dynamic backend settings
if (client.type === 'CLIENT') {
params['type'] = 10
- if (client.parentId) params.categories.C__CATG__LOCATION = { 'data': { 'parent': client.parentId } }
} else if (client.type === 'SERVER') {
params['type'] = 5
-
- if (client.location && client.location.bay === null) params.categories.C__CATG__LOCATION = { 'data': { 'parent': client.parentId, 'option': client.location.assembly, 'insertion': client.location.insertion, 'pos': client.location.slot } }
- if (client.formfactor) params.categories.C__CATG__FORMFACTOR = { 'data': { 'formfactor': client.formfactor.formfactor, 'rackunits': client.formfactor.rackunits } }
-
- // Rack segmentation
- if (client.location.bay !== undefined && client.location.bay !== null) {
- // Get all assigned objects of the rack (parentid) to check for existing rack segments at slot position.
- const rackobjectsBody = this.getBody('cmdb.category.read', { 'apikey': c.apikey, 'object': client.parentId, 'objID': client.parentId, 'category': 'C__CATG__OBJECT' }, 'get_rack_objects')
- const rackobjects = await this.axiosRequest(c.url, [rackobjectsBody], headers)
-
- // Get the name of the rack
- console.log('')
- console.log('Get Rack Name:')
- const rackBody = this.getBody('cmdb.category.read', { 'apikey': c.apikey, 'object': client.parentId, 'objID': client.parentId, 'category': 'C__CATG__GLOBAL' }, 'get_rack')
- const rack = await this.axiosRequest(c.url, [rackBody], headers)
-
- if (!rack[0].result) return { error: 'IDOIT_ERROR', message: rack[0].error.message }
-
- const rackName = rack[0].result[0].title
-
- let objectPositionBodies = []
-
- // For each segmentation object in the rack get the slot number
- console.log('')
- console.log('Get Slot IDs Request:')
- for (let obj in rackobjects[0].result) {
- const object = rackobjects[0].result[obj]
- if (object.assigned_object.type !== 'C__OBJTYPE__RACK_SEGMENT') continue
- objectPositionBodies.push(this.getBody('cmdb.category.read', { 'apikey': c.apikey, 'object': object.objID, 'objID': object.objID, 'category': 'C__CATG__LOCATION' }, 'get_rack_object_position_' + object.objID))
- }
- let objectPositions = await this.axiosRequest(c.url, objectPositionBodies, headers)
- if (objectPositions.length >= 1) objectPositions = objectPositions.filter(x => parseInt(x.result[0].pos.title) === parseInt(client.location.slot))
-
- // There should only be one segment object for the rack slot if so set it as parent
- var chassisId
- if (objectPositions.length === 1) chassisId = parseInt(objectPositions[0].result[0].objID)
- else {
- // Create a new rack segment
- const createSegmentParamObject = {
- 'apikey': c.apikey,
- 'type': 92,
- 'title': rackName + ' Slot ' + client.location.slot,
- 'categories': {
- 'C__CATS__CHASSIS': {
- 'data': {
- 'front_x': 2,
- 'front_y': 1,
- 'rear_x': 0,
- 'rear_y': 0
- }
- },
- 'C__CATS__CHASSIS_SLOT': [
- {
- 'title': 'Bay 1',
- 'insertion': 'front',
- 'from_x': 0,
- 'to_x': 0,
- 'from_y': 0,
- 'to_y': 0
- },
- {
- 'title': 'Bay 2',
- 'insertion': 'front',
- 'from_x': 1,
- 'to_x': 1,
- 'from_y': 0,
- 'to_y': 0
- }
- ],
- 'C__CATG__LOCATION': {
- 'data': {
- 'parent': client.parentId,
- 'option': client.location.option,
- 'insertion': client.location.insertion,
- 'pos': client.location.slot
- }
- }
- }
- }
-
- console.log('')
- console.log('Create Segment Request:')
- const createSegmentParam = this.getBody('cmdb.object.create', createSegmentParamObject, 'create_segment')
- const createSegment = await this.axiosRequest(c.url, [createSegmentParam], headers)
- chassisId = createSegment[0].result.id
-
- /*
- // Set the new rack units height. (Needs an extra request, why? I DONT KNOW... idoit...)
- const setSegmentSizeParams = this.getBody('cmdb.category.save', { 'apikey': c.apikey,
- 'object': chassisId,
- 'objID': chassisId,
- 'category': 'C__CATG__FORMFACTOR',
- 'data': { 'rackunits': client.formfactor.rackunits } }, 'set_segment_size')
- await this.axiosRequest(c.url, [setSegmentSizeParams], headers)
- */
- }
- }
- }
-
- // Add categories to the object
- if (client.uuid) params.categories.C__CATG__MODEL = { 'data': { 'productid': client.uuid } }
- if (client.networks) {
- params.categories.C__CATG__IP = []
- for (let index in client.networks) {
- const network = client.networks[index]
- let networkparams = {}
- if (network.ip) networkparams.ipv4_address = network.ip
- if (network.hostname) networkparams.hostname = network.hostname
- if (network.domain) networkparams.domain = network.domain
- if (network.net) networkparams.net = network.net
- if (network.primary) networkparams.primary = network.primary ? 1 : 0
- params.categories.C__CATG__IP.push(networkparams)
- }
- }
-
- // Add contact assignment to the object.
- if (client.contacts) {
- // Get the persons ids.
- let readPersonBodies = []
- for (let index in client.contacts) {
- readPersonBodies.push(this.getBody('cmdb.objects.read', {
- 'apikey': c.apikey,
- 'filter': {
- 'type': 'C__OBJTYPE__PERSON',
- 'first_name': client.contacts[index].first_name,
- 'last_name': client.contacts[index].last_name
- }
- }, 'read_persons_' + index))
- }
- console.log('')
- console.log('Read Person Request:')
- const requestReadPersons = await this.axiosRequest(c.url, readPersonBodies, headers)
- if (requestReadPersons.error) return requestReadPersons
- const error = requestReadPersons.filter(x => x.error)
-
- if (error.length === 0) {
- const personIds = requestReadPersons.map(x => {
- if (x.result.length === 1) return x.result[0].id
- }).filter(Boolean)
- params.categories.C__CATG__CONTACT = []
- for (let index in personIds) {
- params.categories.C__CATG__CONTACT.push({
- 'contact': personIds[index]
- })
- }
- } else console.log(error)
- }
-
- // Add operating system information.
- if (client.runtime && client.runtime.operating_system) {
- // Get the operating system ids.
- console.log('')
- console.log('Get OS Request:')
- const getOSParam = {
- 'apikey': c.apikey,
- 'filter': {
- 'type': 35, // 35 = Operating System
- 'title': client.runtime.operating_system.name
- }
- }
- const getOSBody = this.getBody('cmdb.objects.read', getOSParam, 'get_os')
- const requestGetOS = await this.axiosRequest(c.url, [getOSBody], headers)
-
- // Extra request for getting the id of the version number
- console.log('')
- console.log('Get OS-Version Request:')
- const getOSVersionParam = {
- 'apikey': c.apikey,
- 'objID': requestGetOS[0].result[0].id,
- 'catgID': 'C__CATG__VERSION'
- }
- const getOSVersionBody = this.getBody('cmdb.category.read', getOSVersionParam, 'get_os_version')
- const requestGetOSVersion = await this.axiosRequest(c.url, [getOSVersionBody], headers)
- const osVersion = requestGetOSVersion[0].result.filter(x => x.title === client.runtime.operating_system.version)
-
- // Add the result of the OS request (ids) to the create request.
- if (requestGetOS[0].result) {
- params.categories.C__CATG__OPERATING_SYSTEM = {
- 'data': {
- 'application': requestGetOS[0].result[0].id,
- 'assigned_version': osVersion[0].id
- }
- }
- }
}
// Send the create request.
- console.log('')
- console.log('Create Client Request:')
const body = this.getBody('cmdb.object.create', params, 'client_create')
const requestCreate = await this.axiosRequest(c.url, [body], headers)
@@ -384,82 +195,21 @@ class IdoitBackend extends ExternalBackends {
if (requestCreate.error) return { error: requestCreate.errno, message: 'Connection was refused.' }
else if (requestCreate[0].error) return { error: 'IDOIT_ERROR', message: requestCreate[0].error.message }
- // Add mac address: Network port is a subcategory of network so it need an extra request.
- let macRequests = []
- const hostnameIds = requestCreate[0].result.categories.C__CATG__IP
-
- if (client.networks) {
- let macBodies = []
- for (let index in client.networks) {
- const network = client.networks[index]
- // For the ip adresses
- // network.id = requestCreate[0].result.categories.C__CATG__IP[index]
- let addresses = []
- // Push the ids as string
- if (hostnameIds.length > index) addresses.push('' + hostnameIds[index])
-
- let paramsMac = {
- 'object': requestCreate[0].result.id,
- 'objID': requestCreate[0].result.id,
- 'category': 'C__CATG__NETWORK_PORT',
- 'data': {
- 'mac': network.mac,
- 'addresses': addresses
- },
- 'apikey': c.apikey
- }
-
- if (network.device) {
- if (network.device.speed) {
- paramsMac.data.speed = parseFloat(network.device.speed)
- // MB/s GB/s ... etc not supported?! Only Mbit/s Gbit/s ...
- paramsMac.data.speed_type = null
- }
-
- if (network.device.name) paramsMac.data.title = network.device.name
- if (network.device.type) paramsMac.data.port_type = network.device.type
- }
-
- macBodies.push(this.getBody('cmdb.category.save', paramsMac, 'add_mac_address_' + index))
- }
-
- console.log('')
- console.log('Add MAC Request:')
- const response = await this.axiosRequest(c.url, macBodies, headers)
- macRequests.push(response)
- }
-
- // If chassis id is set, assign the object to the chassis bay
- if (chassisId) {
- // Read bay ids
- const paramsSlots = {
- 'object': chassisId,
- 'objID': chassisId,
- 'category': 'C__CATS__CHASSIS_SLOT',
- 'apikey': c.apikey
- }
-
- console.log('')
- console.log('Read Rack Slots:')
- const readSlotsParam = this.getBody('cmdb.category.read', paramsSlots, 'read_slots')
- const readSlots = await this.axiosRequest(c.url, [readSlotsParam], headers)
- const bays = readSlots[0].result
-
- console.log('')
- console.log('Assign to Rack Slot:')
- const assignToSlotBody = this.getBody('cmdb.category.save', { 'apikey': c.apikey,
- 'objID': chassisId,
- 'object': chassisId,
- 'category': 'C__CATS__CHASSIS_DEVICES',
- 'data': { 'assigned_device': requestCreate[0].result.id, 'assigned_slots': [bays[client.location.bay].id] } }, 'assign_to_slot')
- await this.axiosRequest(c.url, [assignToSlotBody], headers)
- }
+ // Add id to the client and call the update method for all the other hardware information
+ client.id = requestCreate[0].result.id
+ const update = await this.updateClient(credentials, client)
// Purpose for Clients:
// 1 = Production | 5 = PVS
// 2 = Test | 7 = Pool PC
// 3 = Quality Assurance | 8 = Mitarbeiter Arbeitsplatz
- return { succes: true, id: requestCreate[0].result.id, type: params.type, message: requestCreate[0].result.message, macRequests: macRequests }
+ return {
+ succes: true,
+ id: requestCreate[0].result.id,
+ type: params.type,
+ message: requestCreate[0].result.message,
+ responses: [requestCreate, ...update.response]
+ }
}
/*
@@ -468,11 +218,43 @@ class IdoitBackend extends ExternalBackends {
* credentials: <BACKEND_CREDENTIALS>
* The client parameters are all optional.
* client: {
- * id: <CLIENT_ID>, title: <CLIENT_TITLE>, parentId: <PARENT_ID>,
- * system: { model: <SYSTEM_MODEL>, manufacturer: <SYSTEM_MANUFACTURER>, serialnumber: <SYSTEM_SERIALNUMBER> },
- * cpu: { model: <CPU_MODEL>, manufacturer: <CPU_MANUFACTURER>, type: <CPU_TYPE>, frequency: <CPU_FREQUENCY>, cores: <CPU_CORES> },
- * ram: [{ title: <RAM_TITLE>, manufacturer: <RAM_MANUFACTURER>, type: <RAM_TYPE>, capacity: <RAM_CAPACITY>, unit: <RAM_UNIT> }, ...],
- * drives: [{model: <DRIVE_MODEL>,}, serial: <DRIVE_SERIAL>, capacity: <DRIVE_CAPACITY>, unit: <DRIVE_UNIT>, type: <DRIVE_TYPE>, formfactor: <DRIVE_FORMFACTOR>, connection: <DRIVE_CONNECTION> ...]
+ * id: <CLIENT_ID>,
+ * title: <CLIENT_TITLE>,
+ * parentId: <PARENT_ID>,
+ * system: {
+ * model: <SYSTEM_MODEL>,
+ * manufacturer: <SYSTEM_MANUFACTURER>,
+ * serialnumber: <SYSTEM_SERIALNUMBER>
+ * },
+ * cpu: {
+ * model: <CPU_MODEL>,
+ * manufacturer: <CPU_MANUFACTURER>,
+ * type: <CPU_TYPE>,
+ * frequency: <CPU_FREQUENCY>,
+ * cores: <CPU_CORES>
+ * },
+ * ram: [
+ * {
+ * title: <RAM_TITLE>,
+ * manufacturer: <RAM_MANUFACTURER>,
+ * type: <RAM_TYPE>,
+ * capacity: <RAM_CAPACITY>,
+ * unit: <RAM_UNIT>
+ * },
+ * ...
+ * ],
+ * drives: [
+ * {
+ * model: <DRIVE_MODEL>,
+ * serial: <DRIVE_SERIAL>,
+ * capacity: <DRIVE_CAPACITY>,
+ * unit: <DRIVE_UNIT>,
+ * type: <DRIVE_TYPE>,
+ * formfactor: <DRIVE_FORMFACTOR>,
+ * connection: <DRIVE_CONNECTION>
+ * },
+ * ...
+ * ]
* }
*/
async updateClient (credentials, client) {
@@ -485,190 +267,418 @@ class IdoitBackend extends ExternalBackends {
client.parentId = parseInt(client.parentId)
let bodies = []
- // workaround for the fucking idoit shit. -.-
- let requestResults = []
-
- // Update title of the object
- if (client.name) bodies.push(this.getBody('cmdb.object.update', { 'id': client.id, 'title': client.name, 'apikey': c.apikey }, 'update_title'))
- // 'object' should be 'objID' but there is a fucking bug in the idoit api. Soo let's add both parameters because else it will break when they fix it.
- // Update the productid to the uuid.
- if (client.uuid) {
+ // Helper function for creating categorie update requests
+ let createCategorieRequest = (categorie, method, additionalParams, idCounter = 0) => {
+ // 'object' should be 'objID' but there is a bug in the idoit api.
+ // Soo let's add both parameters because else it will break when they fix it. -.-i
let params = {
'object': client.id,
'objID': client.id,
- 'category': 'C__CATG__MODEL',
- 'data': {
- 'productid': client.uuid
- },
- 'apikey': c.apikey
+ 'category': categorie,
+ 'apikey': c.apikey,
+ ...additionalParams
}
- bodies.push(this.getBody('cmdb.category.save', params, 'update_uuid'))
+ return this.getBody(`cmdb.category.${method}`, params, `${method.toUpperCase()}_${categorie}_${idCounter}`)
}
- if (client.parentId) {
- // Update the object. Location
- let paramsLocation = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__LOCATION',
- 'data': {
- 'parent': client.parentId
- },
+ let createUpdateCategorieRequest = (categorie, data, additionalParams, idCounter) => {
+ return createCategorieRequest(categorie, 'save', { data: data, ...additionalParams }, idCounter)
+ }
+
+ // Update title of the object
+ if (client.name) {
+ const params = {
+ 'id': client.id,
+ 'title': client.name,
'apikey': c.apikey
}
- bodies.push(this.getBody('cmdb.category.save', paramsLocation, 'update_parent'))
+ bodies.push(this.getBody('cmdb.object.update', params, 'update_title'))
}
- // Update the object. Model data.
- if (client.system) {
- let params = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__MODEL',
- 'data': {
- 'manufacturer': client.system.manufacturer,
- 'title': client.system.model,
- 'serial': client.system.serialnumber
- },
- 'apikey': c.apikey
+ // Update the productid to the uuid and model/system data.
+ if (client.uuid || client.system) {
+ const modelData = {
+ ...(client.uuid && {
+ 'productid': client.uuid
+ }),
+ ...(client.system && {
+ ...(client.system.manufacturer && {
+ 'manufacturer': client.system.manufacturer
+ }),
+ ...(client.system.model && {
+ 'title': client.system.model
+ }),
+ ...(client.system.serialnumber && {
+ 'serial': client.system.serialnumber
+ })
+ })
}
- bodies.push(this.getBody('cmdb.category.save', params, 'update_model'))
+
+ bodies.push(createUpdateCategorieRequest('C__CATG__MODEL', modelData))
}
- // Update networks & Check if there is at least one network which will get updated.
- if (client.networks && client.networks.filter(network => Object.keys(network).length >= 4).length !== 0) {
- let parmReadNetwork = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__IP',
- 'apikey': c.apikey
+ // For all objects, where a client can have mutiple of, we need to check if we need to update a similar entrie or if it's a new one
+ // Get all data, where the clients wants to update
+ const getObjectsBodies = []
+
+ if (client.networks && client.networks.length > 0) {
+ // Get all ips and macs to check if an update is needed
+ getObjectsBodies.push(createCategorieRequest('C__CATG__IP', 'read'))
+ getObjectsBodies.push(createCategorieRequest('C__CATG__NETWORK_PORT', 'read'))
+ }
+ if (client.cpus && client.cpus.length > 0) getObjectsBodies.push(createCategorieRequest('C__CATG__CPU', 'read'))
+ if (client.gpus && client.gpus.length > 0) getObjectsBodies.push(createCategorieRequest('C__CATG__GRAPHIC', 'read'))
+ if (client.ram && client.ram.modules && client.ram.modules.length > 0) getObjectsBodies.push(createCategorieRequest('C__CATG__MEMORY', 'read'))
+ if (client.drives && client.drives.length > 0) getObjectsBodies.push(createCategorieRequest('C__CATG__STORAGE_DEVICE', 'read'))
+ if (client.monitors && client.monitors.length > 0) getObjectsBodies.push(createCategorieRequest('C__CATG__CUSTOM_FIELDS_MONITOR', 'read'))
+ if (!client.parentId && client.location && client.location.bay) getObjectsBodies.push(createCategorieRequest('C__CATG__LOCATION', 'read'))
+ if (client.contacts && client.contacts.length > 0) {
+ // Get the already attached objects
+ getObjectsBodies.push(createCategorieRequest('C__CATG__CONTACT', 'read'))
+
+ // Get the whole persons list
+ getObjectsBodies.push(
+ this.getBody(
+ 'cmdb.objects.read',
+ {
+ 'apikey': c.apikey,
+ 'filter': {
+ 'type': 'C__OBJTYPE__PERSON'
+ }
+ },
+ 'READ_C__OBJTYPE__PERSON'
+ )
+ )
+ }
+
+ const boundObjects = await this.axiosRequest(c.url, getObjectsBodies, headers)
+
+ // Add contact assignment to the object.
+ if (client.contacts) {
+ // Get the persons ids.
+ const persons = boundObjects.filter(response => response.id.startsWith('READ_C__OBJTYPE__PERSON'))[0].result
+ let counter = 0
+
+ // Helper method for replaceing ä -> ae, ü -> ue, ö -> oe
+ const replaceUmlauts = input => {
+ return input.toLowerCase().replace(/\u00e4/g, 'ae').replace(/\u00fc/g, 'ue').replace(/\u00f6/g, 'oe')
}
- const ips = await this.axiosRequest(c.url, [this.getBody('cmdb.category.read', parmReadNetwork, 'read_ips')], headers)
- parmReadNetwork.category = 'C__CATG__NETWORK_PORT'
- const macs = await this.axiosRequest(c.url, [this.getBody('cmdb.category.read', parmReadNetwork, 'read_macs')], headers)
-
- for (let index in client.networks) {
- const network = client.networks[index]
- if (network.ip && network.hostname && network.domain) {
- // Update ip addresses
- let paramsIp = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__IP',
- 'data': {
+
+ for (let contact of client.contacts) {
+ const firstname = replaceUmlauts(contact.firstname)
+ const lastname = replaceUmlauts(contact.lastname)
+
+ const contactPerson = persons.filter(person => {
+ if (!replaceUmlauts(person.title).includes(firstname)) return false
+ else if (!replaceUmlauts(person.title).includes(lastname)) return false
+ return true
+ })
+
+ let contactId
+ if (contactPerson.length > 0) contactId = contactPerson[0].id
+
+ // Check if the contact is already assigned
+ const bContacts = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__CONTACT'))
+ let bContactExists = false
+ if (bContacts.length > 0) {
+ bContactExists = bContacts[0].result.filter(c => parseInt(c.contact.id) === contactId).length > 0
+ }
+
+ if (contactId && !bContactExists) {
+ const contactData = {
+ 'contact': contactId,
+ 'primary': counter === 1 ? 1 : 0
+ }
+ bodies.push(createUpdateCategorieRequest('C__CATG__CONTACT', contactData, {}, counter))
+ counter++
+ }
+ }
+ }
+
+ // Update networks & Check if there is at least one network which will get updated.
+ if (client.networks && client.networks.length > 0) {
+ // Returns an array with the existing objects
+ const ips = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__IP'))[0].result
+ .map(ip => {
+ return {
+ id: ip.id,
+ ip: ip.ipv4_address.ref_title,
+ hostname: ip.hostname,
+ domain: ip.domain
+ }
+ })
+
+ const macs = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__NETWORK_PORT'))[0].result
+ .map(mac => {
+ return {
+ id: mac.id,
+ name: mac.title,
+ mac: mac.mac,
+ ip: mac.addresses.length > 0 ? mac.addresses[0] : undefined
+ }
+ })
+
+ let counter = 0
+ for (let network of client.networks) {
+ let updateIp = true
+ const networkObject = {
+ ip: network.ip,
+ hostname: network.hostname,
+ domain: network.domain
+ }
+
+ // Check if there is an existing object with a similar entrie
+ const similarObjects = []
+ for (let ipObj of ips) {
+ const simplifiedIpObject = {
+ ip: ipObj.ip,
+ hostname: ipObj.hostname ? ipObj.hostname : undefined,
+ domain: ipObj.domain ? ipObj.domain : undefined
+ }
+ // Check weather there is already an item which has the same attributes
+ if (JSON.stringify(networkObject) === JSON.stringify(simplifiedIpObject)) {
+ updateIp = false
+ break
+ }
+ if (network.ip && network.ip === ipObj.ip) similarObjects.push(ipObj)
+ else if (network.hostname && network.hostname !== '' && network.hostname === ipObj.hostname) similarObjects.push(ipObj)
+ // else if (network.ipv6 === ip.ipv6_address.ref_title) similarObjects.push(ipObj)
+ // else if (network.domain && network.domain === ipObj.domain) similarObjects.push(ipObj)
+ }
+
+ let ipEntryIds = []
+ if (updateIp) {
+ const ipData = {
+ ...(network.ip && {
'ipv4_address': network.ip,
- 'hostname': network.hostname,
- 'domain': network.domain,
- 'net': network.net
- },
- 'apikey': c.apikey
+ 'primary': network.primary ? 1 : 0
+ }),
+ ...(network.hostname && {
+ 'hostname': network.hostname
+ }),
+ ...(network.domain && {
+ 'domain': network.domain
+ })
+ // TODO: ipv6 needs a different host address type. Not possible to set both?
+ // ...(network.ipv6 && {
+ // 'ipv6_address': network.ipv6
+ // }),
+ }
+
+ let addParams = {}
+
+ // For now update the first one if there are more
+ if (similarObjects.length > 0) {
+ addParams.entry = parseInt(similarObjects[0].id)
+ }
+
+ if (Object.keys(ipData).length !== 0) {
+ // If we update an existing entry, we don't need the entry id, else we need to create the object to get the entry id for the mac object.
+ const ipBody = createUpdateCategorieRequest('C__CATG__IP', ipData, addParams, counter)
+ if (addParams.entry) {
+ bodies.push(ipBody)
+ ipEntryIds.push(addParams.entry)
+ } else {
+ const createIpResponse = await this.axiosRequest(c.url, [ipBody], headers)
+ ipEntryIds.push(createIpResponse[0].result.entry)
+ }
}
- if (ips[0].result.length > index) paramsIp.entry = parseInt(ips[0].result[index].id)
- bodies.push(this.getBody('cmdb.category.save', paramsIp, 'update_ip'))
}
- // Update mac addresses
- if (network.mac) {
- let paramsMac = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__NETWORK_PORT',
- 'data': {
- 'mac': network.mac
- },
- 'apikey': c.apikey
+ // Check for similar mac objects
+ let updateMac = true
+ const similarMacs = []
+ for (let mac of macs) {
+ const simplifiedMacObject = {
+ name: mac.name,
+ mac: mac.mac
}
- if (macs[0].result.length > index) paramsMac.entry = parseInt(macs[0].result[index].id)
- bodies.push(this.getBody('cmdb.category.save', paramsMac, 'update_mac'))
+
+ if (JSON.stringify({ name: network.name, mac: network.mac }) === JSON.stringify(simplifiedMacObject)) {
+ updateMac = false
+ break
+ }
+ if (network.name && network.name === mac.title) similarMacs.push(mac)
+ // Can't go with mac because two diffrent interface could have the same mac
+ // else if (network.mac && network.mac === mac.mac) return true
+ }
+
+ let addParams = {}
+ if (similarMacs.length > 0) {
+ addParams.entry = parseInt(similarMacs[0].id)
}
+
+ if (updateMac) {
+ // Update Mac-Address
+ const macData = {
+ 'title': network.name,
+ 'mac': network.mac,
+ 'addresses': ipEntryIds
+ }
+
+ bodies.push(createUpdateCategorieRequest('C__CATG__NETWORK_PORT', macData, addParams, counter))
+ }
+ counter++
}
}
// Update the object. CPU data.
- // TODO: Delete cpu if exists?
if (client.cpus) {
- let counter = 1
+ const boundedCpus = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__CPU'))[0].result
+ .map(cpu => {
+ return {
+ id: cpu.id,
+ title: cpu.title,
+ manufacturer: cpu.manufacturer.title,
+ type: cpu.type.title,
+ frequency: cpu.frequency.title,
+ frequency_unit: parseInt(cpu.frequency_unit.id),
+ cores: parseInt(cpu.cores)
+ }
+ })
+
+ let counter = 0
for (let cpu of client.cpus) {
if (cpu.unit === 'MHz') cpu.unit = 2
else if (cpu.unit === 'GHz') cpu.unit = 3
- let params = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__CPU',
- 'data': {
- 'manufacturer': cpu.manufacturer,
- 'title': cpu.model,
- 'type': cpu.type,
- 'frequency': parseFloat(cpu.frequency),
- 'frequency_unit': cpu.unit,
- 'cores': parseInt(cpu.cores)
- },
- 'apikey': c.apikey
+ const cpuData = {
+ 'title': cpu.model,
+ 'manufacturer': cpu.manufacturer,
+ 'type': cpu.type,
+ 'frequency': parseFloat(cpu.frequency),
+ 'frequency_unit': cpu.unit,
+ 'cores': parseInt(cpu.cores)
}
- counter++
- bodies.push(this.getBody('cmdb.category.save', params, 'create_cpu_' + counter))
+ let updateCpu = true
+ for (let bCpu of boundedCpus) {
+ let simplifiedCpuObject = { ...bCpu }
+ delete simplifiedCpuObject.id
+
+ if (JSON.stringify(cpuData) === JSON.stringify(simplifiedCpuObject)) {
+ updateCpu = false
+ break
+ }
+ }
+
+ if (updateCpu) {
+ bodies.push(createUpdateCategorieRequest('C__CATG__CPU', cpuData, undefined, counter))
+ counter++
+ }
}
}
// GPUS
if (client.gpus) {
- let counter = 1
+ const boundedGpus = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__GRAPHIC'))[0].result
+ .map(gpu => {
+ return {
+ id: gpu.id,
+ title: gpu.title,
+ manufacturer: gpu.manufacturer.title,
+ ...(gpu.memory && { 'memory': gpu.memory }),
+ ...(gpu.unit && { 'unit': gpu.unit })
+ }
+ })
+
+ let counter = 0
for (let gpu of client.gpus) {
- let params = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__GRAPHIC',
- 'data': {
- 'manufacturer': gpu.manufacturer,
- 'title': gpu.model,
- 'memory': gpu.memory,
- 'unit': gpu.unit
- },
- 'apikey': c.apikey
+ const gpuData = {
+ 'title': gpu.model,
+ 'manufacturer': gpu.manufacturer,
+ ...(gpu.memory && { 'memory': gpu.memory }),
+ ...(gpu.unit && { 'unit': gpu.unit })
}
- counter++
- bodies.push(this.getBody('cmdb.category.save', params, 'create_gpu_' + counter))
+ let updateGpu = true
+ for (let bGpu of boundedGpus) {
+ let simplifiedGpuObject = { ...bGpu }
+ delete simplifiedGpuObject.id
+
+ if (JSON.stringify(gpuData) === JSON.stringify(simplifiedGpuObject)) {
+ updateGpu = false
+ break
+ }
+ }
+
+ if (updateGpu) {
+ bodies.push(createUpdateCategorieRequest('C__CATG__GRAPHIC', gpuData, undefined, counter))
+ counter++
+ }
}
}
// Update the object. Ram data.
if (client.ram) {
- let counter = 1
+ const boundedRams = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__MEMORY'))[0].result
+ .map(bRam => {
+ return {
+ id: bRam.id,
+ title: bRam.title.title,
+ manufacturer: bRam.manufacturer.title,
+ capacity: bRam.capacity.title,
+ unit: bRam.unit.id,
+ type: bRam.type.title,
+ description: bRam.description
+ }
+ })
+
+ let counter = 0
for (let module of client.ram.modules) {
// Add KB and TB
- if (module.unit === 'MB') module.unit = 2
- else if (module.unit === 'GB') module.unit = 3
+ if (module.unit === 'MB') module.unit = '2'
+ else if (module.unit === 'GB') module.unit = '3'
+
+ let ramData = {
+ 'title': module.model,
+ 'manufacturer': module.manufacturer,
+ 'capacity': parseFloat(module.capacity),
+ 'unit': module.unit,
+ 'type': module.type,
+ 'description': JSON.stringify({
+ serialnumber: module.serialnumber,
+ formfactor: module.formfactor,
+ speed: module.speed
+ })
+ }
- let params = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__MEMORY',
- 'data': {
- 'title': module.model,
- 'manufacturer': module.manufacturer,
- 'type': module.type,
- 'capacity': parseFloat(module.capacity),
- 'unit': module.unit,
- 'description': JSON.stringify({
- serialnumber: module.serialnumber,
- formfactor: module.formfactor,
- speed: module.speed
- })
- },
- 'apikey': c.apikey
+ let updateRam = true
+ for (let bRam of boundedRams) {
+ let simplifiedRamObject = { ...bRam }
+ delete simplifiedRamObject.id
+
+ if (JSON.stringify(ramData) === JSON.stringify(simplifiedRamObject)) {
+ updateRam = false
+ break
+ }
+ }
+
+ if (updateRam) {
+ bodies.push(createUpdateCategorieRequest('C__CATG__MEMORY', ramData, undefined, counter))
+ counter++
}
- counter++
- bodies.push(this.getBody('cmdb.category.save', params, 'create_memory_' + counter))
}
}
// Update the object. Drive data.
if (client.drives) {
- let counter = 1
+ const boundedDrives = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__STORAGE_DEVICE'))[0].result
+ .map(bDrive => {
+ return {
+ id: bDrive.id,
+ title: bDrive.title,
+ type: bDrive.type.title,
+ ...(bDrive.firmware && { firmware: bDrive.firmware }),
+ ...(bDrive.capacity && { capacity: bDrive.capacity.title }),
+ ...(bDrive.unit && { unit: parseInt(bDrive.unit.id) }),
+ ...(bDrive.serial && { serial: bDrive.serial }),
+ ...(bDrive.connected && { connected: bDrive.connected.title })
+ }
+ })
+
+ let counter = 0
for (let index in client.drives) {
const drive = client.drives[index]
// UNIT
@@ -683,33 +693,183 @@ class IdoitBackend extends ExternalBackends {
else if (drive.type === '7200 rpm') drive.type = 'Hard disk'
else if (drive.type === '') drive.type = 'Hard disk'
- let params = {
- 'object': client.id,
- 'objID': client.id,
- 'category': 'C__CATG__STORAGE_DEVICE',
+ let driveData = {
+ 'title': drive.model,
+ 'type': drive.type,
+ ...(drive.firmware && { 'firmware': drive.firmware }),
+ ...(drive.capacity && { 'capacity': parseFloat(drive.capacity) }),
+ ...(drive.unit && { 'unit': drive.unit }),
+ ...(drive.serial && { 'serial': drive.serial }),
+ ...(drive.connection && { 'connected': drive.connection })
+ }
+
+ let updateDrive = true
+ for (let bDrive of boundedDrives) {
+ let simplifiedDriveObject = { ...bDrive }
+ delete simplifiedDriveObject.id
+
+ if (JSON.stringify(driveData) === JSON.stringify(simplifiedDriveObject)) {
+ updateDrive = false
+ break
+ }
+ }
+
+ if (updateDrive) {
+ bodies.push(createUpdateCategorieRequest('C__CATG__STORAGE_DEVICE', driveData, undefined, counter))
+ counter++
+ }
+ }
+ }
+
+ // Add Monitors
+ if (client.monitors) {
+ // Monitor is a custom object, therefore the fieldnames can be looked up in the idoit interface / api
+ const boundedMonitors = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__CUSTOM_FIELDS_MONITOR'))[0].result
+ .map(bMonitor => {
+ return {
+ id: bMonitor.id,
+ f_text_c_1618324877787: bMonitor.f_text_c_1618324877787,
+ f_text_c_1618324891521: bMonitor.f_text_c_1618324891521,
+ f_text_c_1618328160730: bMonitor.f_text_c_1618328160730,
+ f_text_c_1618328167672: bMonitor.f_text_c_1618328167672,
+ f_text_c_1620145359196: bMonitor.f_text_c_1620145359196,
+ f_text_c_1622557969975: bMonitor.f_text_c_1622557969975
+ }
+ })
+
+ let counter = 0
+ for (let monitor of client.monitors) {
+ const monitorData = {
+ 'f_text_c_1618324877787': monitor.model, // Model
+ 'f_text_c_1618324891521': monitor.vendor, // Manufacturer
+ 'f_text_c_1618328160730': `${monitor.resolution.width}x${monitor.resolution.height}`, // Resolution
+ 'f_text_c_1618328167672': monitor.serialnumber, // Serial Number
+ 'f_text_c_1620145359196': `${monitor.dimensions.inch}"`, // Display Size (Inch)
+ 'f_text_c_1622557969975': monitor.port
+ }
+
+ let updateMonitor = true
+ for (let bMonitor of boundedMonitors) {
+ let simplifiedMonitorObject = { ...bMonitor }
+ delete simplifiedMonitorObject.id
+
+ if (JSON.stringify(monitorData) === JSON.stringify(simplifiedMonitorObject)) {
+ updateMonitor = false
+ break
+ }
+ }
+
+ if (updateMonitor) {
+ bodies.push(createUpdateCategorieRequest('C__CATG__CUSTOM_FIELDS_MONITOR', monitorData, undefined, counter))
+ counter++
+ }
+ }
+ }
+
+ /* OPERTATING SYSTEM REWORK TODO
+ // Add operating system information.
+ if (client.runtime && client.runtime.operating_system) {
+ // Get the operating system ids.
+ const getOSParam = {
+ 'apikey': c.apikey,
+ 'filter': {
+ 'type': 35, // 35 = Operating System
+ 'title': client.runtime.operating_system.name
+ }
+ }
+ const getOSBody = this.getBody('cmdb.objects.read', getOSParam, 'get_os')
+ const requestGetOS = await this.axiosRequest(c.url, [getOSBody], headers)
+
+ // Extra request for getting the id of the version number
+ const getOSVersionParam = {
+ 'apikey': c.apikey,
+ 'objID': requestGetOS[0].result[0].id,
+ 'catgID': 'C__CATG__VERSION'
+ }
+ const getOSVersionBody = this.getBody('cmdb.category.read', getOSVersionParam, 'get_os_version')
+ const requestGetOSVersion = await this.axiosRequest(c.url, [getOSVersionBody], headers)
+ const osVersion = requestGetOSVersion[0].result.filter(x => x.title === client.runtime.operating_system.version)
+
+ // Add the result of the OS request (ids) to the create request.
+ if (requestGetOS[0].result) {
+ params.categories.C__CATG__OPERATING_SYSTEM = {
'data': {
- 'category_id': counter,
- 'title': drive.model,
- 'type': drive.type,
- 'firmware': drive.firmware,
- // 'manufacturer': ,
- // 'model': ,
- 'capacity': parseFloat(drive.capacity),
- 'unit': drive.unit,
- 'serial': drive.serial,
- 'connected': drive.connection
- },
- 'apikey': c.apikey
+ 'application': requestGetOS[0].result[0].id,
+ 'assigned_version': osVersion[0].id
+ }
}
+ }
+ }
+ */
- bodies.push(this.getBody('cmdb.category.save', params, 'create_drive_' + counter))
- counter++
+ // Update the object location.
+ if (client.parentId && (!client.location || (client.location && !client.location.slot))) {
+ // Either client or no slot was set
+ const locationData = {
+ 'parent': client.parentId
+ }
+
+ bodies.push(createUpdateCategorieRequest('C__CATG__LOCATION', locationData))
+ } else {
+ // Create segments and prepare bay
+
+ // Rack segmentation
+ if (!!client.location && !!client.location.slot) {
+ // Get the parentId if none was given
+ if (!client.parentId) {
+ let boundedLocation = boundObjects.filter(response => response.id.startsWith('READ_C__CATG__LOCATION'))
+ if (boundedLocation.length > 0) boundedLocation = boundedLocation[0].result
+ if (boundedLocation.length > 0) client.parentId = parseInt(boundedLocation[0].location_path)
+ }
+
+ // Call method for getting the chassis id, can be either an existing one or a new created one.
+ const chassisId = await this.getChassisId(c, client, headers)
+
+ // If chassis id is set, assign the object to the chassis bay
+ if (chassisId) {
+ // Read bay ids
+ const paramsSlots = {
+ 'object': parseInt(chassisId),
+ 'objID': parseInt(chassisId),
+ 'category': 'C__CATS__CHASSIS_SLOT',
+ 'apikey': c.apikey
+ }
+
+ const readSlotsParam = this.getBody('cmdb.category.read', paramsSlots, 'read_slots')
+ const readSlots = await this.axiosRequest(c.url, [readSlotsParam], headers)
+ const bays = readSlots[0].result
+
+ const assignToSlotData = {
+ 'assigned_device': client.id,
+ 'assigned_slots': [parseInt(bays[client.location.bay].id)]
+ }
+
+ bodies.push(createUpdateCategorieRequest('C__CATS__CHASSIS_DEVICES', assignToSlotData, {
+ 'object': parseInt(chassisId),
+ 'objID': parseInt(chassisId)
+ }))
+ }
}
}
+ // Only server have formfactor categories.
+ if (client.formfactor) {
+ const formfactorData = {
+ ...(client.formfactor.formfactor && {
+ 'formfactor': client.formfactor.formfactor
+ }),
+ ...(client.formfactor.rackunits && {
+ 'rackunits': client.formfactor.rackunits
+ })
+ }
+
+ bodies.push(createUpdateCategorieRequest('C__CATG__FORMFACTOR', formfactorData))
+ }
+
+ let requestUpdate = []
+ // Send the batch request to idoit
if (bodies.length > 0) {
- const requestUpdate = await this.axiosRequest(c.url, bodies, headers)
- requestResults.push(requestUpdate)
+ requestUpdate = await this.axiosRequest(c.url, bodies, headers)
if (requestUpdate.error) return requestUpdate
}
@@ -724,12 +884,129 @@ class IdoitBackend extends ExternalBackends {
success: true,
id: client.id,
type: type,
- response: requestResults
+ response: requestUpdate
}
return result
}
+ /*
+ * Rack -> Rack obeject
+ * Slot -> Rack Segment object (contains multiple bays)
+ * Bay -> Slot objects inside the Rack Segment object
+ *
+ */
+ async getChassisId (credentials, client, headers) {
+ // Check if parentId is still missing. If so skip bay assignment.
+ if (!client.parentId) return undefined
+
+ // Get all assigned objects of the rack (parentid) to check for existing rack segments at slot position.
+ const rackobjectsBody = this.getBody(
+ 'cmdb.category.read',
+ {
+ 'apikey': credentials.apikey,
+ 'object': client.parentId,
+ 'objID': client.parentId,
+ 'category': 'C__CATG__OBJECT'
+ },
+ 'get_rack_objects'
+ )
+
+ // Get the name of the rack
+ const rackBody = this.getBody(
+ 'cmdb.category.read',
+ {
+ 'apikey': credentials.apikey,
+ 'object': client.parentId,
+ 'objID': client.parentId,
+ 'category': 'C__CATG__GLOBAL'
+ },
+ 'get_rack'
+ )
+
+ const rackRequest = await this.axiosRequest(credentials.url, [rackobjectsBody, rackBody], headers)
+ const rackObjects = rackRequest[0]
+ const rack = rackRequest[1]
+
+ if (!rackObjects.result || !rack.result) return undefined
+
+ const rackName = rack.result[0].title
+ let rackSegmentId
+
+ // For each segmentation object in the rack get the slot number
+ for (let object of rackObjects.result) {
+ if (object.assigned_object.type !== 'C__OBJTYPE__RACK_SEGMENT') continue
+
+ if (object.assigned_object.title === `${rackName} Slot ${client.location.slot}`) {
+ // This is the slot where it should get added
+ rackSegmentId = object.assigned_object.id
+ break
+ }
+ }
+
+ // There should only be one segment object for the rack slot if so set it as parent
+ let chassisId = rackSegmentId
+ if (!chassisId) {
+ // Create a new rack segment
+ const createSegmentParamObject = {
+ 'apikey': credentials.apikey,
+ 'type': 92,
+ 'title': rackName + ' Slot ' + client.location.slot,
+ 'categories': {
+ 'C__CATS__CHASSIS': {
+ 'data': {
+ 'front_x': 2,
+ 'front_y': 1,
+ 'rear_x': 0,
+ 'rear_y': 0
+ }
+ },
+ 'C__CATS__CHASSIS_SLOT': [
+ {
+ 'title': 'Bay 1',
+ 'insertion': 'front',
+ 'from_x': 0,
+ 'to_x': 0,
+ 'from_y': 0,
+ 'to_y': 0
+ },
+ {
+ 'title': 'Bay 2',
+ 'insertion': 'front',
+ 'from_x': 1,
+ 'to_x': 1,
+ 'from_y': 0,
+ 'to_y': 0
+ }
+ ],
+ 'C__CATG__LOCATION': {
+ 'data': {
+ 'parent': client.parentId,
+ 'option': client.location.option ? client.location.option : 'Horizontal',
+ 'insertion': client.location.insertion ? client.location.insertion : 'Front and backside',
+ 'pos': client.location.slot
+ }
+ }
+ }
+ }
+
+ const createSegmentParam = this.getBody('cmdb.object.create', createSegmentParamObject, 'create_segment')
+ const createSegment = await this.axiosRequest(credentials.url, [createSegmentParam], headers)
+ chassisId = createSegment[0].result.id
+
+ /*
+ // Set the new rack units height. (Needs an extra request, why? I DONT KNOW... idoit...)
+ const setSegmentSizeParams = this.getBody('cmdb.category.save', { 'apikey': c.apikey,
+ 'object': chassisId,
+ 'objID': chassisId,
+ 'category': 'C__CATG__FORMFACTOR',
+ 'data': { 'rackunits': client.formfactor.rackunits } }, 'set_segment_size')
+ await this.axiosRequest(c.url, [setSegmentSizeParams], headers)
+ */
+ }
+ return chassisId
+ }
+
async getFileList (credentials, externalId) {
const c = this.mapCredentials(credentials)
const body = this.getBody('cmdb.category.read', { 'objID': externalId, 'category': 'C__CATG__FILE', apikey: c.apikey }, 'filelist')