summaryrefslogtreecommitdiffstats
path: root/server/lib
diff options
context:
space:
mode:
authorJannik Schönartz2019-03-15 05:49:30 +0100
committerJannik Schönartz2019-03-15 05:49:30 +0100
commitc2c64dafe7f2a4fc2accd7ee5f87d382886bbedb (patch)
tree08ac85332cdff8af7e682add94223dcc2bc29e60 /server/lib
parentmerge (diff)
downloadbas-c2c64dafe7f2a4fc2accd7ee5f87d382886bbedb.tar.gz
bas-c2c64dafe7f2a4fc2accd7ee5f87d382886bbedb.tar.xz
bas-c2c64dafe7f2a4fc2accd7ee5f87d382886bbedb.zip
[external-backeds] Big idoit rework, to match the updated api
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/external-backends/backendhelper.js48
-rw-r--r--server/lib/external-backends/backends/idoit-backend.js987
-rw-r--r--server/lib/external-backends/backends/infoblox-backend.js16
-rw-r--r--server/lib/external-backends/index.js10
4 files changed, 354 insertions, 707 deletions
diff --git a/server/lib/external-backends/backendhelper.js b/server/lib/external-backends/backendhelper.js
index ae1af3d..bb95844 100644
--- a/server/lib/external-backends/backendhelper.js
+++ b/server/lib/external-backends/backendhelper.js
@@ -15,22 +15,11 @@ module.exports = {
const instance = ba.getInstance(backend.type)
var tmpClient = JSON.parse(JSON.stringify(client))
- // If the client id is set we need to get the external id.
- if (client.id) {
- var exid = backend.mappedClients.find(y => y.id === parseInt(client.id))
- if (exid) tmpClient.id = exid.backend_x_client.externalId
- } else {
- // If we don't already have the client id, we need to check if there is already a client with the provided uuid in the backend.
- var cl = await instance.getClient(backend.credentials, { uuid: tmpClient.uuid })
- if (cl.succes) {
- tmpClient.id = cl.data
- }
- }
-
+ // Add client has no support for update anymore.. use update method.. maybe call conflict here
// Convert the parent group id to the external backend parentId.
// if (client.parentId) {
if (client.parents) {
- var elements = backend.mappedGroups.filter(x => client.parents.includes(x.id))
+ const elements = backend.mappedGroups.filter(x => client.parents.includes(x.id))
if (elements.length > 1) {
// Conflict occured!
const conflict = await db.conflict.create({ description: 'Multiple parents found' })
@@ -43,13 +32,15 @@ module.exports = {
conflict.createObject({ objectType: 'GROUP', objectId: element.id })
}
} else if (elements.length === 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId
-
- // var element = backend.mappedGroups.find(x => x.id === parseInt(client.parentId))
- // if (element) tmpClient['parentId'] = element.backend_x_group.externalId
}
- var addClient = await instance.addClient(backend.credentials, tmpClient)
+ let addClient = await instance.addClient(backend.credentials, tmpClient)
addClient.backendId = backend.id
+ if (addClient.succes) {
+ // If the object was created we need to make the objectid / external id mapping.
+ const clientDb = await db.client.findOne({ where: { id: client.id } })
+ backend.addMappedClients(clientDb, { through: { externalId: addClient.id, externalType: addClient.type } })
+ }
result.push(addClient)
}
return result
@@ -57,11 +48,11 @@ module.exports = {
updateClient: async function (client) {
// Get all backends and call addClient for each instance.
- var backends = await db.backend.findAll({ include: ['mappedGroups', 'mappedClients'] })
- var result = []
+ const backends = await db.backend.findAll({ include: ['mappedGroups', 'mappedClients'] })
+ let result = []
- for (var b in backends) {
- var backend = backends[b]
+ for (let b in backends) {
+ const backend = backends[b]
const ba = new ExternalBackends()
const instance = ba.getInstance(backend.type)
var tmpClient = JSON.parse(JSON.stringify(client))
@@ -76,7 +67,7 @@ module.exports = {
if (element) tmpClient['parentId'] = element.backend_x_group.externalId
}
- var updateClient = await instance.updateClient(backend.credentials, tmpClient)
+ let updateClient = await instance.updateClient(backend.credentials, tmpClient)
updateClient.backendId = backend.id
result.push(updateClient)
}
@@ -100,15 +91,18 @@ module.exports = {
},
uploadFiles: async function (clientId, files) {
- var backends = await db.backend.findAll({ include: ['mappedClients'] })
- for (var b in backends) {
- var backend = backends[b]
+ const backends = await db.backend.findAll({ include: ['mappedClients'] })
+ let results = []
+ for (let b in backends) {
+ const backend = backends[b]
const ba = new ExternalBackends()
const instance = ba.getInstance(backend.type)
- var exid = backend.mappedClients.find(y => y.id === parseInt(clientId))
+ let exid = backend.mappedClients.find(y => y.id === parseInt(clientId))
if (exid) exid = exid.backend_x_client.externalId
- instance.uploadFiles(backend.credentials, exid, files)
+ results.push(await instance.uploadFiles(backend.credentials, exid, files))
}
+ return results
}
+
}
diff --git a/server/lib/external-backends/backends/idoit-backend.js b/server/lib/external-backends/backends/idoit-backend.js
index d3d992f..9325ad5 100644
--- a/server/lib/external-backends/backends/idoit-backend.js
+++ b/server/lib/external-backends/backends/idoit-backend.js
@@ -4,9 +4,6 @@ const ExternalBackends = require(path.join(__appdir, 'lib', 'external-backends')
var axios = require('axios')
class IdoitBackend extends ExternalBackends {
- // ############################################################################
- // ######################## needed functions #################################
-
/*
* Returns the credential structure / fields, defined in the backends.
*/
@@ -31,33 +28,30 @@ class IdoitBackend extends ExternalBackends {
* Checks the connection of a given backend.
* idoIT: Checks if we can get a valid session id. If so the connection must be successfull.
*
- * return: { success: <boolean>, status: '<STATUS_CODE_IF_ERROR>', error: '<ERROR_MESSAGE>' }
+ * return: true / { error: <ERROR>, message: <MESSAGE> }
*/
- checkConnection (credentials) {
- var c = this.mapCredentials(credentials)
- return this.getSession(c)
+ async checkConnection (credentials) {
+ const c = this.mapCredentials(credentials)
+ const body = this.getBody('idoit.version', { 'apikey': c.apikey }, 'version_check')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
+
+ // Axios request
+ const result = await this.axiosRequest(c.url, [body], headers)
+ if (result.error) return { error: 'IDOIT_ERROR', message: result.errno }
+ return true
}
// Return the list of object types created in iDoIT.
async getObjectTypes (credentials) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- // Headers
- var headers = {
- 'X-RPC-Auth-Session': sid
- }
-
- // Params
- var params = {
- 'apikey': c.apikey,
- 'language': 'en'
- }
+ const c = this.mapCredentials(credentials)
+ const body = this.getBody('cmdb.object_types', { 'apikey': c.apikey }, 'object_types')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
var result = {}
- result.types = await this.axiosRequest(c.url, 'cmdb.object_types', params, headers)
- result.types = result.types.data.result
+ result.types = await this.axiosRequest(c.url, [body], headers)
+ result.types = result.types[0].result
var types = []
result.types.forEach(type => {
@@ -72,235 +66,90 @@ class IdoitBackend extends ExternalBackends {
}
/*
- * Gets all objects and searches for the ip. Because idoit cannot search for ip or mac.
+ * Gets all objects and searches for the uuid to get the requested client.
*
*/
async getClient (credentials, client) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
- // var uuid = client.uuid
-
- // Headers
- var headers = {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
+ const c = this.mapCredentials(credentials)
- // Params to get all clients.
- var params = {
+ const paramsObjects = {
'apikey': c.apikey,
- 'language': 'en',
'filter': {
'type': 10
- }
+ },
+ 'categories': ['C__CATG__MODEL']
}
+ const body = this.getBody('cmdb.objects', paramsObjects, 'objects')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
// Get all client objects.
- var clients = await this.axiosRequest(c.url, 'cmdb.objects', params, headers)
- clients = clients.data.result
-
- var bodies = []
-
- clients.forEach(client => {
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.read',
- 'params': {
- 'objID': client.id,
- 'apikey': c.apikey,
- 'language': 'en',
- 'category': 'C__CATG__MODEL'
- },
- 'id': client.id
- })
- })
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
- var requestClient = await axios.post(c.url, bodies, config)
- requestClient = requestClient.data.filter(x => x.result.length >= 1 && x.result[0].productid === client.uuid)
+ const clients = await this.axiosRequest(c.url, [body], headers)
- return requestClient.length >= 1 ? { succes: true, data: requestClient[0].result[0].objID } : { success: false, error: 'NO_CLIENT_FOUND', msg: 'There is no client matching with the provided uuid.' }
+ let result = clients[0].result.filter(x => x.categories.C__CATG__MODEL.length > 0 && x.categories.C__CATG__MODEL[0].productid === client.uuid)
+ return result.length >= 1 ? result.map(x => x.id) : { error: 'NO_CLIENT_FOUND', msg: 'There is no client matching with the provided uuid.' }
}
async getObjects (credentials) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- // Headers
- var headers = {
- 'X-RPC-Auth-Session': sid
- }
-
- // Params
- var params = {
- 'apikey': c.apikey,
- 'language': 'en'
- }
+ const c = this.mapCredentials(credentials)
+ const body = this.getBody('cmdb.objects', { 'apikey': c.apikey }, 'objects')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
- var result = {}
- result.objects = await this.axiosRequest(c.url, 'cmdb.objects', params, headers)
- result.objects = result.objects.data.result
-
- return result
+ const objects = await this.axiosRequest(c.url, [body], headers)
+ return objects[0]
}
async getObject (credentials, oid) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- // Headers
- var headers = {
- 'X-RPC-Auth-Session': sid
- }
-
- // Params
- var params = {
- 'id': oid,
- 'apikey': c.apikey,
- 'language': 'en'
- }
+ const c = this.mapCredentials(credentials)
+ const body = this.getBody('cmdb.object.read', { 'apikey': c.apikey, 'id': oid }, 'object_read')
+ const bodyChilds = this.getBody('cmdb.location_tree', { 'apikey': c.apikey, 'id': oid }, 'object_location_tree')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
var result = {}
- result.object = await this.axiosRequest(c.url, 'cmdb.object.read', params, headers)
- result.childs = await this.axiosRequest(c.url, 'cmdb.location_tree', params, headers)
- result.object = result.object.data.result
- result.childs = result.childs.data.result
+ result.object = await this.axiosRequest(c.url, [body], headers)
+ result.childs = await this.axiosRequest(c.url, [bodyChilds], headers)
+ result.object = result.object[0].result
+ result.childs = result.childs[0].result
return result
}
async deleteObjects (credentials, objectIds) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
-
- var bodies = []
+ const c = this.mapCredentials(credentials)
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
+ let bodies = []
objectIds.forEach(oid => {
- // Body
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.object.delete',
- 'params': {
- 'id': oid,
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': oid
- })
+ bodies.push(this.getBody('cmdb.object.quickpurge', { 'id': oid, 'apikey': c.apikey }, oid))
})
- var requestDelete = await axios.post(c.url, bodies, config)
-
- return { success: requestDelete.success, data: requestDelete.data }
+ let deleteRequest = await this.axiosRequest(c.url, bodies, headers)
+ return deleteRequest
}
// Function to use the same session for multiple requests
async getDataTree (credentials, objects) {
- var c = this.mapCredentials(credentials)
-
- // LOGIN
- // Open and get a session
- const body = {
- 'version': '2.0',
- 'method': 'idoit.login',
- 'params': {
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 1
- }
-
- // Headers
- var headers = {}
- // Optional credentials
- if (c.login) {
- headers['X-RPC-Auth-Username'] = c.username
- headers['X-RPC-Auth-Password'] = c.password
- }
-
- var config = {
- timeout: 180000,
- headers: headers
- }
-
- // Make a login request and see if we are authenticated.
- var log = await axios.post(c.url, body, config)
- log = log.data.result
- var sid = log['session-id']
-
- // Headers
- config.headers = { 'X-RPC-Auth-Session': sid, 'Content-Type': 'application/json' }
- body.method = 'cmdb.location_tree'
-
- // Go through the objects and get all the childs.
- var promises = []
-
- var counter = 0
- var index = 0
- var gids = {}
+ const c = this.mapCredentials(credentials)
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
+ let bodies = []
+ let gids = {}
// Prepare all the batch request bodies.
- var e
- for (e in objects) {
- // Pack 400 requests in one batch request to reduce api calls.
- if (counter >= 400) {
- counter = 0
- index++
- }
- if (counter === 0) promises[index] = []
- counter++
-
- var element = objects[e]
- const bod = {
- 'version': '2.0',
- 'method': 'cmdb.location_tree',
- 'params': {
- 'id': element.eid,
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': element.eid
- }
- promises[index].push(bod)
+ for (let element of objects) {
+ bodies.push(this.getBody('cmdb.location_tree', { 'id': element.eid, 'apikey': c.apikey }, element.eid))
gids[element.eid] = element.gid
}
// Send all the batch request and post proccess the result into one array.
- var result = []
- var p
- var counter2 = 1
- for (p in promises) {
- // TODO: Remove
- // Counter for getting an overview, how far the requests are.
- console.log(counter2 + '/' + promises.length + ' requests send')
- counter2++
-
- // Send the request.
- var requestResult = await axios.post(c.url, promises[p], config)
- const args = requestResult.data
-
- // Post process the data.
- var a
- for (a in args) {
- result.push({ gid: gids[args[a].id], childs: args[a].result })
- }
+ let requestResult = await this.axiosRequest(c.url, bodies, headers)
+
+ // Post process the data.
+ let result = []
+ for (let res of requestResult) {
+ result.push({ gid: gids[res.id], childs: res.result })
}
return result
}
@@ -309,157 +158,53 @@ class IdoitBackend extends ExternalBackends {
* Adds the client to the backend.
*
* credentials: <BACKEND_CREDENTIALS>
- * The client parameters are all optional. If the client has an id the object is not created but the categories of the object.
+ * The client parameters are all optional.
* client: {
- * id: <CLIENT_ID>, title: <CLIENT_TITLE>, parentId: <PARENT_ID>,
+ * title: <CLIENT_TITLE>, parentId: <PARENT_ID>,
* network: { mac: <MAC_ADDRESS>, ip: <IP_ADDRESS> }
* }
*/
async addClient (credentials, client) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
- var bodies = []
- var clientid
- if (!client.id) {
- // Create the object in idoIT.
- var params = {
- 'type': 10,
- 'title': client.title,
- 'apikey': c.apikey,
- 'language': 'en'
- }
- // 1 = Production
- // 2 = Test
- // 3 = Quality Assurance
- // 5 = PVS
- // 7 = Pool PC
- // 8 = Mitarbeiter Arbeitsplatz
- if (client.purpose === 'Pool PC') params.purpose = 7
-
- var requestCreate = await this.axiosRequest(c.url, 'cmdb.object.create', params, config.headers)
-
- clientid = requestCreate.data.result.id
- } else {
- clientid = client.id
-
- // Update the client title
- var bodyGeneral = {
- 'version': '2.0',
- 'method': 'cmdb.object.update',
- 'params': {
- 'id': clientid,
- 'title': client.title,
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 'update_title'
- }
- if (client.purpose === 'Pool PC') bodyGeneral.params.purpose = 7
-
- bodies.push(bodyGeneral)
- }
+ const c = this.mapCredentials(credentials)
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
- if (client.uuid) {
- // Update the productid to the uuid.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.update',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__MODEL',
- 'data': {
- 'productid': client.uuid
- },
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 'update_uuid'
- })
+ let params = {
+ 'apikey': c.apikey,
+ 'title': client.title,
+ 'purpose': client.purpose === 'Pool PC' ? 7 : undefined,
+ 'categories': {}
}
- if (client.network) {
- // Update the object. MAC-Address
- if (client.network.mac) {
- // First read if there are current entries.
- // Delete the previous entries.
- // Finally create the new entry.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__NETWORK_PORT',
- 'data': {
- 'category_id': 1,
- 'mac': client.network.mac
- },
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 'create_mac'
- })
- }
+ if (client.type === 'CLIENT') params['type'] = 10
+ else if (client.type === 'SERVER') {
+ params['type'] = 5
- // Update the object. IP-Address
- if (client.network.ip) {
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__IP',
- 'data': {
- 'category_id': 1,
- 'ipv4_address': client.network.ip
- },
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 'create_ip'
- })
- }
+ if (client.location) params.categories.C__CATG__LOCATION = { 'data': { 'option': client.location.assembly, 'insertion': client.location.insertion, 'pos': 32 } }
+ // TODO: Assign to rack with the given rackid
}
- // Update the object. Location
- if (client.parentId) {
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.update',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__LOCATION',
- 'data': {
- 'parent': client.parentId
- },
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 'update_parent'
- })
- }
-
- var requestUpdate = await axios.post(c.url, bodies, config)
-
- var result = {
- success: true,
- id: clientid,
- type: 10,
- create: requestCreate ? requestCreate.success : false,
- update: requestUpdate ? requestUpdate.success : false,
- createData: requestCreate ? requestCreate.data : false,
- updateData: requestUpdate ? requestUpdate.data : false
- }
-
- return result
+ // Add categories to the object
+ if (client.uuid) params.categories.C__CATG__MODEL = { 'data': { 'productid': client.uuid } }
+ if (client.network) {
+ // TOOD:
+ // First read if there are current entries.
+ // Delete the previous entries.
+ // Finally create the new entry.
+ if (client.network.mac) params.categories.C__CATG__NETWORK_PORT = { 'data': { 'category_id': 1, 'mac': client.network.mac } }
+ if (client.network.ip) params.categories.C__CATG__IP = { 'data': { 'category_id': 1, 'ipv4_address': client.network.ip } }
+ }
+ if (client.parentId) params.categories.C__CATG__LOCATION = { 'data': { 'parent': client.parentId } }
+
+ // Send the create request.
+ const body = this.getBody('cmdb.object.create', params, 'client_create')
+ const requestCreate = await this.axiosRequest(c.url, [body], headers)
+
+ // 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 }
}
/*
@@ -476,120 +221,84 @@ class IdoitBackend extends ExternalBackends {
* }
*/
async updateClient (credentials, client) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
+ const c = this.mapCredentials(credentials)
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
- var clientid = client.id
- var bodies = []
- var counter
-
- if (client.title) {
- // Update title of the object
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.object.update',
- 'params': {
- 'id': clientid,
- 'title': client.title,
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 'update_title'
- })
- }
+ let bodies = []
+
+ // Update title of the object
+ if (client.title) bodies.push(this.getBody('cmdb.object.update', { 'id': client.id, 'title': client.title, '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) {
- // Update the productid to the uuid.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.update',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__MODEL',
- 'data': {
- 'productid': client.uuid
- },
- 'apikey': c.apikey,
- 'language': 'en'
+ let params = {
+ 'object': client.id,
+ 'objID': client.id,
+ 'category': 'C__CATG__MODEL',
+ 'data': {
+ 'productid': client.uuid
},
- 'id': 'update_uuid'
- })
+ 'apikey': c.apikey
+ }
+ bodies.push(this.getBody('cmdb.category.save', params, 'update_uuid'))
}
// Update the object. Location
if (client.parentId) {
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.update',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__LOCATION',
- 'data': {
- 'parent': client.parentId
- },
- 'apikey': c.apikey,
- 'language': 'en'
+ let params = {
+ 'object': client.id,
+ 'objID': client.id,
+ 'category': 'C__CATG__LOCATION',
+ 'data': {
+ 'parent': client.parentId
},
- 'id': 'update_parent'
- })
+ 'apikey': c.apikey
+ }
+ bodies.push(this.getBody('cmdb.category.save', params, 'update_parent'))
}
+ // Update the object. Model data.
if (client.system) {
- // Update the object.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.update',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__MODEL',
- 'data': {
- 'manufacturer': client.system.manufacturer,
- 'title': client.system.model,
- 'serial': client.system.serialnumber
- },
- 'apikey': c.apikey,
- 'language': 'en'
+ 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
},
- 'id': 'update_model'
- })
+ 'apikey': c.apikey
+ }
+ bodies.push(this.getBody('cmdb.category.save', params, 'update_model'))
}
+ // Update the object. CPU data.
+ // TODO: Delete cpu if exists?
if (client.cpu) {
- // TODO: Delete cpu if exists?
- // Update the object.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__CPU',
- 'data': {
- 'category_id': 1,
- 'manufacturer': client.cpu.manufacturer,
- 'title': client.cpu.model,
- 'type': client.cpu.type,
- 'frequency': client.cpu.frequency,
- 'frequency_unit': 3,
- 'cores': client.cpu.cores
- },
- 'apikey': c.apikey,
- 'language': 'en'
+ let params = {
+ 'object': client.id,
+ 'objID': client.id,
+ 'category': 'C__CATG__CPU',
+ 'data': {
+ 'category_id': 1,
+ 'manufacturer': client.cpu.manufacturer,
+ 'title': client.cpu.model,
+ 'type': client.cpu.type,
+ 'frequency': client.cpu.frequency,
+ 'frequency_unit': 3,
+ 'cores': client.cpu.cores
},
- 'id': 'update_cpu'
- })
+ 'apikey': c.apikey
+ }
+ bodies.push(this.getBody('cmdb.category.save', params, 'update_cpu'))
}
+ // Update the object. Ram data.
if (client.ram) {
- counter = 1
+ let counter = 1
for (var memory in client.ram) {
var mem = client.ram[memory]
var ramId = 'create_memory_' + counter
@@ -597,31 +306,27 @@ class IdoitBackend extends ExternalBackends {
// 2 = MB
// 3 = GB
- // Update the object.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__MEMORY',
- 'data': {
- 'title': mem.title,
- 'manufacturer': mem.manufacturer,
- 'type': mem.type,
- 'capacity': mem.capacity,
- 'unit': 3
- },
- 'apikey': c.apikey,
- 'language': 'en'
+ let params = {
+ 'object': client.id,
+ 'objID': client.id,
+ 'category': 'C__CATG__MEMORY',
+ 'data': {
+ 'title': mem.title,
+ 'manufacturer': mem.manufacturer,
+ 'type': mem.type,
+ 'capacity': mem.capacity,
+ 'unit': 3
},
- 'id': ramId
- })
+ 'apikey': c.apikey
+ }
counter++
+ bodies.push(this.getBody('cmdb.category.save', params, ramId))
}
}
+ // Update the object. Drive data.
if (client.drives) {
- counter = 1
+ let counter = 1
for (var drive in client.drives) {
var d = client.drives[drive]
var driveId = 'create_drive_' + counter
@@ -634,198 +339,113 @@ class IdoitBackend extends ExternalBackends {
else if (d.unit === 'KB') unit = 1
else if (d.unit === 'B') unit = 0
- // Update the object.
- bodies.push({
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': clientid,
- 'category': 'C__CATG__STORAGE_DEVICE',
- 'data': {
- 'title': d.model,
- 'type': d.type,
- // 'manufacturer': ,
- // 'model': ,
- 'capacity': d.capacity,
- 'unit': unit,
- 'serial': d.serial,
- 'connected': d.connection
- },
- 'apikey': c.apikey,
- 'language': 'en'
+ let params = {
+ 'object': client.id,
+ 'objID': client.id,
+ 'category': 'C__CATG__STORAGE_DEVICE',
+ 'data': {
+ 'title': d.model,
+ 'type': d.type,
+ // 'manufacturer': ,
+ // 'model': ,
+ 'capacity': d.capacity,
+ 'unit': unit,
+ 'serial': d.serial,
+ 'connected': d.connection
},
- 'id': driveId
- })
+ 'apikey': c.apikey
+ }
+ bodies.push(this.getBody('cmdb.category.save', params, driveId))
}
}
- try {
- var requestUpdate = await axios.post(c.url, bodies, config)
- } catch (error) {
- console.log(error)
- }
+
+ const requestUpdate = await this.axiosRequest(c.url, bodies, headers)
// 10 is the idoit object id for clients.
var result = {
success: true,
- id: clientid,
+ id: client.id,
type: 10,
- update: requestUpdate ? requestUpdate.success : false,
- updateData: requestUpdate ? requestUpdate.data : false
+ response: requestUpdate
}
return result
}
async getFileList (credentials, externalId) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
- var body = {
- 'version': '2.0',
- 'method': 'cmdb.category.read',
- 'params': {
- 'objID': externalId,
- 'category': 'C__CATG__FILE',
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 1
- }
- let result = await axios.post(c.url, body, config)
- return result.data.result
+ const c = this.mapCredentials(credentials)
+ const body = this.getBody('cmdb.category.read', { 'objID': externalId, 'category': 'C__CATG__FILE', apikey: c.apikey }, 'filelist')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
+
+ const result = await this.axiosRequest(c.url, [body], headers)
+ return result[0].result
}
async getFile (credentials, externalId, filename) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
+ const c = this.mapCredentials(credentials)
+ const body = this.getBody('cmdb.category.read', { 'objID': externalId, 'category': 'C__CATG__FILE', apikey: c.apikey }, 'filelist')
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
- var body = {
- 'version': '2.0',
- 'method': 'cmdb.category.read',
- 'params': {
- 'objID': externalId,
- 'category': 'C__CATG__FILE',
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 1
- }
- let files = await axios.post(c.url, body, config)
- let fileObjId = files.data.result.find(x => x.file.title === filename).file.id
+ const files = await this.axiosRequest(c.url, [body], headers)
+ let fileObjId = files[0].result.find(x => x.file.title === filename).file.id
- var body2 = {
- 'version': '2.0',
- 'method': 'cmdb.category.read',
- 'params': {
- 'objID': fileObjId,
- 'category': 'C__CMDB__SUBCAT__FILE_VERSIONS',
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': 1
- }
- let result = await axios.post(c.url, body2, config)
- result = result.data.result[0]
+ const body2 = this.getBody('cmdb.category.read', { 'objID': fileObjId, 'category': 'C__CMDB__SUBCAT__FILE_VERSIONS', apikey: c.apikey }, 'file')
+ let result = await this.axiosRequest(c.url, [body2], headers)
+ result = result[0].result[0]
return { filename: result.file_title, value: result.file_content.value, md5: result.md5_hash }
}
async uploadFiles (credentials, externalId, files) {
- var c = this.mapCredentials(credentials)
- var login = await this.getSession(c)
- var sid = login.data.result['session-id']
-
- var config = {
- timeout: 180000,
- headers: {
- 'X-RPC-Auth-Session': sid,
- 'Content-Type': 'application/json'
- }
- }
- var result = []
- for (var key in files) {
- var body = {
- 'version': '2.0',
- 'method': 'cmdb.object.create',
- 'params': {
- 'type': 29,
- 'title': files[key].name,
- 'apikey': c.apikey,
- 'language': 'en'
- },
- 'id': key
- }
- var fileObject = await axios.post(c.url, body, config)
- result.push(fileObject)
+ const c = this.mapCredentials(credentials)
+ const headers = await this.getHeaders(c)
+ if (headers.error) return headers
+ let result = []
+ for (var key in files) {
+ const filename = files[key].name
/* eslint-disable */
- var buffer = new Buffer.from(files[key].data)
+ const buffer = new Buffer.from(files[key].data)
/* eslint-enable */
- var filename = files[key].name
+ // Create the fileObject where the file gets uplaoded to.
+ const body = this.getBody('cmdb.object.create', { 'type': 29, 'title': files[key].name, 'apikey': c.apikey }, 'createFileObject_' + key)
+ const fileObject = await this.axiosRequest(c.url, [body], headers)
// Upload file to fileobject.
- body = {
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': fileObject.data.result.id,
- 'data': {
- 'file_content': buffer.toString('base64'),
- 'file_physical': filename,
- 'file_title': filename,
- 'version_description': key
- },
- 'category': 'C__CMDB__SUBCAT__FILE_VERSIONS',
- 'apikey': c.apikey,
- 'language': 'en'
+ const paramsUploadFile = {
+ 'object': fileObject[0].result.id, // <-- workaround for the idoit api bug (wrong mapping of objID)
+ 'objID': fileObject[0].result.id,
+ 'data': {
+ 'file_content': buffer.toString('base64'),
+ 'file_physical': filename,
+ 'file_title': filename,
+ 'version_description': key
},
- 'id': key
+ 'category': 'C__CMDB__SUBCAT__FILE_VERSIONS',
+ 'apikey': c.apikey
}
- var fileupload = await axios.post(c.url, body, config)
- result.push(fileupload)
-
- // Combine fileObject with object.
- body = {
- 'version': '2.0',
- 'method': 'cmdb.category.create',
- 'params': {
- 'objID': externalId,
- 'data': {
- 'file': fileObject.data.result.id
- },
- 'category': 'C__CATG__FILE',
- 'apikey': c.apikey,
- 'language': 'en'
+ const bodyUploadFile = this.getBody('cmdb.category.save', paramsUploadFile, 'uploadFile_' + key)
+ const uploadFile = await this.axiosRequest(c.url, [bodyUploadFile], headers)
+
+ // Connect the file with the client (object).
+ const paramsConnectFile = {
+ 'object': externalId,
+ 'objID': externalId,
+ 'data': {
+ 'file': fileObject[0].result.id
},
- 'id': 4
- }
- var concat = await axios.post(c.url, body, config)
- result.push(concat)
- }
+ 'category': 'C__CATG__FILE',
+ 'apikey': c.apikey }
+ const bodyConnect = this.getBody('cmdb.category.save', paramsConnectFile, 'uploadFile_' + key)
+ const connectFile = await this.axiosRequest(c.url, [bodyConnect], headers)
- return { result: result }
+ result.push({ createObject: fileObject, uploadFile: uploadFile, connectObjectFile: connectFile })
+ }
+ return result
}
- // ############################################################################
- // ####################### helper/optional functions #########################
-
// Helper function, to map the array of credential objects into a single js object.
mapCredentials (credentials) {
const c = JSON.parse(credentials)
@@ -843,61 +463,86 @@ class IdoitBackend extends ExternalBackends {
return mapped
}
- // Username and password are optional.
- async getSession (credentials) {
- // Headers
- var headers = {}
- // Optional credentials
- if (credentials.login) {
- headers['X-RPC-Auth-Username'] = credentials.username
- headers['X-RPC-Auth-Password'] = credentials.password
- }
-
- // Params
- var params = {
- 'apikey': credentials.apikey,
- 'language': 'en'
+ // Method for making the axios request and error handling.
+ async axiosRequest (url, bodies, headers, batchRequestSize = 400) {
+ let config = { timeout: 180000, headers: headers }
+
+ // Split batchrequest in multiple request
+ let batchRequests = []
+ // For spliceing the array a while loop seems to be the most efficient:
+ // https://ourcodeworld.com/articles/read/278/how-to-split-an-array-into-chunks-of-the-same-size-easily-in-javascript
+ while (bodies.length) {
+ batchRequests = [...batchRequests, bodies.splice(0, batchRequestSize)]
+ }
+ // Make all batch request and return the result of all.
+ let results = []
+ let requestCounter = 1
+
+ for (let i = 0; i < batchRequests.length; i++) {
+ // Axios error handling
+ try {
+ console.log(requestCounter + '/' + batchRequests.length + ' requests send')
+ requestCounter++
+ const responses = await axios.post(url, batchRequests[i], config)
+ if (Array.isArray(responses.data)) results = [...results, ...responses.data]
+ else results = [...results, responses.data]
+ } catch (error) {
+ let errorResponse = { error: true }
+ if (error.response) {
+ // The request was made and the server responded with a status code
+ // that falls out of the range of 2xx
+ errorResponse['data'] = error.response.data
+ errorResponse['status'] = error.response.status
+ errorResponse['headers'] = error.response.headers
+ } else if (error.request) {
+ // The request was made but no response was received
+ // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
+ // http.ClientRequest in node.js
+ errorResponse['errno'] = error.errno
+ } else {
+ // Something happened in setting up the request that triggered an Error
+ errorResponse['message'] = error.message
+ }
+
+ return errorResponse
+ }
}
-
- // Make a login request and see if we are authenticated.
- return this.axiosRequest(credentials.url, 'idoit.login', params, headers)
+ return results
}
- // Helper function to make the axios http/https requests to reduced copy pasta code in this backend. Including the error handling.
- async axiosRequest (url, method, params, headers) {
- const body = {
+ // Body wrapper for the requests to remove duplicated code.
+ getBody (method, params, id) {
+ return {
'version': '2.0',
'method': method,
- 'params': params,
- 'id': 1
+ 'params': {
+ ...params,
+ 'language': 'en'
+ },
+ 'id': id
}
+ }
- var config = {
- timeout: 180000,
- headers: headers
- }
- config.headers['Content-Type'] = 'application/json'
- var response = await axios.post(url, body, config)
- .then(response => {
- return response
- })
- .catch(error => {
- console.log(error)
- return error.response ? error.response : { status: 900, statusText: 'Request failed timeout' }
- })
- // Axios error handling
- if (response.status !== 200) {
- return { success: false, error: response.status, msg: response.statusText }
- }
- // iDoIT error handling.
- if (response.data.result) {
- return { success: true, data: response.data }
- } else if (response.data.error) {
- console.log(response.data.error)
- return { success: false, error: response.data.error.message, msg: response.data.error.data.error }
- } else {
- return { success: false, error: 'UNNOWN_ERROR' }
+ // Returns the header. Sets the session id if needed.
+ async getHeaders (credentials = {}) {
+ let headers = { 'Content-Type': 'application/json' }
+
+ // Get a session id for the header
+ if (credentials.login && credentials.username && credentials.password) {
+ const header = {
+ ...headers,
+ 'X-RPC-Auth-Username': credentials.username,
+ 'X-RPC-Auth-Password': credentials.password
+ }
+ const sessionRequest = await this.axiosRequest(credentials.url, [this.getBody('idoit.login', { 'apikey': credentials.apikey, 'language': 'en' }, 'login')], header)
+ // Axios errors
+ if (sessionRequest.error) return sessionRequest
+ // Idoit error
+ if (sessionRequest[0].error) return { error: 'IDOIT_ERROR', message: sessionRequest[0].error.message }
+ headers = { ...headers, 'X-RPC-Auth-Session': sessionRequest[0].result['session-id'] }
}
+
+ return headers
}
}
diff --git a/server/lib/external-backends/backends/infoblox-backend.js b/server/lib/external-backends/backends/infoblox-backend.js
index 9d070ac..2b2c6d1 100644
--- a/server/lib/external-backends/backends/infoblox-backend.js
+++ b/server/lib/external-backends/backends/infoblox-backend.js
@@ -25,20 +25,20 @@ class InfobloxBackend extends ExternalBackends {
*
* return: { success: <boolean>, status: '<STATUS_CODE_IF_ERROR>', error: '<ERROR_MESSAGE>' }
*/
- checkConnection (credentials) {
+ async checkConnection (credentials) {
var c = this.mapCredentials(credentials)
var ipam = new Infoblox({
ip: c.url,
apiVersion: c.version
})
- return ipam.login(c.username, c.password).then(response => {
- if (response) {
- return { success: true }
- } else {
- return { success: false, error: 'Login failed' }
- }
- })
+ const response = await ipam.login(c.username, c.password)
+
+ if (response) {
+ return true
+ } else {
+ return { error: 'LOGIN_FAILED', message: 'Login failed' }
+ }
}
/*
diff --git a/server/lib/external-backends/index.js b/server/lib/external-backends/index.js
index 92e0f07..755cef4 100644
--- a/server/lib/external-backends/index.js
+++ b/server/lib/external-backends/index.js
@@ -141,13 +141,21 @@ class ExternalBackends {
* credentials: <BACKEND_CREDENTIALS>
* The client parameters are all optional.
* client: {
- * id: <CLIENT_ID>, title: <CLIENT_TITLE>, parentId: <PARENT_ID>, uuid: <CLIENT_UUID>,
+ * id: <CLIENT_ID>, title: <CLIENT_TITLE>, parentId: <PARENT_ID>, uuid: <CLIENT_UUID>, type: <CLIENT/SERVER>
* 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: [{ model: <RAM_MODEL>, manufacturer: <RAM_MANUFACTURER>, type: <RAM_TYPE>, capacity: <RAM_CAPACITY>, unit: <RAM_UNIT> }, ...],
* storage: {},
* network: { mac: <MAC_ADDRESS>, ip: <IP_ADDRESS> }
* }
+ *
+ * Servers are clients, that can additionally have special values:
+ * {
+ * ..., rackid: <RACK_ID>
+ * location: { assembly: <Horizontal/Vertical>, insertion: <Back/Front/Front and Back>, position: <RU 1 - 46> }
+ * system: { model: <SYSTEM_MODEL>, manufacturer: <SYSTEM_MANUFACTURER>, serialnumber: <SYSTEM_SERIALNUMBER> },
+ * formfactor: { formfactor: <e.g. 19">, rackUnits: <integer> }
+ * }
*/
async updateClient (credentials, client) {
return { success: false, error: 'NOT_IMPLEMENTED_EXCEPTION', message: 'The provided backend does not have an updateClient method' }