diff options
Diffstat (limited to 'modules-available/statistics/pages/list.inc.php')
-rw-r--r-- | modules-available/statistics/pages/list.inc.php | 182 |
1 files changed, 134 insertions, 48 deletions
diff --git a/modules-available/statistics/pages/list.inc.php b/modules-available/statistics/pages/list.inc.php index e2e7ff09..f08cd71c 100644 --- a/modules-available/statistics/pages/list.inc.php +++ b/modules-available/statistics/pages/list.inc.php @@ -10,48 +10,56 @@ class SubPage public static function doRender() { - $sortColumn = Request::any('sortColumn'); - $sortDirection = Request::any('sortDirection'); - - $filters = StatisticsFilter::parseQuery(StatisticsFilter::getQuery()); + $filters = StatisticsFilter::parseQuery(); $filterSet = new StatisticsFilterSet($filters); - $filterSet->setSort($sortColumn, $sortDirection); if (!$filterSet->setAllowedLocationsFromPermission('view.list')) { Message::addError('main.no-permission'); Util::redirect('?do=main'); } - Render::openTag('div', array('class' => 'row')); - StatisticsFilter::renderFilterBox('list', $filterSet, StatisticsFilter::getQuery()); - Render::closeTag('div'); + StatisticsFilter::renderFilterBox('list', $filterSet); self::showMachineList($filterSet); } - /** - * @param \StatisticsFilterSet $filterSet - */ - private static function showMachineList($filterSet) + private static function showMachineList(StatisticsFilterSet $filterSet): void { Module::isAvailable('js_stupidtable'); - $filterSet->makeFragments($where, $join, $sort, $args); + $filterSet->makeFragments($where, $join, $args); $xtra = ''; - if ($filterSet->isNoId44Filter()) { - $xtra .= ', data'; - } if (Module::isAvailable('runmode')) { $xtra .= ', runmode.module AS rmmodule, runmode.isclient'; if (strpos($join, 'runmode') === false) { - $join .= ' LEFT JOIN runmode USING (machineuuid) '; + $join .= ' LEFT JOIN runmode ON (m.machineuuid = runmode.machineuuid) '; } } - $res = Database::simpleQuery("SELECT m.machineuuid, m.locationid, m.macaddr, m.clientip, m.lastseen, - m.logintime, m.state, m.realcores, m.mbram, m.kvmstate, m.cpumodel, m.id44mb, m.hostname, m.notes IS NOT NULL AS hasnotes, + $allRows = Database::queryAll("SELECT m.machineuuid, m.locationid, m.macaddr, m.clientip, m.lastseen, + m.logintime, m.state, m.currentuser, m.currentrunmode, m.realcores, m.mbram, m.kvmstate, m.cpumodel, m.id44mb, + m.id45mb, m.hostname, m.notes IS NOT NULL AS hasnotes, m.badsectors, Count(s.machineuuid) AS confvars $xtra FROM machine m - LEFT JOIN setting_machine s USING (machineuuid) - $join WHERE $where GROUP BY m.machineuuid $sort", $args); - $rows = array(); - $singleMachine = 'none'; + LEFT JOIN setting_machine s ON (m.machineuuid = s.machineuuid) + $join WHERE $where GROUP BY m.machineuuid", $args); + // If filter results in just one result, redirect to machine details + if (count($allRows) === 1) { + Util::redirect('?do=statistics&uuid=' . $allRows[0]['machineuuid']); + } + // Gather additional info that would be ugly to fetch via joins above + $uuids = array_column($allRows, 'machineuuid'); + $machineWithHdds = Database::queryKeyValueList("SELECT mxx.machineuuid, Count(s.hwid) AS num + FROM statistic_hw s + INNER JOIN machine_x_hw AS mxx ON (s.hwid = mxx.hwid AND s.hwtype = :type + AND mxx.disconnecttime = 0 AND mxx.machineuuid IN (:ids)) + GROUP BY mxx.machineuuid", + ['type' => HardwareInfo::HDD, 'ids' => $uuids]); + $machineNicSpeed = Database::queryKeyValueList("SELECT mxx.machineuuid, Max(mxhp.`numeric`) AS num + FROM statistic_hw s + INNER JOIN machine_x_hw AS mxx ON (s.hwid = mxx.hwid AND s.hwtype = :type + AND mxx.disconnecttime = 0 AND mxx.machineuuid IN (:ids)) + INNER JOIN machine_x_hw_prop mxhp ON (mxx.machinehwid = mxhp.machinehwid AND mxhp.prop = :prop) + GROUP BY mxx.machineuuid", + ['type' => HardwareInfo::MAINBOARD, 'prop' => 'nic-speed', 'ids' => $uuids]); + $machineWithConfigOverrides = Database::queryKeyValueList("SELECT machineuuid, Count(machineuuid) AS num + FROM setting_machine WHERE machineuuid IN (:ids) GROUP BY machineuuid", ['ids' => $uuids]); // TODO: Cannot disable checkbox for those where user has no permission, since we got multiple actions now // We should pass these lists to the output and add some JS magic // Either disable the delete/reboot/... buttons as soon as at least one "forbidden" client is selected (potentially annoying) @@ -61,37 +69,54 @@ class SubPage $shutdownAllowedLocations = User::getAllowedLocations('.rebootcontrol.action.reboot'); $wolAllowedLocations = User::getAllowedLocations('.rebootcontrol.action.wol'); $execAllowedLocations = User::getAllowedLocations('.rebootcontrol.action.exec'); + $benchmarkAllowedLocations = User::getAllowedLocations('.vmstore.benchmark'); // Only make client clickable if user is allowed to view details page $detailsAllowedLocations = User::getAllowedLocations("machine.view-details"); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - if ($singleMachine === 'none') { - $singleMachine = $row['machineuuid']; - } else { - $singleMachine = false; - } + $location = self::buildLocationLookup(); + $rows = []; + $colValCount = []; // Count unique values for several columns + foreach ($allRows as &$row) { + settype($row['locationid'], 'int'); $row['link_details'] = in_array($row['locationid'], $detailsAllowedLocations); //$row['firstseen'] = Util::prettyTime($row['firstseen']); $row['lastseen_int'] = $row['lastseen']; $row['lastseen'] = Util::prettyTime($row['lastseen']); //$row['lastboot'] = Util::prettyTime($row['lastboot']); - $row['gbram'] = round(ceil($row['mbram'] / 512) / 2, 1); // Trial and error until we got "expected" rounding.. - $row['gbtmp'] = round($row['id44mb'] / 1024); + $row['gbram'] = Dictionary::number(ceil($row['mbram'] / 512) / 2, 1); // Trial and error until we got "expected" rounding.. + $row['gbtmp'] = Dictionary::number($row['id44mb'] / 1024); + $row['gbpersist'] = Dictionary::number($row['id45mb'] / 1024); $octets = explode('.', $row['clientip']); if (count($octets) === 4) { - $row['subnet'] = "$octets[0].$octets[1].$octets[2]."; + $row['subnet'] = "$octets[0].$octets[1].$octets[2]"; $row['lastoctet'] = $octets[3]; } - $row['ramclass'] = StatisticsStyling::ramColorClass($row['mbram']); + $row['ramclass'] = StatisticsStyling::ramColorClass((int)$row['mbram']); $row['kvmclass'] = StatisticsStyling::kvmColorClass($row['kvmstate']); - $row['hddclass'] = StatisticsStyling::hddColorClass($row['gbtmp']); + $row['hddclass'] = StatisticsStyling::hddColorClass((int)$row['gbtmp']); if (empty($row['hostname'])) { $row['hostname'] = $row['clientip']; } - if (isset($row['data'])) { - if (!preg_match('/^(Disk.* bytes|Disk.*\d{5,} sectors)/m', $row['data'])) { - $row['nohdd'] = true; - } + if (isset($machineWithConfigOverrides[$row['machineuuid']])) { + $row['confvars'] = $machineWithConfigOverrides[$row['machineuuid']]; } + if (isset($machineWithHdds[$row['machineuuid']])) { + $row['hddcount'] = $machineWithHdds[$row['machineuuid']]; + } else if ($row['id44mb'] > 0) { + // This might be a machine that wasn't booted with a recent system, and hence doesn't have HWinfo in DB + // If we have ID44 space in our main table, we most likely got an HDD, so fake a count of 1 + $row['hddcount'] = 1; + } + if (!isset($machineNicSpeed[$row['machineuuid']])) { + $row['nic-speed'] = 0; + $row['nic-speed_s'] = '???'; + } else { + $row['nic-speed'] = $machineNicSpeed[$row['machineuuid']]; + $row['nic-speed_s'] = Dictionary::number($machineNicSpeed[$row['machineuuid']]); + } + if (isset($row['data']) && !$row['data']) { + $row['nohdd'] = true; + } + // Shorten CPU names a bit for prettier display in small column $row['cpumodel'] = preg_replace('/\(R\)|\(TM\)|\bintel\b|\bamd\b|\bcpu\b|dual-core|\bdual\s+core\b|\bdual\b|\bprocessor\b/i', ' ', $row['cpumodel']); if (!empty($row['rmmodule'])) { $data = RunMode::getRunMode($row['machineuuid'], RunMode::DATA_STRINGS); @@ -102,22 +127,70 @@ class SubPage if (!$row['isclient'] && $row['state'] === 'IDLE') { $row['state'] = 'OCCUPIED'; } + if (!$row['isclient']) { + unset($row['currentuser']); + } + } + if ($row['state'] === 'IDLE' || $row['state'] === 'OCCUPIED') { + if ((!empty($row['currentrunmode']) || !empty($row['rmmodule'])) + && $row['currentrunmode'] !== $row['rmmodule']) { + $row['wrongRunMode'] = true; + if (!empty($row['currentrunmode'])) { + $wrongModule = Module::get($row['currentrunmode']); + $row['currentrunmode'] = $wrongModule === false ? $row['currentrunmode'] : $wrongModule->getDisplayName(); + } + } } $row['state_' . $row['state']] = true; - $row['locationname'] = Location::getName($row['locationid']); - $rows[] = $row; + if ($row['locationid'] > 0) { + $row['location'] = $location[$row['locationid']]; + } + foreach (['locationid', 'cpumodel', 'nic-speed_s', 'gbram', 'gbtmp'] as $key) { + if (!isset($colValCount[$key][$row[$key]])) { + $colValCount[$key][$row[$key]] = []; + } + $colValCount[$key][$row[$key]][] = $row['machineuuid']; + } + $rows[] =& $row; } - if ($singleMachine !== false && $singleMachine !== 'none') { - Util::redirect('?do=statistics&uuid=' . $singleMachine); + // Now if all machines are from the same location, try to load the roomplan + // Also, collect all properties that are the same across all machines for display in the sidebar + $roomsvg = null; + $side = []; + if (!empty($rows) && !empty($colValCount)) { + if (count($colValCount['locationid']) === 1 + && ($lid = array_key_first($colValCount['locationid'])) > 0 + && Module::isAvailable('roomplanner')) { + $roomsvg = PvsGenerator::generateSvg($lid, false, 0, 1, true, $colValCount['locationid'][$lid]); + } + // Handle our selected attributes + foreach (['locationid', 'cpumodel', 'nic-speed_s', 'gbram', 'gbtmp'] as $key) { + if (count($colValCount[$key]) === 1) { + $val = array_key_first($colValCount[$key]); + // Suffixes are not localized, but hopefully generic enough for now + switch ($key) { + case 'locationid': + if (!isset($location[$val])) + continue 2; + $val = $location[$val]['name']; + break; + case 'gbram': + $val .= ' GiB RAM'; + break; + case 'gbtmp': + $val .= ' GiB ID-44'; + break; + case 'nic-speed_s': + $val .= ' MBit/s'; + break; + } + $side[] = $val; + } + } } $data = array( 'rowCount' => count($rows), 'rows' => $rows, - 'query' => StatisticsFilter::getQuery(), - 'delimiter' => StatisticsFilter::DELIMITER, - 'sortDirection' => $filterSet->getSortDirection(), - 'sortColumn' => $filterSet->getSortColumn(), - 'columns' => json_encode(StatisticsFilter::$columns), 'showList' => 1, 'show' => 'list', 'redirect' => $_SERVER['QUERY_STRING'], @@ -127,8 +200,21 @@ class SubPage 'canDelete' => !empty($deleteAllowedLocations), 'canWol' => !empty($wolAllowedLocations), 'canExec' => !empty($execAllowedLocations), + 'canBenchmark' => !empty($benchmarkAllowedLocations), + 'roomsvg' => $roomsvg, + 'sidebar' => $side, ); Render::addTemplate('clientlist', $data); } -} + private static function buildLocationLookup(): array + { + $ret = []; + $i = 0; + foreach (Location::getLocationsAssoc() as $lid => $data) { + $ret[$lid] = ['sort' => ++$i, 'name' => $data['locationname']]; + } + return $ret; + } + +}
\ No newline at end of file |