From cee759da4149a1681a89e10cc849a0cadff3bf2d Mon Sep 17 00:00:00 2001 From: Jannik Schönartz Date: Tue, 11 Dec 2018 12:59:50 +0000 Subject: [registration/idoit] TPM upload functionality + improve hw specs Improved IdoIT hw specs capture. Including multiple ram slots. Set purpose of the automatic registration to Pool PC. Added upload files to idoit for uploading the tpm and ssl key. --- server/api/registrations.js | 81 ++++++++++--- server/ipxe/grepSystemInfo.sh | 24 +++- server/ipxe/registration.ipxe | 2 +- server/lib/external-backends/backendhelper.js | 13 ++ .../external-backends/backends/idoit-backend.js | 133 ++++++++++++--------- server/lib/external-backends/index.js | 4 +- 6 files changed, 177 insertions(+), 80 deletions(-) diff --git a/server/api/registrations.js b/server/api/registrations.js index 71e69a4..9192619 100644 --- a/server/api/registrations.js +++ b/server/api/registrations.js @@ -135,8 +135,12 @@ noAuthRouter.post('/add', (req, res) => { const mac = req.body.mac const uuid = req.body.uuid const ip = req.body.ip - const name = req.body.name + var name = req.body.name const parentId = req.body.id + const purpose = req.body.purpose + + if (!name) name = 'Client_' + uuid + db.client.findOne({ where: { uuid: uuid } }).then(client => { if (client) res.send(`#!ipxe\nchain https://bas.intra.uni-freiburg.de/api/configloader/\${uuid}`) else { @@ -149,10 +153,9 @@ noAuthRouter.post('/add', (req, res) => { } // Add the client to the backends. - const c = { uuid: uuid, network: { mac: mac, ip: ip } } + var c = { title: name, uuid: uuid, network: { mac: mac, ip: ip } } if (parentId) c.parentId = parentId - if (name) c.title = name - else c.title = 'Client_' + uuid + if (purpose) c.purpose = purpose backendHelper.addClient(c).then(result => { if (feedback) res.send(result) result.forEach(response => { @@ -171,31 +174,71 @@ noAuthRouter.post('/add', (req, res) => { }) }) -noAuthRouter.post('/update', (req, res) => { - const uuid = req.body.uuid +noAuthRouter.post('/:uuid/update', (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 - const cpuFrequency = req.body.cpu_frequency + var cpuFrequency = req.body.cpu_frequency / 1000 const cpuCores = req.body.cpu_cores - const ramModel = req.body.ram_model - const ramManufacturer = req.body.ram_manufacturer - const ramCapacity = req.body.ram_capacity - const ramUnit = req.body.ram_unit + + // RAM + var ramSize = req.body.ram_size.split('\n') + var ramManufacturer = req.body.ram_manufacturer.split('\n') + var ramFormfactor = req.body.ram_formfactor.split('\n') + var ramType = req.body.ram_type.split('\n') + var ramIsEcc = req.body.ram_isecc.replace('Error Correction Type: ', '') + var ramModules = [] + // Build ram array + for (var ram in ramSize) { + if (ramSize[ram].replace('Size: ', '') !== 'No Module Installed') { + const size = ramSize[ram].replace('Size: ', '').split(' ') + const title = ramFormfactor[ram].replace('Form Factor: ', '') + if (ramIsEcc === 'Single-bit ECC') title += '-ECC' + + var ramModule = { capacity: size[0], unit: size[1], manufacturer: ramManufacturer[ram].replace('Manufacturer: ', ''), title: title, type: ramType[ram].replace('Type: ', '') } + ramModules.push(ramModule) + } + } + // ramTmpSize = ramSize.split('\n')[0].replace('Size: ', '').split(' ') + // ramSize = ramTmpSize[0] + // ramUnit = ramTmpSize[1] + // ramManufacturer = ramManufacturer.split('\n')[0].replace('Manufacturer: ', '') + // ramType = ramType.split('\n')[0].replace('Type: ', '') + // ramFormfactor = ramFormfactor.split('\n')[0].replace('Form Factor: ', '') + // var ramTitle = ramFormfactor + // if (ramIsEcc === "Single-bit ECC") ramTitle += '-ECC' + // var ram = { capacity: ramSize, manufacturer: ramManufacturer, title: ramTitle, type: ramType, formfactor: ramFormfactor, unit: ramUnit } db.client.findOne({ where: { uuid: uuid } }).then(client => { client.update({ name: name }) - const c = { uuid: uuid, id: client.id } + var c = { uuid: uuid, id: client.id } if (name) c.title = name if (parentId) c.parentId = parentId - if (sysManufacturer && sysModel && sysSerial) c.system = { model: sysModel, manufacturer: sysManufacturer, serialnumber: sysSerial } - if (cpuModel && cpuManufacturer && cpuType && cpuFrequency && cpuCores) c.cpu = { model: cpuModel, manufacturer: cpuManufacturer, type: cpuType, frequency: cpuFrequency, cores: cpuCores } - if (ramModel && ramManufacturer && ramCapacity && ramUnit) c.ram = [{ model: ramModel, manufacturer: ramManufacturer, capacity: ramCapacity, unit: ramUnit }] + + // 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 } + c.ram = ramModules backendHelper.updateClient(c).then(result => { res.send(result) @@ -206,9 +249,11 @@ noAuthRouter.post('/update', (req, res) => { /* * Mehtod for uploading the tpm key and stuff. */ -noAuthRouter.put('/:uuid/tpm', (req, res) => { - console.log(req.files) - res.send() +noAuthRouter.put('/:uuid/files', (req, res) => { + db.client.findOne({ where: { uuid: req.params.uuid }}).then(client => { + backendHelper.uploadFiles(client.id, req.files) + res.send() + }) }) /* diff --git a/server/ipxe/grepSystemInfo.sh b/server/ipxe/grepSystemInfo.sh index 2f8e6cc..a0810be 100644 --- a/server/ipxe/grepSystemInfo.sh +++ b/server/ipxe/grepSystemInfo.sh @@ -1,5 +1,5 @@ #!/bin/bash - +# http://git.openslx.org/openslx-ng/mltk.git/tree/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-hardware_stats #dmidecode | grep -i UUID # MAC @@ -30,6 +30,7 @@ CPU_CORES=$(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | sor #CPUMODEL=$(grep -m1 '^model name\s*:' /proc/cpuinfo | sed 's/^model name\s*:\s*//;s/\s\s*/ /g;s/^ //;s/ $//') #echo "$CPUMODEL" CPU_FREQUENCY=$(dmidecode -q -s processor-frequency) +CPU_FREQUENCY=${CPU_FREQUENCY%" MHz"} # RAM # RAM=$(grep -m1 '^MemTotal:' /proc/meminfo | awk '{print $2}') @@ -42,6 +43,25 @@ CPU_FREQUENCY=$(dmidecode -q -s processor-frequency) # done # fi +# RAM_SIZE=$(dmidecode -t 17 | grep -o 'Size:.*[MG]B$') +RAM_SIZE=$(dmidecode -t 17 | grep -o 'Size:.*') +RAM_MANUFACTURER=$(dmidecode -t 17 | grep -o 'Manufacturer:.*') +#RAM_MANUFACTURER=${RAM_MANUFACTURER#"\tManufacturer: "} +RAM_TYPE=$(dmidecode -t 17 | grep -o 'Type:.*') +RAM_ISECC=$(dmidecode -t 16 | grep -o 'Error Correction Type:.*') +RAM_FORMFACTOR=$(dmidecode -t 17 | grep -o 'Form Factor:.*') +#RAM_TYPE=${RAM_TYPE#"\tType: "} + +# HDD / SSD +# hd parm or smartctl from smartmontools +drives=$(ls /dev/sd* | grep -o '/dev/sd.$') +for drive in $drives; do + # drivedata=$(sudo smartctl -i $drive) + # drivedata=$(sudo hdparm -I $drive) + # echo $drivedata | grep -o 'Device Model: .*' +done + + # Curl #curl --data "state=6" --insecure https://bas.stfu-kthx.net:8888/api/registrations/$UUID/state -curl -d "uuid=$UUID&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" -H "Content-Type: application/x-www-form-urlencoded" -X POST https://bas.intra.uni-freiburg.de/api/registrations/$UUID/update +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" -H "Content-Type: application/x-www-form-urlencoded" -X POST --insecure https://bas.intra.uni-freiburg.de/api/registrations/$UUID/update diff --git a/server/ipxe/registration.ipxe b/server/ipxe/registration.ipxe index a20beda..c7fa24c 100644 --- a/server/ipxe/registration.ipxe +++ b/server/ipxe/registration.ipxe @@ -24,10 +24,10 @@ goto start :automatic params -param name unnamed param mac ${net0/mac} param uuid ${uuid} param ip ${net0/ip} +param purpose Pool PC chain https://bas.intra.uni-freiburg.de/api/registrations/add##params :manual diff --git a/server/lib/external-backends/backendhelper.js b/server/lib/external-backends/backendhelper.js index 801fea4..dc4324c 100644 --- a/server/lib/external-backends/backendhelper.js +++ b/server/lib/external-backends/backendhelper.js @@ -82,5 +82,18 @@ module.exports = { if (objectsToDelete.length > 0) instance.deleteObjects(backend.credentials, objectsToDelete) }) }) + }, + + uploadFiles: async function (clientId, files) { + var backends = await db.backend.findAll({ include: ['mappedClients'] }) + for (var b in backends) { + var backend = backends[b] + const ba = new ExternalBackends() + const instance = ba.getInstance(backend.type) + + var exid = backend.mappedClients.find(y => y.id === parseInt(clientId)) + if (exid) exid = exid.backend_x_client.externalId + instance.uploadFiles(backend.credentials, exid, files) + } } } diff --git a/server/lib/external-backends/backends/idoit-backend.js b/server/lib/external-backends/backends/idoit-backend.js index d3ce7e6..57a5929 100644 --- a/server/lib/external-backends/backends/idoit-backend.js +++ b/server/lib/external-backends/backends/idoit-backend.js @@ -328,7 +328,6 @@ class IdoitBackend extends ExternalBackends { } } var bodies = [] - var clientid if (!client.id) { // Create the object in idoIT. @@ -338,6 +337,13 @@ class IdoitBackend extends ExternalBackends { '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) @@ -346,7 +352,7 @@ class IdoitBackend extends ExternalBackends { clientid = client.id // Update the client title - bodies.push({ + var bodyGeneral = { 'version': '2.0', 'method': 'cmdb.object.update', 'params': { @@ -356,7 +362,10 @@ class IdoitBackend extends ExternalBackends { 'language': 'en' }, 'id': 'update_title' - }) + } + if (client.purpose === 'Pool PC') bodyGeneral.params.purpose = 7 + + bodies.push(bodyGeneral) } if (client.uuid) { @@ -462,7 +471,7 @@ class IdoitBackend extends ExternalBackends { * id: , title: , parentId: , * system: { model: , manufacturer: , serialnumber: }, * cpu: { model: , manufacturer: , type: , frequency: , cores: }, - * ram: [{ model: , manufacturer: , type: , capacity: , unit: }, ...], + * ram: [{ title: , manufacturer: , type: , capacity: , unit: }, ...], * storage: {} * } */ @@ -578,12 +587,16 @@ class IdoitBackend extends ExternalBackends { 'id': 'update_cpu' }) } - + console.log(client.ram) if (client.ram) { var counter = 1 - var mem - for (mem in client.ram) { + for (var memory in client.ram) { + var mem = client.ram[memory] var id = 'create_memory_' + counter + if (mem.unit === 'MB') mem.capacity = mem.capacity / 1024 + + // 2 = MB + // 3 = GB // Update the object. bodies.push({ 'version': '2.0', @@ -592,11 +605,11 @@ class IdoitBackend extends ExternalBackends { 'objID': clientid, 'category': 'C__CATG__MEMORY', 'data': { - 'title': mem.model, + 'title': mem.title, 'manufacturer': mem.manufacturer, 'type': mem.type, 'capacity': mem.capacity, - 'unit': mem.unit + 'unit': 3 }, 'apikey': c.apikey, 'language': 'en' @@ -620,7 +633,7 @@ class IdoitBackend extends ExternalBackends { return result } - async uploadTpm (credentials, clientid, clientuuid, tpm) { + async uploadFiles (credentials, externalId, files) { var c = this.mapCredentials(credentials) var login = await this.getSession(c) var sid = login.data.result['session-id'] @@ -632,60 +645,66 @@ class IdoitBackend extends ExternalBackends { 'Content-Type': 'application/json' } } + var result = [] + for (var key in files) { + var body = { + 'version': '2.0', + 'method': 'cmdb.object.create', + 'params': { + 'type': 'C__OBJTYPE__FILE', + 'title': key, + 'apikey': c.apikey, + 'language': 'en' + }, + 'id': key + } + var fileObject = await axios.post(c.url, body, config) + result.push(fileObject) - // Create file object in idoit. - var body = { - 'version': '2.0', - 'method': 'cmdb.object.create', - 'params': { - 'type': 'C__OBJTYPE__FILE', - 'title': 'Just a test', - 'apikey': c.apikey, - 'language': 'en' - }, - 'id': 2 - } - var fileobject = await axios.post(c.url, body, config) - console.log(fileobject.data.result.id) + var buffer = new Buffer.from(files[key].data) + var filename = files[key].name - // Upload file to fileobject. - body = { - 'version': '2.0', - 'method': 'cmdb.category.create', - 'params': { - 'objID': fileobject.data.result.id, - 'data': { - 'file_content': 'dGVzdAo=', - 'file_physical': 'test.txt', - 'file_title': 'Just a test', - 'version_description': 'Just a test' + // 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' }, - 'category': 'C__CMDB__SUBCAT__FILE_VERSIONS', - 'apikey': c.apikey, - 'language': 'en' - }, - 'id': 3 - } - var fileupload = await axios.post(c.url, body, config) + 'id': key + } + 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': clientid, - 'data': { - 'file': fileobject.data.result.id + // 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' }, - 'category': 'C__CATG__FILE', - 'apikey': c.apikey, - 'language': 'en' - }, - 'id': 4 + 'id': 4 + } + var concat = await axios.post(c.url, body, config) + result.push(concat) } - var concat = await axios.post(c.url, body, config) - return { create: fileobject.data.result, upload: fileupload.data.result, concat: concat.data.result } + return { result: result } } // ############################################################################ diff --git a/server/lib/external-backends/index.js b/server/lib/external-backends/index.js index 1adb100..c782807 100644 --- a/server/lib/external-backends/index.js +++ b/server/lib/external-backends/index.js @@ -154,8 +154,8 @@ class ExternalBackends { return { success: false, status: 'NOT_IMPLEMENTED_EXCEPTION', error: 'The provided backend does not have an updateClient method' } } - async uploadTpm (credentials, clientid, clientuuid, tpm) { - return { success: false, status: 'NOT_IMPLEMENTED_EXCEPTION', error: 'The provided backend does not have an uploadTpm method' } + async uploadFiles (credentials, externalId, files) { + return { success: false, status: 'NOT_IMPLEMENTED_EXCEPTION', error: 'The provided backend does not have an uploadFiles method' } } } -- cgit v1.2.3-55-g7522