summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2021-10-04 14:52:55 +0200
committerSimon Rettberg2021-10-04 14:52:55 +0200
commitcc8aacc56315d590841e39a4b419e32975182294 (patch)
tree250d84aee72f75f5e831365e2611cfa21003a68f
parent[statistics] Adapt hw-data parsing to new json format for display (diff)
downloadslx-admin-cc8aacc56315d590841e39a4b419e32975182294.tar.gz
slx-admin-cc8aacc56315d590841e39a4b419e32975182294.tar.xz
slx-admin-cc8aacc56315d590841e39a4b419e32975182294.zip
[statistics] stuf
-rw-r--r--inc/arrayutil.inc.php8
-rw-r--r--modules-available/statistics/inc/hardwareparser.inc.php10
-rw-r--r--modules-available/statistics/inc/hardwareparserlegacy.inc.php186
-rw-r--r--modules-available/statistics/pages/machine.inc.php183
-rw-r--r--modules-available/statistics/templates/machine-hdds.html46
-rw-r--r--modules-available/statistics/templates/machine-main.html13
6 files changed, 290 insertions, 156 deletions
diff --git a/inc/arrayutil.inc.php b/inc/arrayutil.inc.php
index 490b5a4f..c1306ac7 100644
--- a/inc/arrayutil.inc.php
+++ b/inc/arrayutil.inc.php
@@ -12,13 +12,7 @@ class ArrayUtil
*/
public static function flattenByKey(array $list, string $key)
{
- $ret = [];
- foreach ($list as $item) {
- if (array_key_exists($key, $item)) {
- $ret[] = $item[$key];
- }
- }
- return $ret;
+ return array_column($list, $key);
}
/**
diff --git a/modules-available/statistics/inc/hardwareparser.inc.php b/modules-available/statistics/inc/hardwareparser.inc.php
index f2ebe335..0217835e 100644
--- a/modules-available/statistics/inc/hardwareparser.inc.php
+++ b/modules-available/statistics/inc/hardwareparser.inc.php
@@ -96,7 +96,7 @@ class HardwareParser
}
// Count, size (unitless)
if (is_numeric($val) && preg_match('/^-?[0-9]+$/', $val)
- && preg_match('/used|occupied|count|number|size|temperature/', $key)) {
+ && preg_match('/used|occupied|count|number|size|temperature|_start|_value|_thresh|_worst|_time/', $key)) {
return (int)$val;
}
// Date
@@ -413,8 +413,8 @@ class HardwareParser
'size' => $size,
'physical_block_size' => $smart['physical_block_size'] ?? $lsblk['phy-sec'] ?? 0,
'logical_block_size' => $smart['logical_block_size'] ?? $lsblk['log-sec'] ?? 0,
- ] + self::propsFromArray($smart,
- 'rotation_rate', 'sata_version//string', 'interface_speed//max//string'));
+ ] + self::propsFromArray($smart, 'rotation_rate', 'sata_version//string',
+ 'interface_speed//max//string', 'model_family'));
// Mangle smart attribute table
// TODO: Handle used endurance indicator for (SATA) SSDs
$table = [];
@@ -497,10 +497,12 @@ class HardwareParser
}
}
$table['unused'] = $size - $used;
+ $table['dev'] = $dev['readlink'];
$table += self::propsFromArray($smart + ($lsblk ?? []),
'serial_number', 'firmware_version',
'interface_speed//current//string',
- 'smart_status//passed', 'temperature//current', 'temperature//min', 'temperature//max');
+ 'smart_status//passed', 'temperature//current', 'temperature//min', 'temperature//max',
+ 'power_on_time//hours');
$mappingId = self::writeLocalHardwareData($uuid, $hwid, $dev['readlink'],
$table);
// Delete old partition and smart attribute entries
diff --git a/modules-available/statistics/inc/hardwareparserlegacy.inc.php b/modules-available/statistics/inc/hardwareparserlegacy.inc.php
index 1bee23f9..4d8a8502 100644
--- a/modules-available/statistics/inc/hardwareparserlegacy.inc.php
+++ b/modules-available/statistics/inc/hardwareparserlegacy.inc.php
@@ -5,66 +5,71 @@ class HardwareParserLegacy
public static function parseHdd(&$row, $data)
{
- $hdds = array();
+ $hdds = [];
// Could have more than one disk - linear scan
$lines = preg_split("/[\r\n]+/", $data);
$i = 0;
- $mbrToMbFactor = $sectorToMbFactor = 0;
+ $mbrToByteFactor = $sectorToByteFactor = 0;
foreach ($lines as $line) {
if (preg_match('/^Disk (\S+):.* (\d+) bytes/i', $line, $out)) {
// --- Beginning of MBR disk ---
unset($hdd);
if ($out[2] < 10000) // sometimes vmware reports lots of 512byte disks
continue;
- if (substr($out[1], 0, 8) === '/dev/dm-') // Ignore device mapper
+ if (preg_match('#^/dev/(dm-|x?loop|d?nbd)#', $out[1])) // Ignore device mapper etc.
continue;
// disk total size and name
- $mbrToMbFactor = 0; // This is != 0 for mbr
- $sectorToMbFactor = 0; // This is != for gpt
- $hdd = array(
+ $mbrToByteFactor = 0; // This is != 0 for mbr
+ $sectorToByteFactor = 0; // This is != for gpt
+ $hdd = [
'devid' => 'devid-' . ++$i,
'dev' => $out[1],
'sectors' => 0,
- 'size' => round($out[2] / (1024 * 1024 * 1024)),
+ 'size' => $out[2],
'used' => 0,
- 'partitions' => array(),
- 'json' => array(),
- );
+ 'partitions' => [],
+ ];
$hdds[] = &$hdd;
} elseif (preg_match('/^Disk (\S+):\s+(\d+)\s+sectors,/i', $line, $out)) {
// --- Beginning of GPT disk ---
unset($hdd);
if ($out[2] < 1000) // sometimes vmware reports lots of 512byte disks
continue;
- if (substr($out[1], 0, 8) === '/dev/dm-') // Ignore device mapper
+ if (preg_match('#^/dev/(dm-|x?loop|d?nbd)#', $out[1])) // Ignore device mapper etc.
continue;
// disk total size and name
- $mbrToMbFactor = 0; // This is != 0 for mbr
- $sectorToMbFactor = 0; // This is != for gpt
- $hdd = array(
+ $mbrToByteFactor = 0; // This is != 0 for mbr
+ $sectorToByteFactor = 0; // This is != for gpt
+ $hdd = [
'devid' => 'devid-' . ++$i,
'dev' => $out[1],
'sectors' => $out[2],
'size' => 0,
'used' => 0,
- 'partitions' => array(),
- 'json' => array(),
- );
+ 'partitions' => [],
+ ];
$hdds[] = &$hdd;
} elseif (preg_match('/^Units =.*= (\d+) bytes/i', $line, $out)) {
// --- MBR: Line that tells us how to interpret units for the partition lines ---
// Unit for start and end
- $mbrToMbFactor = $out[1] / (1024 * 1024); // Convert so that multiplying by unit yields MiB
+ $mbrToByteFactor = $out[1]; // Convert so that multiplying by unit yields MiB
} elseif (preg_match('/^Logical sector size:\s*(\d+)/i', $line, $out)) {
// --- GPT: Line that tells us the logical sector size used everywhere ---
- $sectorToMbFactor = $out[1] / (1024 * 1024);
+ $sectorToByteFactor = $out[1];
} elseif (isset($hdd) && preg_match('/^First usable sector.* is (\d+)$/i', $line, $out)) {
// --- Some fdisk versions are messed up and report 2^32 as the sector count in the first line,
// but the correct value in the "last usable sector is xxxx" line below ---
if ($out[1] > $hdd['sectors']) {
$hdd['sectors'] = $out[1];
}
- } elseif (isset($hdd) && $mbrToMbFactor !== 0 && preg_match(',^/dev/(\S+)\s+.*\s(\d+)[+\-]?\s+(\d+)[+\-]?\s+\d+[+\-]?\s+([0-9a-f]+)\s+(.*)$,i', $line, $out)) {
+ } elseif (isset($hdd) && $mbrToByteFactor !== 0 && preg_match(',
+ ^/dev/(\S+) # device
+ \s+.*\s(\d+)[+\-]? # start
+ \s+(\d+)[+\-]? # end
+ \s+\d+[+\-]? # size
+ \s+([0-9a-f]+) # typeid
+ \s+(.*)$ # type name
+ ,ix', $line, $out)) {
// --- MBR: Partition entry ---
// Some partition
$type = strtolower($out[4]);
@@ -72,81 +77,58 @@ class HardwareParserLegacy
continue;
} elseif ($type === '44') {
$out[5] = 'OpenSLX-ID44';
- $color = '#5c1';
} elseif ($type === '45') {
$out[5] = 'OpenSLX-ID45';
- $color = '#0d7';
- } elseif ($type === '82') {
- $color = '#48f';
- } else {
- $color = '#e55';
}
- $partsize = round(($out[3] - $out[2]) * $mbrToMbFactor);
- $hdd['partitions'][] = array(
+ $start = $out[2] * $mbrToByteFactor;
+ $partsize = ($out[3] - $out[2]) * $mbrToByteFactor;
+ $hdd['partitions'][] = [
'id' => $out[1],
- 'name' => $out[1],
- 'size' => round($partsize / 1024, $partsize < 1024 ? 1 : 0),
- 'type' => $out[5],
- );
- $hdd['json'][] = array(
- 'label' => $out[1],
- 'value' => $partsize,
- 'color' => $color,
- );
+ 'index' => $out[1],
+ 'start' => $start,
+ 'size' => $partsize,
+ 'name' => $out[5],
+ 'slxtype' => $type,
+ ];
$hdd['used'] += $partsize;
- } elseif (isset($hdd) && $sectorToMbFactor !== 0 && preg_match(',^\s*(\d+)\s+(\d+)[+\-]?\s+(\d+)[+\-]?\s+\S+\s+([0-9a-f]+)\s+(.*)$,i', $line, $out)) {
+ } elseif (isset($hdd) && $sectorToByteFactor !== 0 && preg_match(',
+ ^\s*(\d+) # index
+ \s+(\d+)[+\-]? # start
+ \s+(\d+)[+\-]? # end
+ \s+\S+ # human readable size
+ \s+([0-9a-f]{2})[0-9a-f]* # pseudo-type-id
+ \s+(.*)$ # PartLabel
+ ,ix', $line, $out)) {
// --- GPT: Partition entry ---
// Some partition
- $type = $out[5];
- if ($type === 'OpenSLX-ID44') {
- $color = '#5c1';
- } elseif ($type === 'OpenSLX-ID45') {
- $color = '#0d7';
- } elseif ($type === 'Linux swap') {
- $color = '#48f';
- } else {
- $color = '#e55';
+ $slxtype = $out[4];
+ if ($out[5] === 'OpenSLX-ID44') {
+ $slxtype = '44';
+ } elseif ($out[5] === 'OpenSLX-ID45') {
+ $slxtype = '45';
+ } elseif ($out[5] === 'Linux swap') {
+ $slxtype = '82';
}
$id = $hdd['devid'] . '-' . $out[1];
- $partsize = round(($out[3] - $out[2]) * $sectorToMbFactor);
- $hdd['partitions'][] = array(
+ $start = $out[2] * $sectorToByteFactor;
+ $partsize = ($out[3] - $out[2]) * $sectorToByteFactor;
+ $hdd['partitions'][] = [
'id' => $id,
- 'name' => $out[1],
- 'size' => round($partsize / 1024, $partsize < 1024 ? 1 : 0),
- 'type' => $type,
- );
- $hdd['json'][] = array(
- 'label' => $id,
- 'value' => $partsize,
- 'color' => $color,
- );
+ 'index' => $out[1],
+ 'start' => $start,
+ 'size' => $partsize,
+ 'name' => $out[5],
+ 'slxtype' => $slxtype,
+ ];
$hdd['used'] += $partsize;
}
}
unset($hdd);
- $i = 0;
foreach ($hdds as &$hdd) {
- $hdd['used'] = round($hdd['used'] / 1024);
if ($hdd['size'] === 0 && $hdd['sectors'] !== 0) {
- $hdd['size'] = round(($hdd['sectors'] * $sectorToMbFactor) / 1024);
+ $hdd['size'] = round($hdd['sectors'] * $sectorToByteFactor);
}
- $free = $hdd['size'] - $hdd['used'];
- if ($hdd['size'] > 0 && ($free > 5 || ($free / $hdd['size']) > 0.1)) {
- $hdd['partitions'][] = array(
- 'id' => 'free-id-' . $i,
- 'name' => Dictionary::translate('unused'),
- 'size' => $free,
- 'type' => '-',
- );
- $hdd['json'][] = array(
- 'label' => 'free-id-' . $i,
- 'value' => $free * 1024,
- 'color' => '#aaa',
- );
- ++$i;
- }
- $hdd['json'] = json_encode($hdd['json']);
}
unset($hdd);
$row['hdds'] = &$hdds;
@@ -213,32 +195,28 @@ class HardwareParserLegacy
}
if (preg_match('/^([A-Z][^:]+):\s*(.*)$/', $line, $out)) {
$key = preg_replace('/\s|-|_/', '', $out[1]);
- if ($key === 'ModelNumber') {
- $key = 'DeviceModel';
- }
- $dev['s_' . $key] = $out[2];
- } elseif (preg_match('/^\s*\d+\s+(\S+)\s+\S+\s+\d+\s+\d+\s+\S+\s+\S+\s+(\d+)(\s|$)/', $line, $out)) {
- $dev['s_' . preg_replace('/\s|-|_/', '', $out[1])] = $out[2];
- }
- }
- // Format strings
- foreach ($hdds as &$hdd) {
- if (isset($hdd['s_PowerOnHours'])) {
- $hdd['PowerOnTime'] = '';
- $val = (int)str_replace('.', '', $hdd['s_PowerOnHours']);
- if ($val > 8760) {
- $hdd['PowerOnTime'] .= floor($val / 8760) . 'Y, ';
- $val %= 8760;
+ if ($key === 'ModelNumber' || $key === 'DeviceModel') {
+ $dev['model'] = $out[2];
+ } elseif ($key === 'ModelFamily') {
+ $dev['model_family'] = $out[2];
+ } elseif ($key === 'SerialNumber') {
+ $dev['serial_number'] = $out[2];
}
- if ($val > 720) {
- $hdd['PowerOnTime'] .= floor($val / 720) . 'M, ';
- $val %= 720;
+ } elseif (preg_match('/
+ ^\s*(?<id>\d+)\s+\S+ # flags
+ \s+\S+\s+(?<v>\d+)
+ \s+(?<w>\d+)
+ \s+(?<t>\S+)\s+\S+ # fail
+ \s+(?<raw>\d+)(\s|$)/x', $line, $out)) {
+ $dev['attr_' . $out['id']] = [
+ 'value' => $out['v'],
+ 'worst' => $out['w'],
+ 'thresh' => $out['t'],
+ 'raw' => $out['raw'],
+ ];
+ if ($out['id'] == 194) {
+ $dev['temperature'] = $out['raw'];
}
- if ($val > 24) {
- $hdd['PowerOnTime'] .= floor($val / 24) . 'd, ';
- $val %= 24;
- }
- $hdd['PowerOnTime'] .= $val . 'h';
}
}
}
@@ -309,14 +287,12 @@ class HardwareParserLegacy
}
} elseif ($section === 'Memory Device') {
if (preg_match('/^\s*Size:\s*(.*?)\s*$/i', $line, $out)) {
- $row['extram'] = true;
if (preg_match('/(\d+)\s*(\w)i?B/i', $out[1])) {
if (HardwareParser::convertSize($out[1], 'M', false) < 35)
continue; // TODO: Parsing this line by line is painful. Check for other indicators, like Locator
$ramslot['Size'] = HardwareParser::convertSize($out[1], 'G');
}
- }
- if (preg_match('/^\s*Manufacturer:\s*(.*?)\s*$/i', $line, $out) && $out[1] !== 'Unknown') {
+ } elseif (preg_match('/^\s*Manufacturer:\s*(.*?)\s*$/i', $line, $out) && $out[1] !== 'Unknown') {
$ramslot['Manufacturer'] = HardwareParser::decodeJedec($out[1]);
} elseif (preg_match('/^\s*Form Factor:\s*(.*?)\s*$/i', $line, $out) && $out[1] !== 'Unknown') {
$ramForm = $out[1];
@@ -325,7 +301,7 @@ class HardwareParserLegacy
} elseif (preg_match('/^\s*Configured Memory Speed:\s*(.*?)\s*$/i', $line, $out) && $out[1] !== 'Unknown') {
$ramslot['Configured Clock Speed'] = $out[1];
} elseif (preg_match('/^\s*([^:]+):\s*(.*?)\s*$/i', $line, $out)
- && $out[2] !== 'Unknown' && $out[2] !== '' && $out[2] !== 'Not Specified') {
+ && $out[2] !== 'Unknown' && $out[2] !== '' && $out[2] !== 'Not Specified' && $out[2] !== 'None') {
$ramslot[$out[1]] = $out[2];
}
} elseif ($section === 'BIOS Information') {
diff --git a/modules-available/statistics/pages/machine.inc.php b/modules-available/statistics/pages/machine.inc.php
index e1133338..fdb04023 100644
--- a/modules-available/statistics/pages/machine.inc.php
+++ b/modules-available/statistics/pages/machine.inc.php
@@ -54,13 +54,31 @@ class SubPage
$client = Database::queryFirst('SELECT machineuuid, locationid, macaddr, clientip, firstseen, lastseen, logintime, lastboot, state,
mbram, live_tmpsize, live_tmpfree, live_id45size, live_id45free, live_swapsize, live_swapfree,
live_memsize, live_memfree, live_cpuload, live_cputemp,
- Length(position) AS hasroomplan, kvmstate, cpumodel, id44mb, data, hostname, currentuser, currentsession, notes
+ Length(position) AS hasroomplan, kvmstate, cpumodel, id44mb, id45mb, data, hostname, currentuser, currentsession, notes
FROM machine WHERE machineuuid = :uuid',
array('uuid' => $uuid));
if ($client === false) {
Message::addError('unknown-machine', $uuid);
return;
}
+ // Parse data
+ $hdds = array();
+ if ($client['data'][0] === '{') {
+ $json = json_decode($client['data'], true);
+ if (is_array($json)) {
+ $client += self::parseJson($uuid, $json);
+ $hdds['hdds'] = self::parseJsonHdd($uuid);
+ }
+ } else {
+ self::parseLegacy($client, $hdds);
+ }
+ unset($client['data']);
+ // Get rid of configured speed, if equal to maximum speed
+ foreach ($client['ram'] as &$ram) {
+ if (isset($ram['Configured Memory Speed']) && $ram['Configured Memory Speed'] === $ram['Speed']) {
+ unset($ram['Configured Memory Speed']);
+ }
+ }
if (Module::isAvailable('locations') && !Location::isLeaf($client['locationid'])) {
$client['hasroomplan'] = false;
}
@@ -121,6 +139,7 @@ class SubPage
}
$client['gbram'] = round(ceil($client['mbram'] / 512) / 2, 1);
$client['gbtmp'] = round($client['id44mb'] / 1024);
+ $client['gbid45'] = round($client['id45mb'] / 1024);
foreach (['tmp', 'id45', 'swap', 'mem'] as $item) {
if ($client['live_' . $item . 'size'] == 0)
continue;
@@ -135,28 +154,25 @@ class SubPage
$client['ramclass'] = StatisticsStyling::ramColorClass($client['mbram']);
$client['kvmclass'] = StatisticsStyling::kvmColorClass($client['kvmstate']);
$client['hddclass'] = StatisticsStyling::hddColorClass($client['gbtmp']);
- //
- $hdds = array();
- if ($client['data'][0] === '{') {
- $json = json_decode($client['data'], true);
- if (is_array($json)) {
- $client += self::parseJson($uuid, $json);
- }
- } else {
- self::parseLegacy($client, $hdds);
+ // Format HDD data to strings
+ foreach ($hdds['hdds'] as &$hdd) {
+ $hdd['smart_status_failed'] = !($client['smart_status//passed'] ?? 1);
+ self::mangleHdd($hdd);
}
- unset($client['data']);
// BIOS update check
- if (!empty($client['biosrevision'])) {
- $mainboard = $client['mobomanufacturer'] . '##' . $client['mobomodel'];
- $system = $client['pcmanufacturer'] . '##' . $client['pcmodel'];
- $ret = self::checkBios($mainboard, $system, $client['biosdate'], $client['biosrevision']);
+ if (!empty($client['bios']['BIOS Revision']) || !empty($client['bios']['Release Date'])) {
+ if (preg_match('#^(\d{1,2})/(\d{1,2})/(\d{4})#', $client['bios']['Release Date'], $out)) {
+ $client['bios']['Release Date'] = $out[2] . '.' . $out[1] . '.' . $out[3];
+ }
+ $mainboard = $client['mainboard']['Manufacturer'] . '##' . $client['mainboard']['Product Name'];
+ $system = $client['system']['Manufacturer'] . '##' . $client['system']['Product Name'];
+ $ret = self::checkBios($mainboard, $system, $client['bios']['Release Date'], $client['bios']['BIOS Revision']);
if ($ret === false) { // Not loaded, use AJAX
$params = [
'mainboard' => $mainboard,
'system' => $system,
- 'date' => $client['biosdate'],
- 'revision' => $client['biosrevision'],
+ 'date' => $client['bios']['Release Date'],
+ 'revision' => $client['bios']['BIOS Revision'],
];
$client['biosurl'] = '?do=statistics&action=bios&' . http_build_query($params);
} elseif (!isset($ret['status']) || $ret['status'] !== 0) {
@@ -391,7 +407,120 @@ class SubPage
return $return;
}
- private static function eventToIconName($event)
+ private static function parseJsonHdd(string $uuid): array
+ {
+ $hdds = [];
+ $ret = Database::simpleQuery("SELECT mp.`machinehwid`, mp.`prop`, mp.`value`, mp.`numeric`
+ FROM machine_x_hw_prop mp
+ INNER JOIN machine_x_hw mxhw ON (mp.machinehwid = mxhw.machinehwid AND mxhw.machineuuid = :uuid AND mxhw.disconnecttime = 0)
+ INNER JOIN statistic_hw sh ON (mxhw.hwid = sh.hwid AND sh.hwtype = :type)
+ UNION SELECT mxhw.`machinehwid`, hwp.`prop`, hwp.`value`, hwp.`numeric`
+ FROM statistic_hw_prop hwp
+ INNER JOIN machine_x_hw mxhw ON (hwp.hwid = mxhw.hwid AND mxhw.machineuuid = :uuid AND mxhw.disconnecttime = 0)
+ INNER JOIN statistic_hw sh ON (mxhw.hwid = sh.hwid AND sh.hwtype = :type)
+ ",
+ ['type' => HardwareInfo::HDD, 'uuid' => $uuid]);
+ foreach ($ret as $row) {
+ if (!isset($hdds[$row['machinehwid']])) {
+ $hdds[$row['machinehwid']] = ['partitions' => []];
+ }
+ $hdd =& $hdds[$row['machinehwid']];
+ if (preg_match('/^(attr_[0-9]+)_(.*)$/', $row['prop'], $out)) {
+ // SMART attributes
+ if (!isset($hdd[$out[1]])) {
+ $hdd[$out[1]] = [];
+ }
+ $hdd[$out[1]][$out[2]] = $row['numeric'] ?? $row['value'];
+ } elseif (preg_match('/^part_([0-9]+)_(.*)$/', $row['prop'], $out)) {
+ // Partitions
+ if (!isset($hdd['partitions'][$out[1]])) {
+ $hdd['partitions'][$out[1]] = ['id' => 'dev-' . count($hdds) . '-' . $out[1], 'index' => $out[1] + 1];
+ }
+ $hdd['partitions'][$out[1]][$out[2]] = $row['numeric'] ?? $row['value'];
+ } else {
+ $hdd[$row['prop']] = $row['numeric'] ?? $row['value'];
+ }
+ }
+ foreach ($hdds as $k => &$hdd) {
+ $hdd['devid'] = 'k' . $k;
+ $hdd['partitions'] = array_values($hdd['partitions']);
+ }
+ return array_values($hdds);
+ }
+
+ private static function mangleHdd(array &$hdd)
+ {
+ $hours = $hdd['power_on_time//hours'] ?? $hdd['attr_9']['raw'] ?? $hdd['power_on_hours']
+ ?? $hdd['power_on_time']['hours'] ?? null;
+ if ($hours !== null) {
+ $hdd['PowerOnTime'] = '';
+ $val = (int)str_replace('.', '', $hours);
+ if ($val > 8760) {
+ $hdd['PowerOnTime'] .= floor($val / 8760) . 'Y, ';
+ $val %= 8760;
+ }
+ if ($val > 720) {
+ $hdd['PowerOnTime'] .= floor($val / 720) . 'M, ';
+ $val %= 720;
+ }
+ if ($val > 24) {
+ $hdd['PowerOnTime'] .= floor($val / 24) . 'd, ';
+ $val %= 24;
+ }
+ $hdd['PowerOnTime'] .= $val . 'h';
+ }
+ // Sort by start for building pie-chart
+ $xx = array_column($hdd['partitions'], 'start');
+ array_multisort($xx, SORT_ASC, SORT_NUMERIC,
+ $hdd['partitions']);
+ $used = 0;
+ $json = [];
+ $lastEnd = 0;
+ $minDisplaySize = $hdd['size'] / 150;
+ foreach ($hdd['partitions'] as &$part) {
+ $dist = $part['start'] - $lastEnd;
+ if ($dist > $minDisplaySize) {
+ error_log('Dist: ' . Util::readableFileSize($dist));
+ $json[] = ['value' => $dist, 'color' => '#aaa'];
+ }
+ if ($part['size'] > $minDisplaySize) {
+ $json[] = ['value' => $part['size'], 'color' => self::typeToColor($part), 'label' => $part['id']];
+ }
+ $part['size_s'] = Util::readableFileSize($part['size']);
+ $used += $part['size'];
+ $lastEnd = $part['start'] + $part['size'];
+ if (!isset($part['name'])) {
+ $part['name'] = self::mbrType($part['slxtype'] ?? $part['type']);
+ }
+ }
+ $dist = $hdd['size'] - $lastEnd;
+ if ($dist > $minDisplaySize) {
+ $json[] = ['value' => $dist, 'color' => '#aaa'];
+ }
+ $hdd['json'] = json_encode($json);
+ $hdd['size_s'] = Util::readableFileSize($hdd['size']);
+ if ($hdd['size'] - $used > 1000000000) {
+ $hdd['unused_s'] = Util::readableFileSize($hdd['size'] - $used);
+ }
+ // Finally sort by index for table display
+ array_multisort(array_column($hdd['partitions'], 'index'), SORT_ASC,
+ $hdd['partitions']);
+ }
+
+ private static function typeToColor(array $part): string
+ {
+ switch ($part['slxtype'] ?? $part['type']) {
+ case 44:
+ return '#5c1';
+ case 45:
+ return '#0d7';
+ case 82:
+ return '#48f';
+ }
+ return '#e55';
+ }
+
+ private static function eventToIconName($event): string
{
switch ($event) {
case 'session-open':
@@ -484,4 +613,22 @@ class SubPage
return $retval;
}
+ private static function mbrType(string $type): string
+ {
+ switch ($type) {
+ case '44':
+ case '45':
+ return 'OpenSLX-ID' . $type;
+ case '82':
+ return 'Linux Swap';
+ case '83':
+ return 'Linux';
+ case '7':
+ return 'NTFS/Windows';
+ case 'ef':
+ return 'EFI';
+ }
+ return $type;
+ }
+
} \ No newline at end of file
diff --git a/modules-available/statistics/templates/machine-hdds.html b/modules-available/statistics/templates/machine-hdds.html
index 4d0409f9..84feccfd 100644
--- a/modules-available/statistics/templates/machine-hdds.html
+++ b/modules-available/statistics/templates/machine-hdds.html
@@ -4,24 +4,27 @@
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
- <b>{{s_ModelFamily}}</b> {{dev}}
+ <b>{{model_family}}{{^model_family}}{{model}}{{/model_family}}</b> {{dev}}
</div>
<div class="panel-body">
- {{#s_DeviceModel}}
- <div>{{lang_modelNo}}: {{s_DeviceModel}}, {{lang_serialNo}}: {{s_SerialNumber}}</div>
- {{/s_DeviceModel}}
- {{#s_ReallocatedSectorCt}}
- <div class="red">{{lang_reallocatedSectors}}: {{s_ReallocatedSectorCt}}</div>
- {{/s_ReallocatedSectorCt}}
- {{#s_CurrentPendingSector}}
- <div class="red">{{lang_pendingSectors}}: {{s_CurrentPendingSector}}</div>
- {{/s_CurrentPendingSector}}
- {{#s_PowerOnHours}}
- <div>{{lang_powerOnTime}}: {{s_PowerOnHours}}&thinsp;{{lang_hours}} ({{PowerOnTime}})</div>
- {{/s_PowerOnHours}}
- {{#s_MediaandDataIntegrityErrors}}
- <div class="red">{{lang_mediaIntegrityErrors}}: {{s_MediaandDataIntegrityErrors}}</div>
- {{/s_MediaandDataIntegrityErrors}}
+ {{#model}}
+ <div>{{lang_modelNo}}: {{model}}, {{lang_serialNo}}: {{serial_number}}</div>
+ {{/model}}
+ {{#smart_status_failed}}
+ <div class="red">{{lang_smartSelfTestFailed}}</div>
+ {{/smart_status_failed}}
+ {{#attr_5.raw}}
+ <div class="red">{{lang_reallocatedSectors}}: {{attr_5.raw}}</div>
+ {{/attr_5.raw}}
+ {{#attr_197.raw}}
+ <div class="red">{{lang_pendingSectors}}: {{attr_197.raw}}</div>
+ {{/attr_197.raw}}
+ {{#PowerOnTime}}
+ <div>{{lang_powerOnTime}}: {{PowerOnTime}}</div>
+ {{/PowerOnTime}}
+ {{#media_errors}}
+ <div class="red">{{lang_mediaIntegrityErrors}}: {{media_errors}}</div>
+ {{/media_errors}}
<div class="row">
<div class="col-sm-7">
<table class="table table-condensed table-striped table-responsive">
@@ -32,13 +35,16 @@
</tr>
{{#partitions}}
<tr id="{{id}}">
+ <td>{{index}}</td>
+ <td class="text-right text-nowrap">{{size_s}}</td>
<td>{{name}}</td>
- <td class="text-right text-nowrap">{{size}}&thinsp;GiB</td>
- <td>{{type}}</td>
</tr>
{{/partitions}}
</table>
- <div class="slx-bold">{{lang_total}}: {{size}}&thinsp;GiB</div>
+ <div class="slx-bold">{{lang_total}}: {{size_s}}</div>
+ {{#unused_s}}
+ <div class="slx-bold">{{lang_unused}}: {{unused_s}}</div>
+ {{/unused_s}}
</div>
<div class="col-sm-5">
<canvas id="{{devid}}-chart" style="width:100%;height:250px"></canvas>
@@ -46,7 +52,7 @@
document.addEventListener("DOMContentLoaded", function() {
var data = {{{json}}};
var sel = false;
- new Chart(document.getElementById('{{devid}}-chart').getContext('2d')).Pie(data, {
+ new Chart(document.getElementById('{{devid}}-chart').getContext('2d')).Pie(data, {
animation: false,
tooltipTemplate: "<%if (label){%><%=label%><%}%>",
customTooltips: function(tooltip) {
diff --git a/modules-available/statistics/templates/machine-main.html b/modules-available/statistics/templates/machine-main.html
index 29d63a73..0509a646 100644
--- a/modules-available/statistics/templates/machine-main.html
+++ b/modules-available/statistics/templates/machine-main.html
@@ -292,16 +292,25 @@
<tr>
<td colspan="2">
<table class="table-responsive slx-table text-nowrap">
+ <thead>
+ <tr class="small">
+ <td>{{lang_slot}}</td>
+ <td></td>
+ <td>{{lang_speed}}</td>
+ <td>{{lang_vendor}}</td>
+ <td>{{lang_serialNo}}</td>
+ </tr>
+ </thead>
{{#ram}}
{{#Speed}}
<tr>
<td>
{{Locator}},
{{Bank Locator}}
- {{^Bank Locator}}Set {{Set}}{{/Bank Locator}}
+ {{^Bank Locator}}{{#Set}}Set {{Set}}{{/Set}}{{/Bank Locator}}
</td>
<td class="slx-bold">{{Size}}</td>
- <td>{{#Configured Speed}}{{Configured Speed}} / {{/Configured Speed}}{{Speed}}</td>
+ <td>{{#Configured Memory Speed}}{{Configured Memory Speed}} / {{/Configured Memory Speed}}{{Speed}}</td>
<td>{{Manufacturer}}</td>
<td>{{Serial Number}}</td>
</tr>