summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2021-09-08 15:44:26 +0200
committerSimon Rettberg2021-09-08 15:44:26 +0200
commit1ce202d1686588f37d46f99a597138398a826d7a (patch)
tree92b5f58e5d866160b5a1517426b77ed9724f0700
parent[statistics] Local hardware update on duplicate key (diff)
downloadslx-admin-1ce202d1686588f37d46f99a597138398a826d7a.tar.gz
slx-admin-1ce202d1686588f37d46f99a597138398a826d7a.tar.xz
slx-admin-1ce202d1686588f37d46f99a597138398a826d7a.zip
[statistics] Computer
-rw-r--r--modules-available/statistics/api.inc.php2
-rw-r--r--modules-available/statistics/inc/hardwareinfo.inc.php95
2 files changed, 68 insertions, 29 deletions
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index b7f3541c..7cb8a312 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -3,7 +3,7 @@
if (Request::any('action') === 'test' && isLocalExecution()) {
HardwareInfo::parseMachine('0A5D9E23-80F4-9C43-912C-96D80AE7E80B',
file_get_contents('/tmp/bla.json'));
- error_log('Kweries: ' . Database::getQueryCount());
+ echo 'Kweries: ' . Database::getQueryCount();
exit;
}
diff --git a/modules-available/statistics/inc/hardwareinfo.inc.php b/modules-available/statistics/inc/hardwareinfo.inc.php
index ff780b62..1259391f 100644
--- a/modules-available/statistics/inc/hardwareinfo.inc.php
+++ b/modules-available/statistics/inc/hardwareinfo.inc.php
@@ -11,6 +11,7 @@ class HardwareInfo
const SYSTEM_SLOT = 'SYSTEM_SLOT';
const PCI_DEVICE = 'PCI_DEVICE';
const HDD = 'HDD';
+ const CPU = 'CPU';
public static function parseMachine(string $uuid, string $data)
@@ -22,18 +23,35 @@ class HardwareInfo
return;
}
// determine misc stuff first
- $mainboardExtra = [];
+ $globalMainboardExtra = [];
+ $localMainboardExtra = [];
// physical memory array
$memArrays = self::getDmiHandles($data, 16);
- $mainboardExtra['Memory Slot Count'] = 0;
- $mainboardExtra['Memory Maximum Capacity'] = 0;
+ $globalMainboardExtra['Memory Slot Count'] = 0;
+ $globalMainboardExtra['Memory Maximum Capacity'] = 0;
foreach ($memArrays as $mem) {
$mem = self::prepareDmiProperties($mem);
if (isset($mem['Number Of Devices']) && ($mem['Use'] ?? 0) === 'System Memory') {
- $mainboardExtra['Memory Slot Count'] += $mem['Number Of Devices'];
+ $globalMainboardExtra['Memory Slot Count'] += $mem['Number Of Devices'];
}
if (isset($mem['Maximum Capacity'])) {
- $mainboardExtra['Memory Maximum Capacity'] += Parser::convertSize($mem['Maximum Capacity'], 'M', false);
+ $globalMainboardExtra['Memory Maximum Capacity'] += Parser::convertSize($mem['Maximum Capacity'], 'M', false);
+ }
+ }
+ // BIOS section - need to cross-match this with mainboard or system model, as it doesn't have a meaningful
+ // identifier on its own
+ $bios = self::prepareDmiProperties(self::getDmiHandles($data, 0)[0]);
+ foreach (['Version', 'Release Date', 'Firmware Revision'] as $k) {
+ if (isset($bios[$k])) {
+ $localMainboardExtra['BIOS ' . $k] = $bios[$k];
+ }
+ }
+ if (isset($bios['BIOS Revision'])) {
+ $localMainboardExtra['BIOS Revision'] = $bios['BIOS Revision'];
+ }
+ foreach (['Vendor', 'ROM Size'] as $k) {
+ if (isset($bios[$k])) {
+ $globalMainboardExtra['BIOS ' . $k] = $bios[$k];
}
}
// Using the general helper function
@@ -46,12 +64,12 @@ class HardwareInfo
['Locator', 'Bank Locator', 'Serial Number', 'Asset Tag', 'Configured Memory Speed', 'Configured Voltage']
);
// Fake RAM slots used/total into this
- $mainboardExtra['Memory Slot Occupied'] = $ramModCount;
+ $localMainboardExtra['Memory Slot Occupied'] = $ramModCount;
self::updateHwTypeFromDmi($uuid, $data, 2, self::MAINBOARD, ['Manufacturer', 'Product Name'],
[],
['Manufacturer', 'Product Name', 'Type', 'Version'],
['Serial Number', 'Asset Tag', 'Location In Chassis'],
- $mainboardExtra
+ $globalMainboardExtra, $localMainboardExtra
);
self::updateHwTypeFromDmi($uuid, $data, 1, self::DMI_SYSTEM, ['Manufacturer', 'Product Name'],
[],
@@ -59,10 +77,14 @@ class HardwareInfo
['Serial Number', 'UUID', 'SKU Number']
);
self::updateHwTypeFromDmi($uuid, $data, 39, self::POWER_SUPPLY, ['Manufacturer'],
- ['Location', 'Power Unit Group', 'Name'], // Location might ne empty/"Unknown", but Name can be something like "PSU 2"
+ ['Location', 'Power Unit Group', 'Name'], // Location might be empty/"Unknown", but Name can be something like "PSU 2"
['Manufacturer', 'Product Name', 'Model Part Number', 'Revision', 'Max Power Capacity'],
['Serial Number', 'Asset Tag', 'Status', 'Plugged', 'Hot Replaceable']
);
+ self::updateHwTypeFromDmi($uuid, $data, 4, self::CPU, ['Version'],
+ ['Socket Designation'],
+ ['Type', 'Family', 'Manufacturer', 'Signature', 'Version', 'Core Count', 'Thread Count'],
+ ['Voltage', 'Current Speed', 'Upgrade', 'Core Enabled']);
self::updateHwTypeFromDmi($uuid, $data, 9, self::SYSTEM_SLOT, function(array &$entry): bool {
if (!isset($entry['Type']))
return false;
@@ -93,7 +115,7 @@ class HardwareInfo
$pciHwIds[] = $mappingId;
}
self::markDisconnected($uuid, self::PCI_DEVICE, $pciHwIds);
- // ---- Disks ------------------------------------
+ // ---- Disks ------------------------------------0Y3R3K
$hddHwIds = [];
foreach (($data['drives'] ?? []) as $dev) {
if (empty($dev['readlink']))
@@ -205,7 +227,7 @@ class HardwareInfo
private static function updateHwTypeFromDmi(string $uuid, array $data, int $type, string $dbType,
$requiredPropsOrCallback, array $pathFields, array $globalProps, array $localProps,
- array $globalExtra = []): int
+ array $globalExtra = [], array $localExtra = []): int
{
$sections = self::getDmiHandles($data, $type);
$thisMachineHwIds = [];
@@ -221,10 +243,13 @@ class HardwareInfo
if (!$requiredPropsOrCallback($flat))
continue;
}
- $hwid = self::writeGlobalHardwareData($dbType, self::propsFromArray($flat, ...$globalProps) + $globalExtra);
+ // Global
+ $props = self::propsFromArray($flat, ...$globalProps);
+ $hwid = self::writeGlobalHardwareData($dbType, $props + $globalExtra);
+ // Local
$pathId = md5(self::idFromArray($flat, ...$pathFields));
$props = self::propsFromArray($flat, ...$localProps);
- $mappingId = self::writeLocalHardwareData($uuid, $hwid, $pathId, $props);
+ $mappingId = self::writeLocalHardwareData($uuid, $hwid, $pathId, $props + $localExtra);
$thisMachineHwIds[] = $mappingId;
}
// Any hw <-> client mappings not in that list get marked as disconnected
@@ -242,11 +267,27 @@ class HardwareInfo
if (!isset($cache[$id])) {
// Cache lookup, make sure we insert this only once for every run, as this is supposed to be general
// information about the hardware, e.g. model number, max. resultion, capacity, ...
- $cache[$id] = self::updateHwEntity($dbType, $id, $global);
+ $hwid = Database::insertIgnore('statistic_hw', 'hwid', ['hwtype' => $dbType, 'hwname' => $id]);
+ $vals = [];
+ foreach ($global as $k => $v) {
+ $vals[] = [$hwid, $k, $v];
+ }
+ if (!empty($vals)) {
+ Database::exec("INSERT IGNORE INTO statistic_hw_prop (hwid, prop, `value`) VALUES :vals",
+ ['vals' => $vals]);
+ }
+ $cache[$id] = $hwid;
}
return $cache[$id];
}
+ /**
+ * Mark all devices of a given type disconnected from the given machine, with an optional
+ * exclude list of machine-client-mapping IDs
+ * @param string $uuid client
+ * @param string $dbType type, eg HDD
+ * @param array $excludedHwIds mappingIDs to exclude, ie. devices that are still connected
+ */
private static function markDisconnected(string $uuid, string $dbType, array $excludedHwIds)
{
error_log("Marking disconnected for $dbType from " . implode(', ', $excludedHwIds));
@@ -315,20 +356,6 @@ class HardwareInfo
return $out;
}
- private static function updateHwEntity(string $hwType, string $uniqueName, array $props): int
- {
- $hwid = Database::insertIgnore('statistic_hw', 'hwid', ['hwtype' => $hwType, 'hwname' => $uniqueName]);
- $vals = [];
- foreach ($props as $k => $v) {
- $vals[] = [$hwid, $k, $v];
- }
- if (!empty($vals)) {
- Database::exec("INSERT IGNORE INTO statistic_hw_prop (hwid, prop, `value`) VALUES :vals",
- ['vals' => $vals]);
- }
- return $hwid;
- }
-
/**
* Takes hwinfo json, then looks up and returns all sections from the
* dmidecode subtree that represent the given dmi table entry type,
@@ -368,7 +395,7 @@ class HardwareInfo
if ($val === '' || $val === 'notspecified' || $val === 'tobefilledbyoem' || $val === 'unknown'
|| $val === 'chassismanufacture' || $val === 'chassismanufacturer' || $val === 'chassisversion'
|| $val === 'chassisserialnumber' || $val === 'defaultstring' || $val === 'productname'
- || $val === 'manufacturer' || $val === 'systemmodel') {
+ || $val === 'manufacturer' || $val === 'systemmodel' || $val === 'fillbyoem') {
continue;
}
$val = trim($vals['values'][0] ?? '');
@@ -382,6 +409,9 @@ class HardwareInfo
return $ret;
}
+ /**
+ * Unify different variants of manufacturer names
+ */
private static function fixManufacturer(string $in): string
{
$in = Parser::decodeJedec($in);
@@ -418,6 +448,15 @@ class HardwareInfo
return $in;
}
+ /**
+ * Establish a mapping between a client and some hardware device.
+ * Optionally writes hardware properties specific to a hardware instance of a client
+ * @param string $uuid client
+ * @param int $hwid hw global hw id
+ * @param string $pathId unique identifier for the local instance of this hw, e.q. PCI slot, /dev path, something that handles the case that there are multiple instances of the same hardware in one machine
+ * @param array $props KV-pairs of properties to write for this instance; can be empty
+ * @return int
+ */
private static function writeLocalHardwareData(string $uuid, int $hwid, string $pathId, array $props): int
{
// Add mapping between hw entity and machine