From 392e235d744c29b8852dea58b3db4aa19b1346a8 Mon Sep 17 00:00:00 2001 From: Jannik Schönartz Date: Tue, 23 Mar 2021 19:15:24 +0000 Subject: [server/registration] Add support for the new hw collection python script (not fully finished) --- server/api/registration.js | 220 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 212 insertions(+), 8 deletions(-) diff --git a/server/api/registration.js b/server/api/registration.js index fd10fba..b9d6f0b 100644 --- a/server/api/registration.js +++ b/server/api/registration.js @@ -12,6 +12,7 @@ const config = require(path.join(__appdir, 'config', 'config')) const url = config.https.host // + ':' + config.https.port const log = require(path.join(__appdir, 'lib', 'log')) const HttpResponse = require(path.join(__appdir, 'lib', 'httpresponse')) +// const pci = require(path.join(__appdir, 'lib', 'pci')) // This is needed for parsing vendor/product codes (not required for now) // Permission check middleware router.all(['', '/hooks', '/:y', '/hooks/:x'], async (req, res, next) => { @@ -324,14 +325,21 @@ noAuthRouter.postAsync('/clients', async (req, res) => { }) noAuthRouter.postAsync('/clients/:uuid', async (req, res) => { - let client = req.body.client - if (typeof client === 'string') client = JSON.parse(client) - - if (client && client.ram && client.ram.modules) { - // 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' + let client = {} + if (req.body.version && req.body.version >= 2) { + /* New hardware collection script */ + client = parseHardwareInformation(req.body) + } else { + /* OLD SCRIPT */ + client = req.body.client + if (typeof client === 'string') client = JSON.parse(client) + + if (client && client.ram && client.ram.modules) { + // 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' + } } } @@ -470,6 +478,202 @@ function getRecursiveParents (groupIds) { }) } +/* + * New mehthod for preparing the new json formatted hw information + */ +function parseHardwareInformation (data) { + let result = { + 'client': { + 'parents': [], // TODO: + 'type': '', // SERVER OR CLIENT + 'uuid': '', + 'networks': [], // { 'mac': '', 'ip': '' } + 'system': { + 'model': '', + 'manufacturer': '', + 'serialnumber': '' + }, + 'cpus': [], + 'ram': { + 'modules': [], + 'isEcc': false + }, + 'drives': [], + 'gpus': [] + } + } + + // TODO: Rack and Bay stuff + + /* DmiDecode: CPU, RAM, System Information (Serial, Model, ...) */ + if (data.dmidecode && data.dmidecode.length > 0) { + const filter = [ + /* "BIOS Information", "OEM Strings"," Base Board Information", "Chassis Information", "System Power Supply" */ + 'System Information', + 'Processor Information', + 'Memory Device', + 'Physical Memory Array' + ] + const filteredData = data.dmidecode.filter(x => filter.includes(x.name)) + for (let entry of filteredData) { + switch (entry.name) { + case 'System Information': + result.client.system.model = entry.props['Product Name'].values[0] + result.client.system.manufacturer = entry.props['Manufacturer'].values[0] + result.client.system.serialnumber = entry.props['Serial Number'].values[0] + result.client.uuid = entry.props['UUID'].values[0] + break + + case 'Processor Information': + result.client.cpus.push({ + 'model': entry.props['Version'].values[0], + 'manufacturer': entry.props['Manufacturer'].values[0], + 'type': entry.props['Family'].values[0], + 'cores': entry.props['Core Count'].values[0], + 'frequency': entry.props['Current Speed'].values[0].split(' ')[0], + 'unit': entry.props['Current Speed'].values[0].split(' ')[1] + }) + break + + case 'Memory Device': + if (entry.props['Size'].values[0] === 'No Module Installed') break + result.client.ram.modules.push({ + 'capacity': entry.props['Size'].values[0].split(' ')[0], + 'unit': entry.props['Size'].values[0].split(' ')[1], + 'manufacturer': entry.props['Manufacturer'].values[0], + 'model': entry.props['Part Number'].values[0], + 'type': entry.props['Type'].values[0], + 'formfactor': entry.props['Form Factor'].values[0], + 'speed': entry.props['Speed'].values[0], + 'serialnumber': entry.props['Serial Number'].values[0] + }) + break + + case 'Physical Memory Array': + result.client.ram.isEcc = !!entry.props['Error Correction Type'].values[0].endsWith('ECC') + break + } + } + } + + /* Smartctl */ + for (let key in data.smartctl) { + let drive = { + 'model': '', + 'family': '', // NEW + 'firmware': '', // NEW maybe save in desc? + 'serial': '', // TODO: Update this to serialnumber to unify (also need to be changed in the idoit backend then) + 'capacity': '', + 'unit': '', + 'type': '', + 'formfactor': '', + 'connection': '', // CHECK?! + 'connection_speed': '' // NEW + } + let units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] + + /* Figure out if it's HDD, SSD or CD/DVD-ROM */ + if (data.smartctl[key]['user_capacity']) { + let capacity = data.smartctl[key]['user_capacity']['bytes'] + let unitcounter = 0 + while (capacity > 1000) { + if (unitcounter + 1 <= units.length) { + capacity = capacity / 1000 + unitcounter++ + } + } + drive['capacity'] = Math.round(capacity) + drive['unit'] = units[unitcounter] + + if (data.smartctl[key]['rotation_rate']) { + if (data.smartctl[key]['rotation_rate'] > 0) { + drive['type'] = 'HDD' + } else if (data.smartctl[key]['rotation_rate'] === 0) { + drive['type'] = 'SSD' + } + } + } else { + const regexCDDVD = /\/dev\/sr[0-9]+/ + // Seems to be a CD/DVD-ROM + if (data.smartctl[key]['readlink'].match(regexCDDVD)) drive['type'] = 'CD/DVD-ROM' + else drive['type'] = 'UNKNOWN' + } + + if (data.smartctl[key]['form_factor']) drive['formfactor'] = data.smartctl[key]['form_factor'].name + if (data.smartctl[key]['sata_version']) drive['connection'] = data.smartctl[key]['sata_version'].string + if (data.smartctl[key]['interface_speed']) { + if (data.smartctl[key]['interface_speed'].current) drive['connection_speed'] = data.smartctl[key]['interface_speed'].current.string + else if (data.smartctl[key]['interface_speed'].max) drive['connection_speed'] = data.smartctl[key]['interface_speed'].max.string + } + + if (data.smartctl[key]['model_name']) drive.model = data.smartctl[key]['model_name'] + if (data.smartctl[key]['model_family']) drive.family = data.smartctl[key]['model_family'] + if (data.smartctl[key]['serial_number']) drive.serial = data.smartctl[key]['serial_number'] + if (data.smartctl[key]['firmware_version']) drive.firmware = data.smartctl[key]['firmware_version'] + + result.client.drives.push(drive) + } + + /* lspci */ + + /* ip */ + for (let ip of data.ip) { + if (ip['link_type'] === 'loopback') continue + let network = { + 'name': ip.ifname, + 'mac': ip.address, + 'ip': '', + 'ipv6': '', + 'hostname': '' + } + + for (let addr of ip['addr_info']) { + if (addr.scope !== 'global') continue + if (addr.family === 'inet') network.ip = addr.local + else if (addr.family === 'inet6') network.ipv6 = addr.local + } + + result.client.networks.push(network) + } + + /* net */ + /* Get network information as fallback for ip */ + if (result.client.networks.length <= 0) { + for (let key in data.net) { + let network = { + 'name': key, + 'mac': data.net[key]['mac'], + 'ip': data.net[key]['ipv4'], + 'ipv6': data.net[key]['ipv6'], + 'hostname': '' + } + result.client.networks.push(network) + } + } + + /* edid */ + + /* lshw */ + if (data.lshw && data.lshw.length > 0) { + /* Get display information (as fallback) */ + if (result.client.gpus && result.client.gpus.length === 0) { + const gpus = data.lshw[0].children.filter(y => y.id === 'core')[0].children.filter(z => z.id === 'pci')[0].children.filter(w => w.id === 'display') + for (let gpu of gpus) { + result.client.gpus.push({ + 'manufacturer': gpu.vendor, + 'model': gpu.product + /*, + 'memory': , + 'unit': + */ + }) + } + } + } + + return result +} + /* * id: id of the current selected location. * name: Name of the current selected location -- cgit v1.2.3-55-g7522