summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJannik Schönartz2019-03-20 05:22:50 +0100
committerJannik Schönartz2019-03-20 05:22:50 +0100
commit67d1402c75e562af34058d0021cf6a14b5588d22 (patch)
treed977ee4fce3adbf0de27b4372c5589ece81e54d9 /server
parent[server/registration] Add client with json instead of parameters (ipxe) (diff)
downloadbas-67d1402c75e562af34058d0021cf6a14b5588d22.tar.gz
bas-67d1402c75e562af34058d0021cf6a14b5588d22.tar.xz
bas-67d1402c75e562af34058d0021cf6a14b5588d22.zip
[server/registration/backends] Rework addClient and updateClient to receive json
Add idoit workaround for saving floats again Rework the grepSystemInfo bash script to match the new api
Diffstat (limited to 'server')
-rw-r--r--server/api/registration.js157
-rwxr-xr-xserver/ipxe/bash_scripts/addServer.sh6
-rwxr-xr-xserver/ipxe/bash_scripts/grepSystemInfoRework.sh171
-rw-r--r--server/lib/external-backends/backendhelper.js204
-rw-r--r--server/lib/external-backends/backends/idoit-backend.js132
-rw-r--r--server/lib/external-backends/index.js13
-rw-r--r--server/lib/iphelper.js2
7 files changed, 386 insertions, 299 deletions
diff --git a/server/api/registration.js b/server/api/registration.js
index 11de700..4891e31 100644
--- a/server/api/registration.js
+++ b/server/api/registration.js
@@ -107,17 +107,17 @@ noAuthRouter.post('/group', (req, res) => {
})
/*
- * Reworked add method for adding a client or server.
+ * Add method for adding a client or server.
*/
noAuthRouter.postAsync('/', async (req, res) => {
let client = req.body.client
if (typeof client === 'string') client = JSON.parse(client)
- const ipxe = req.body.ipxe
- if (typeof ipxe === 'string') ipxe === 'true' ? true : false
+ let ipxe = req.body.ipxe
+ if (typeof ipxe === 'string') ipxe = true
if (!client.type) client.type = 'CLIENT'
- if (!client.title) client.title = client.type + '_' + client.uuid
+ if (!client.name) client.name = client.type + '_' + client.uuid
// If the client already exists return the configloader ipxe script.
const clientDb = await db.client.findOne({ where: { uuid: client.uuid } })
@@ -128,7 +128,7 @@ noAuthRouter.postAsync('/', async (req, res) => {
// Client does not exist.
if (!client.parents) client.parents = []
- const createClient = { name: client.title, description: client.type, ip: client.network.ip, mac: client.network.mac, uuid: client.uuid }
+ const createClient = { name: client.name, description: client.type, ip: client.network.ip, mac: client.network.mac, uuid: client.uuid }
if (client.type === 'CLIENT') createClient.registrationState = await getNextHookScript(client.parents)
const newClient = await db.client.create(createClient)
client.id = newClient.id
@@ -136,7 +136,7 @@ noAuthRouter.postAsync('/', async (req, res) => {
// Add groups to the client.
if (client.parents.length === 0) client.parents = await ipHelper.getGroups(client.network.ip)
client.parents.forEach(pid => { newClient.addGroup(pid) })
- log({ category: 'CLIENT_REGISTRATION', description: client.type + ' added successfully.', clientId: newClient.id })
+ log({ category: 'CLIENT_REGISTRATION', description: 'Client added successfully.', clientId: newClient.id })
// Add the client to the backends.
const result = await backendHelper.addClient(client)
@@ -144,142 +144,25 @@ noAuthRouter.postAsync('/', async (req, res) => {
else return res.send(result)
})
-/*
- * Adds the client to the database and set parents if a parent was selected. Calls addClient for all external-backends.
- */
-noAuthRouter.postAsync('/add', async (req, res) => {
- const feedback = req.body.feedback
- const mac = req.body.mac
- const uuid = req.body.uuid
- const ip = req.body.ip
- let name = req.body.name
- const parentId = parseInt(req.body.id)
- const purpose = req.body.purpose
- let parentIds = []
-
- if (!name) name = 'Client_' + uuid
-
- // If the client already exists return the configloader ipxe script.
- const client = await db.client.findOne({ where: { uuid: uuid } })
- if (client) return res.send(`#!ipxe\nchain https://` + url + `/api/configloader/\${uuid}`)
-
- // Else (Client does not exist)
- var groupids = []
- if (parentId) groupids = [parentId]
- const resId = await getNextHookScript(groupids)
- const newClient = await db.client.create({ name: name, description: 'Client', ip: ip, mac: mac, uuid: uuid, registrationState: resId })
- if (parentId) {
- newClient.addGroup(parentId)
- parentIds.push(parentId)
- } else {
- // Filtered list with all group we will add the client
- parentIds = await ipHelper.getGroups(ip)
- parentIds.forEach(pid => { newClient.addGroup(pid) })
- }
- log({ category: 'CLIENT_REGISTRATION', description: 'Client added successfully.', clientId: newClient.id })
-
- // Add the client to the backends.
- var c = { id: newClient.id, title: name, uuid: uuid, network: { mac: mac, ip: ip }, type: req.body.type }
- if (parentIds.length > 0) c.parents = parentIds
- if (purpose) c.purpose = purpose
-
- var result = await backendHelper.addClient(c)
-
- if (feedback) res.send(result)
- else res.send(`#!ipxe\nchain https://` + url + `/api/configloader/\${uuid}`)
-})
-
-noAuthRouter.postAsync('/:uuid/update', async (req, res) => {
- const uuid = req.params.uuid
- const name = req.body.name
- const parentId = req.body.id
-
- // System
- const sysManufacturer = req.body.sys_manufacturer
- const sysModel = req.body.sys_model
- const sysSerial = req.body.sys_serial
-
- // CPU
- const cpuModel = req.body.cpu_model
- const cpuManufacturer = req.body.cpu_manufacturer
- const cpuType = req.body.cpu_type
- var cpuFrequency = req.body.cpu_frequency / 1000
- const cpuCores = req.body.cpu_cores
-
- // RAM
- if (req.body.ram_size) {
- const ramSize = req.body.ram_size.split('\n')
- const ramManufacturer = req.body.ram_manufacturer.split('\n')
- const ramFormfactor = req.body.ram_formfactor.split('\n')
- const ramType = req.body.ram_type.split('\n')
- const ramIsEcc = req.body.ram_isecc.replace('Error Correction Type: ', '')
- var ramModules = []
-
- // Build ram array
- for (let ram in ramSize) {
- if (ramSize[ram].replace('Size: ', '') !== 'No Module Installed') {
- const size = ramSize[ram].replace('Size: ', '').split(' ')
- let title = ramFormfactor[ram].replace('Form Factor: ', '')
- if (ramIsEcc === 'Single-bit ECC') title += '-ECC'
-
- const ramModule = {
- capacity: size[0],
- unit: size[1],
- manufacturer: ramManufacturer[ram].replace('Manufacturer: ', ''),
- title: title,
- type: ramType[ram].replace('Type: ', '')
- }
- ramModules.push(ramModule)
- }
- }
- }
+noAuthRouter.postAsync('/:uuid', async (req, res) => {
+ let client = req.body.client
- // SSD / HDD
- if (req.body.drives) {
- const drivesRaw = req.body.drives.split('%OBJECT_SPLITTER%')
- var drives = []
- for (let driveRaw in drivesRaw) {
- if (drivesRaw[driveRaw].length > 0) {
- const dRaw = drivesRaw[driveRaw].split('%ATTRIBUTE_SPLITTER%')
- const drive = {
- model: dRaw[0].trim().replace('Device Model: ', ''),
- serial: dRaw[1].trim().replace('Serial Number: ', ''),
- capacity: dRaw[2].trim().split(' ')[0],
- unit: dRaw[2].trim().split(' ')[1],
- type: dRaw[3].trim().replace('Rotation Rate: ', ''),
- formfactor: dRaw[4].trim().replace('Form Factor: ', ''),
- connection: dRaw[5].trim().replace('SATA Version is: ', '')
- }
- drives.push(drive)
- }
- }
+ // Add the name to the ram modules.
+ for (let ram of client.ram.modules) {
+ ram.name = ram.formfactor
+ if (client.ram.isEcc === 'Single-bit ECC') ram.name += '-ECC'
}
- const client = await db.client.findOne({ where: { uuid: uuid } })
- if (!client) return res.status(404).send({ error: 'CLIENT_NOT_FOUND', message: 'There is no client matching the provided uuid.' })
-
- client.update({ name: name })
- var c = { uuid: uuid, id: client.id }
- if (name) c.title = name
- if (parentId) c.parentId = parentId
+ const clientDb = await db.client.findOne({ where: { uuid: client.uuid } })
+ if (!clientDb) return res.status(404).send({ error: 'CLIENT_NOT_FOUND', message: 'There is no client matching the provided uuid.' })
+ if (client.name) clientDb.update({ name: client.name })
+ client.id = clientDb.id
// System data. Sometime just string with whitespaces only.
- c.system = {}
- if (/\S/.test(sysManufacturer)) c.system.manufacturer = sysManufacturer
- else c.system.manufacturer = 'Not set'
-
- if (/\S/.test(sysModel)) c.system.model = sysModel
- else c.system.model = 'Not set'
-
- if (/\S/.test(sysSerial)) c.system.serialnumber = sysSerial
- else c.system.serialnumber = 'Not set'
-
- // TODO: MULTI GPU's ?!
- c.cpu = { model: cpuModel, manufacturer: cpuManufacturer, type: cpuType, frequency: cpuFrequency, cores: cpuCores }
- if (ramModules) c.ram = ramModules
- if (drives) c.drives = drives
-
- const result = await backendHelper.updateClient(c)
+ if (!/\S/.test(client.system.manufacturer)) client.system.manufacturer = 'unavailable'
+ if (!/\S/.test(client.system.model)) client.system.model = 'unavailable'
+ if (!/\S/.test(client.system.serialnumber)) client.system.serialnumber = 'unavailable'
+ const result = await backendHelper.updateClient(client)
res.send(result)
})
diff --git a/server/ipxe/bash_scripts/addServer.sh b/server/ipxe/bash_scripts/addServer.sh
index 13f81d1..ad6e3aa 100755
--- a/server/ipxe/bash_scripts/addServer.sh
+++ b/server/ipxe/bash_scripts/addServer.sh
@@ -9,7 +9,7 @@ json_data()
"type": "SERVER",
"uuid": "$(dmidecode -q -s system-uuid | grep -v '^#' | head -n 1 | tr '[a-z]' '[A-Z]')",
"network": {
- "mac": "$(cat /sys/class/net/ens3/address)",
+ "mac": "$(ip addr show | grep -Eo -m 1 'ether\s.*\sbrd' | awk '{print $2}')",
"ip": "$(hostname -I | awk '{print $1}')"
},
"location": {
@@ -27,5 +27,5 @@ json_data()
EOF
}
-#curl -d "$(json_data)" -H "Content-Type: application/json" -X POST --insecure https://bas.intra.uni-freiburg.de/api/registration
-curl --data "$(json_data)" -H "Content-Type: application/json" -X POST --insecure https://bas.stfu-kthx.net:8888/api/registration \ No newline at end of file
+curl -d "$(json_data)" -H "Content-Type: application/json" -X POST --insecure https://bas.intra.uni-freiburg.de/api/registration
+# curl --data "$(json_data)" -H "Content-Type: application/json" -X POST --insecure https://bas.stfu-kthx.net:8888/api/registration \ No newline at end of file
diff --git a/server/ipxe/bash_scripts/grepSystemInfoRework.sh b/server/ipxe/bash_scripts/grepSystemInfoRework.sh
new file mode 100755
index 0000000..bdc59b8
--- /dev/null
+++ b/server/ipxe/bash_scripts/grepSystemInfoRework.sh
@@ -0,0 +1,171 @@
+#!/bin/bash
+. /lib/dracut-lib.sh
+# http://git.openslx.org/openslx-ng/mltk.git/tree/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-hardware_stats
+# dmidecode | grep -i UUID
+TYPE="CLIENT"
+
+cpu() {
+ cat << EOF
+{
+ "model": "$1",
+ "manufacturer": "$2",
+ "type": "$3",
+ "cores": "$4",
+ "frequency": "$5",
+ "unit": "$6"
+}
+EOF
+}
+
+getCpus() {
+ readarray -t CPU_MODEL <<< "$(dmidecode -q -s processor-version)"
+ readarray -t CPU_MANUFACTURER <<< "$(dmidecode -q -s processor-manufacturer)"
+ readarray -t CPU_TYPE <<< "$(dmidecode -q -s processor-family)"
+ readarray -t CPU_CORES <<< "$(dmidecode -t processor | grep -o 'Core Count:.*' | cut -f3- -d ' ')"
+ readarray -t CPU_FREQUENCY <<< "$(dmidecode -q -s processor-frequency | cut -f1- -d ' ')"
+
+ CPUS=()
+ FIRST=true
+ for i in ${!CPU_MODEL[@]}; do
+ if [ "$FIRST" == "true" ]; then
+ FIRST=false
+ else
+ CPUS+=", "
+ fi
+
+ frequency=$(echo ${CPU_FREQUENCY[i]} | awk '{print $1}')
+ unit=$(echo ${CPU_FREQUENCY[i]} | awk '{print $2}')
+ CPUS+=$(cpu "${CPU_MODEL[i]}" "${CPU_MANUFACTURER[i]}" "${CPU_TYPE[i]}" "${CPU_CORES[i]}" "$frequency" "$unit")
+ done
+ echo ${CPUS[*]}
+}
+
+# CPU
+CPU_MODEL=$(dmidecode -q -s processor-version)
+# CPUMODEL=$(grep -m1 '^model name\s*:' /proc/cpuinfo | sed 's/^model name\s*:\s*//;s/\s\s*/ /g;s/^ //;s/ $//')
+CPU_MANUFACTURER=$(dmidecode -q -s processor-manufacturer)
+CPU_TYPE=$(dmidecode -q -s processor-family)
+CPU_CORES=$(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | sort -u | wc -l)
+CPU_FREQUENCY=$(dmidecode -q -s processor-frequency)
+CPU_FREQUENCY=${CPU_FREQUENCY%" MHz"}
+
+ram() {
+ cat << EOF
+{
+ "capacity": "$1",
+ "unit": "$2",
+ "manufacturer": "$3",
+ "type": "$4",
+ "formfactor": "$5"
+}
+EOF
+}
+
+getRamModules() {
+ readarray -t RAM_SIZE <<< "$(dmidecode -t 17 | grep -o 'Size:.*' | cut -f2- -d ' ')"
+ readarray -t RAM_MANUFACTURER <<< "$(dmidecode -t 17 | grep -o 'Manufacturer:.*' | cut -f2- -d ' ')"
+ readarray -t RAM_TYPE <<< "$(dmidecode -t 17 | grep -o 'Type:.*' | cut -f2- -d ' ')"
+ readarray -t RAM_FORMFACTOR <<< "$(dmidecode -t 17 | grep -o 'Form Factor:.*' | cut -f3- -d ' ')"
+ RAM_MODULES=()
+ FIRST=true
+ for i in ${!RAM_SIZE[@]}; do
+ if [ "${RAM_SIZE[i]}" == 'No Module Installed' ]
+ then
+ continue
+ fi
+
+ if [ "$FIRST" == "true" ]; then
+ FIRST=false
+ else
+ RAM_MODULES+=", "
+ fi
+
+ size=$(echo ${RAM_SIZE[i]} | awk '{print $1}')
+ unit=$(echo ${RAM_SIZE[i]} | awk '{print $2}')
+ RAM_MODULES+=$(ram "$size" "$unit" "${RAM_MANUFACTURER[i]}" "${RAM_TYPE[i]}" "${RAM_FORMFACTOR[i]}")
+ done
+ echo ${RAM_MODULES[*]}
+}
+
+drive() {
+ cat << EOF
+{
+ "model": "$1",
+ "serial": "$2",
+ "capacity": "$3",
+ "unit": "$4",
+ "type": "$5",
+ "formfactor": "$6",
+ "connection": "$7"
+}
+EOF
+}
+
+getDrives() {
+# HDD / SSD
+# hd parm or smartctl from smartmontools
+drives=$(ls /dev/sd* | grep -o '/dev/sd.$')
+
+DRIVES=()
+FIRST=true
+for drive in $drives; do
+ if [ "$FIRST" == "true" ]; then
+ FIRST=false
+ else
+ DRIVES+=", "
+ fi
+ drivedata=$(mktemp)
+ smartctl -i $drive >> $drivedata
+
+ DRIVE_MODEL=$(cat $drivedata | grep -o "Device Model: .*" | cut -f2- -d ":" | sed -e 's/^[[:space:]]*//')
+ DRIVE_SERIAL=$(cat $drivedata | grep -o "Serial Number: .*" | cut -f2- -d ":" | sed -e 's/^[[:space:]]*//')
+ DRIVE_CAPACITY=$(cat $drivedata | grep -o "User Capacity: .*" | grep -Pzo '(?<=\[)(.*?)(?=\])' | awk '{print $1}')
+ DRIVE_UNIT=$(cat $drivedata | grep -o "User Capacity: .*" | grep -Pzo '(?<=\[)(.*?)(?=\])' | awk '{print $2}')
+ DRIVE_TYPE=$(cat $drivedata | grep -o "Rotation Rate: .*" | cut -f2- -d ":" | sed -e 's/^[[:space:]]*//')
+ DRIVE_FORMFACTOR=$(cat $drivedata | grep -o "Form Factor: .*" | cut -f2- -d ":" | sed -e 's/^[[:space:]]*//')
+ DRIVE_CONNECTION=$(cat $drivedata | grep -o "SATA Version is: .*" | cut -f2- -d ":" | sed -e 's/^[[:space:]]*//')
+ DRIVES+=$(drive "$DRIVE_MODEL" "$DRIVE_SERIAL" "$DRIVE_CAPACITY" "$DRIVE_UNIT" "$DRIVE_TYPE" "$DRIVE_FORMFACTOR" "$DRIVE_CONNECTION")
+done
+echo ${DRIVES[*]}
+}
+
+# System
+# VENDOR=$(dmidecode | grep -Eo '(Vendor).*' | cut -f 2 -d ":")
+
+# Mainboard
+# MAINBOARD_MANUFACTURER=$(dmidecode -q -s baseboard-manufacturer)
+# MAINBOARD_MODEL=$(dmidecode -q -s baseboard-product-name)
+# MAINBOARD_SERIAL_NUMBER=$(dmidecode -q -s baseboard-serial-number)
+UUID=$(dmidecode -q -s system-uuid | grep -v '^#' | head -n 1 | tr '[a-z]' '[A-Z]')
+json_data() {
+ cat << EOF
+{
+ "client": {
+ "parents": [],
+ "type": "$TYPE",
+ "uuid": "$UUID",
+ "network": {
+ "mac": "$(ip addr show | grep -Eo -m 1 'ether\s.*\sbrd' | awk '{print $2}')",
+ "ip": "$(hostname -I | awk '{print $1}')"
+ },
+ "system": {
+ "model": "$(dmidecode -q -s system-product-name)",
+ "manufacturer": "$(dmidecode -q -s system-manufacturer)",
+ "serialnumber": "$(dmidecode -q -s system-serial-number)"
+ },
+ "cpus": [$(getCpus)],
+ "ram": {
+ "modules": [$(getRamModules)],
+ "isEcc": "$(dmidecode -t 16 | grep -o 'Error Correction Type:.*' | cut -f4- -d ' ')"
+ },
+ "drives": [$(getDrives)]
+ }
+}
+EOF
+}
+
+# Curl
+# curl --data "state=6" --insecure https://bas.stfu-kthx.net:8888/api/registrations/$UUID/state
+# curl -d "name=Client_$UUID&sys_manufacturer=$MANUFACTURER&sys_model=$MODEL&sys_serial=$SERIAL&cpu_model=$CPU_MODEL&cpu_manufacturer=$CPU_MANUFACTURER&cpu_type=$CPU_TYPE&cpu_cores=$CPU_CORES&cpu_frequency=$CPU_FREQUENCY&ram_size=$RAM_SIZE&ram_manufacturer=$RAM_MANUFACTURER&ram_type=$RAM_TYPE&ram_isecc=$RAM_ISECC&ram_formfactor=$RAM_FORMFACTOR&drives=${DRIVES[*]}" -H "Content-Type: application/x-www-form-urlencoded" -X POST --insecure https://bas.intra.uni-freiburg.de/api/registration/$UUID/update
+#echo $(json_data)
+curl -d "$(json_data)" -H "Content-Type: application/json" -X POST --insecure https://bas.intra.uni-freiburg.de/api/registration/$UUID \ No newline at end of file
diff --git a/server/lib/external-backends/backendhelper.js b/server/lib/external-backends/backendhelper.js
index 4bd9969..6892f7c 100644
--- a/server/lib/external-backends/backendhelper.js
+++ b/server/lib/external-backends/backendhelper.js
@@ -4,107 +4,115 @@ const ExternalBackends = require(path.join(__appdir, 'lib', 'external-backends')
const db = require(path.join(__appdir, 'lib', 'sequelize'))
const log = require(path.join(__appdir, 'lib', 'log'))
-module.exports = {
- addClient: async function (client) {
- // Get all backends and call addClient for each instance.
- var backends = await db.backend.findAll({ include: ['mappedGroups', 'mappedClients'] })
- var result = []
-
- for (var b in backends) {
- var backend = backends[b]
- const ba = new ExternalBackends()
- const instance = ba.getInstance(backend.type)
- var tmpClient = JSON.parse(JSON.stringify(client))
-
- // 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) {
- 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' })
-
- // Add backend to the conflict.
- conflict.createObject({ objectType: 'BACKEND', objectId: backend.id })
-
- // Add the groups to the conflict.
- for (let element of elements) {
- conflict.createObject({ objectType: 'GROUP', objectId: element.id })
- }
- } else if (elements.length === 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId
- }
-
- 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 } })
- }
- if (addClient.error && addClient.error !== 'NOT_IMPLEMENTED_EXCEPTION') log({ category: 'BACKEND_ERROR', description: `[${addClient.backendId}] ${addClient.error}: ${addClient.message}`, clientId: client.id })
- result.push(addClient)
+module.exports = { addClient, updateClient, deleteClients, uploadFiles }
+
+async function addClient (client) {
+ // Get all backends and call addClient for each instance.
+ var backends = await db.backend.findAll({ include: ['mappedGroups', 'mappedClients'] })
+ var result = []
+
+ for (var b in backends) {
+ var backend = backends[b]
+ const ba = new ExternalBackends()
+ const instance = ba.getInstance(backend.type)
+ var tmpClient = JSON.parse(JSON.stringify(client))
+
+ // Convert the parent group ids to the external backend parentIds. If multiple -> conflict
+ if (client.parents) {
+ 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' })
+
+ // Add backend to the conflict.
+ conflict.createObject({ objectType: 'BACKEND', objectId: backend.id })
+
+ // Add the groups to the conflict.
+ for (let element of elements) {
+ conflict.createObject({ objectType: 'GROUP', objectId: element.id })
+ }
+ } else if (elements.length === 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId
}
- return result
- },
-
- updateClient: async function (client) {
- // Get all backends and call addClient for each instance.
- const backends = await db.backend.findAll({ include: ['mappedGroups', 'mappedClients'] })
- let result = []
-
- 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))
-
- // Get the external clientid.
- var exid = backend.mappedClients.find(y => y.id === parseInt(client.id))
- if (exid) tmpClient.id = exid.backend_x_client.externalId
-
- // Convert the parent group id to the external backend parentId.
- if (client.parentId) {
- var element = backend.mappedGroups.find(x => x.id === parseInt(client.parentId))
- if (element) tmpClient['parentId'] = element.backend_x_group.externalId
- }
-
- let updateClient = await instance.updateClient(backend.credentials, tmpClient)
- updateClient.backendId = backend.id
- result.push(updateClient)
+
+ 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 } })
}
- return result
- },
-
- deleteClients: async function (clientids) {
- // Get all backends and call deleteClient for each instance.
- const backends = await db.backend.findAll({ where: { '$clientMappings.clientid$': clientids }, include: ['clientMappings'] })
-
- backends.forEach(backend => {
- const ba = new ExternalBackends()
- const instance = ba.getInstance(backend.type)
- var objectsToDelete = []
- backend.clientMappings.forEach(mapping => {
- objectsToDelete.push(mapping.externalId)
- })
- // If there are objects to delete -> delete them.
- if (objectsToDelete.length > 0) instance.deleteObjects(backend.credentials, objectsToDelete)
- })
- },
-
- uploadFiles: async function (clientId, files) {
- 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)
-
- let exid = backend.mappedClients.find(y => y.id === parseInt(clientId))
- if (exid) exid = exid.backend_x_client.externalId
- results.push(await instance.uploadFiles(backend.credentials, exid, files))
+ if (addClient.error && addClient.error !== 'NOT_IMPLEMENTED_EXCEPTION') log({ category: 'BACKEND_ERROR', description: `[${addClient.backendId}] ${addClient.error}: ${addClient.message}`, clientId: client.id })
+ result.push(addClient)
+ }
+ return result
+}
+
+async function updateClient (client) {
+ // Get all backends and call addClient for each instance.
+ const backends = await db.backend.findAll({ include: ['mappedGroups', 'mappedClients'] })
+ let result = []
+
+ 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))
+
+ // Get the external clientid.
+ var exid = backend.mappedClients.find(y => y.id === parseInt(client.id))
+ if (exid) tmpClient.id = exid.backend_x_client.externalId
+
+ // Convert the parent group ids to the external backend parentIds. If multiple -> conflict
+ if (client.parents) {
+ 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' })
+
+ // Add backend to the conflict.
+ conflict.createObject({ objectType: 'BACKEND', objectId: backend.id })
+
+ // Add the groups to the conflict.
+ for (let element of elements) {
+ conflict.createObject({ objectType: 'GROUP', objectId: element.id })
+ }
+ } else if (elements.length === 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId
}
- return results
+
+ let updateClient = await instance.updateClient(backend.credentials, tmpClient)
+ updateClient.backendId = backend.id
+ result.push(updateClient)
}
+ return result
+}
+
+async function deleteClients (clientids) {
+ // Get all backends and call deleteClient for each instance.
+ const backends = await db.backend.findAll({ where: { '$clientMappings.clientid$': clientids }, include: ['clientMappings'] })
+
+ backends.forEach(backend => {
+ const ba = new ExternalBackends()
+ const instance = ba.getInstance(backend.type)
+ var objectsToDelete = []
+ backend.clientMappings.forEach(mapping => {
+ objectsToDelete.push(mapping.externalId)
+ })
+ // If there are objects to delete -> delete them.
+ if (objectsToDelete.length > 0) instance.deleteObjects(backend.credentials, objectsToDelete)
+ })
+}
+async function uploadFiles (clientId, files) {
+ 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)
+
+ let exid = backend.mappedClients.find(y => y.id === parseInt(clientId))
+ if (exid) exid = exid.backend_x_client.externalId
+ 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 8c1a4c3..ce7680a 100644
--- a/server/lib/external-backends/backends/idoit-backend.js
+++ b/server/lib/external-backends/backends/idoit-backend.js
@@ -170,7 +170,7 @@ class IdoitBackend extends ExternalBackends {
if (headers.error) return headers
let params = {
'apikey': c.apikey,
- 'title': client.title,
+ 'title': client.name,
'purpose': client.purpose === 'Pool PC' ? 7 : undefined,
'categories': {}
}
@@ -218,7 +218,7 @@ class IdoitBackend extends ExternalBackends {
'apikey': c.apikey
}
const bodyMac = this.getBody('cmdb.category.save', paramsMac, 'add_mac_address')
- const requestMac = await this.axiosRequest(c.url, [bodyMac], headers)
+ await this.axiosRequest(c.url, [bodyMac], headers)
}
// Purpose for Clients:
@@ -247,9 +247,11 @@ class IdoitBackend extends ExternalBackends {
if (headers.error) return headers
let bodies = []
+ // workaround for the fucking idoit shit. -.-
+ let requestResults = []
// 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'))
+ 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.
@@ -298,95 +300,123 @@ class IdoitBackend extends ExternalBackends {
// Update the object. CPU data.
// TODO: Delete cpu if exists?
- if (client.cpu) {
- 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
- },
- 'apikey': c.apikey
+ if (client.cpus) {
+ let counter = 1
+ for (let cpu of client.cpus) {
+ // Add KB and TB
+ if (cpu.unit === 'MB') cpu.unit = 2
+ else if (cpu.unit === 'GB') 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': 3,
+ 'cores': parseInt(cpu.cores)
+ },
+ 'apikey': c.apikey
+ }
+
+ counter++
+ // WORKAROUND
+ // bodies.push(this.getBody('cmdb.category.save', params, 'create_cpu_' + counter))
+ const a = await this.axiosRequest(c.url, [this.getBody('cmdb.category.save', params, 'create_cpu_' + counter)], headers)
+ requestResults.push(a)
}
- bodies.push(this.getBody('cmdb.category.save', params, 'update_cpu'))
}
// Update the object. Ram data.
if (client.ram) {
let counter = 1
- for (var memory in client.ram) {
- var mem = client.ram[memory]
- var ramId = 'create_memory_' + counter
- if (mem.unit === 'MB') mem.capacity = mem.capacity / 1024
+ 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
- // 2 = MB
- // 3 = GB
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
+ 'title': module.type,
+ 'manufacturer': module.manufacturer,
+ 'type': module.type,
+ 'capacity': parseFloat(module.capacity),
+ 'unit': module.unit
},
'apikey': c.apikey
}
counter++
- bodies.push(this.getBody('cmdb.category.save', params, ramId))
+ // WORKAROUND
+ // bodies.push(this.getBody('cmdb.category.save', params, 'create_memory_' + counter))
+ const a = await this.axiosRequest(c.url, [this.getBody('cmdb.category.save', params, 'create_memory_' + counter)], headers)
+ requestResults.push(a)
}
}
// Update the object. Drive data.
if (client.drives) {
let counter = 1
- for (var drive in client.drives) {
- var d = client.drives[drive]
- var driveId = 'create_drive_' + counter
-
+ for (let drive of client.drives) {
// UNIT
- var unit = 0
- if (d.unit === 'GB') unit = 3
- else if (d.unit === 'TB') unit = 4
- else if (d.unit === 'MB') unit = 2
- else if (d.unit === 'KB') unit = 1
- else if (d.unit === 'B') unit = 0
+ if (drive.unit === 'GB') drive.unit = 3
+ else if (drive.unit === 'MB') drive.unit = 2
+ else if (drive.unit === 'TB') drive.unit = 4
+ else if (drive.unit === 'KB') drive.unit = 1
+ else if (drive.unit === 'B') drive.unit = 0
+
+ if (drive.type === 'Solid State Device') drive.type = 'SSD'
+ else if (drive.type === '5400 rpm') drive.type = 'Hard disk'
+ 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',
'data': {
- 'title': d.model,
- 'type': d.type,
+ 'category_id': counter,
+ 'title': drive.model,
+ 'type': drive.type,
// 'manufacturer': ,
// 'model': ,
- 'capacity': d.capacity,
- 'unit': unit,
- 'serial': d.serial,
- 'connected': d.connection
+ 'capacity': parseFloat(drive.capacity),
+ 'unit': drive.unit,
+ 'serial': drive.serial,
+ 'connected': drive.connection
},
'apikey': c.apikey
}
- bodies.push(this.getBody('cmdb.category.save', params, driveId))
+
+ counter++
+ // WORKAROUND
+ // bodies.push(this.getBody('cmdb.category.save', params, 'create_drive_' + counter))
+ const a = await this.axiosRequest(c.url, [this.getBody('cmdb.category.save', params, 'create_drive_' + counter)], headers)
+ requestResults.push(a)
}
}
const requestUpdate = await this.axiosRequest(c.url, bodies, headers)
+ requestResults.push(requestUpdate)
+
+ if (requestUpdate.error) return requestUpdate
// 10 is the idoit object id for clients.
- var result = {
+ // 5 is the idoit object id for servers.
+ let type = 0
+ if (client.type === 'CLIENT') type = 10
+ else if (client.type === 'SERVER') type = 5
+
+ const result = {
success: true,
id: client.id,
- type: 10,
- response: requestUpdate
+ type: type,
+ // response: requestUpdate
+ response: requestResults
}
return result
diff --git a/server/lib/external-backends/index.js b/server/lib/external-backends/index.js
index 41d1c31..7acaa85 100644
--- a/server/lib/external-backends/index.js
+++ b/server/lib/external-backends/index.js
@@ -128,7 +128,10 @@ class ExternalBackends {
* The client parameters are all optional. If the client has an id the object is not created but the categories of the object.
* client: {
* id: <CLIENT_ID>, title: <CLIENT_TITLE>, parentId: <PARENT_ID>, uuid: <CLIENT_UUID>,
- * network: { mac: <MAC_ADDRESS>, ip: <IP_ADDRESS> }
+ * network: { mac: <MAC_ADDRESS>, ip: <IP_ADDRESS> },
+ * 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 addClient (credentials, client) {
@@ -148,14 +151,6 @@ class ExternalBackends {
* 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 { error: 'NOT_IMPLEMENTED_EXCEPTION', message: 'The provided backend does not have an updateClient method' }
diff --git a/server/lib/iphelper.js b/server/lib/iphelper.js
index 769dcc3..8432b01 100644
--- a/server/lib/iphelper.js
+++ b/server/lib/iphelper.js
@@ -5,7 +5,7 @@ module.exports = { toDecimal, toIPv4, getGroups, isIPv4 }
// Finds the groups where the ip fits best in the subnets.
async function getGroups (ipString) {
- const ipInt = toDecimal(ipString)
+ const ipInt = toDecimal(ipString)
let fittingIpRanges = await db.iprange.findAll({ where: { startIp: { [db.Op.lte]: ipInt }, endIp: { [db.Op.gte]: ipInt } } })
fittingIpRanges = fittingIpRanges.map(x => x.groupId)