<?php
class SubPage
{
public static function doPreprocess()
{
User::assertPermission('view.list');
}
public static function doRender()
{
$filters = StatisticsFilter::parseQuery();
$filterSet = new StatisticsFilterSet($filters);
if (!$filterSet->setAllowedLocationsFromPermission('view.list')) {
Message::addError('main.no-permission');
Util::redirect('?do=main');
}
StatisticsFilter::renderFilterBox('list', $filterSet);
self::showMachineList($filterSet);
}
/**
* @param \StatisticsFilterSet $filterSet
*/
private static function showMachineList($filterSet)
{
Module::isAvailable('js_stupidtable');
$filterSet->makeFragments($where, $join, $args);
$xtra = '';
if (Module::isAvailable('runmode')) {
$xtra .= ', runmode.module AS rmmodule, runmode.isclient';
if (strpos($join, 'runmode') === false) {
$join .= ' LEFT JOIN runmode ON (m.machineuuid = runmode.machineuuid) ';
}
}
$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.hostname, m.notes IS NOT NULL AS hasnotes,
m.badsectors, Count(s.machineuuid) AS confvars $xtra FROM machine m
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]);
$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)
// or add a notice to the confirmation dialog of the according action (nicer but a little more work)
$deleteAllowedLocations = User::getAllowedLocations("machine.delete");
$rebootAllowedLocations = User::getAllowedLocations('.rebootcontrol.action.reboot');
$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");
$location = self::buildLocationLookup();
$rows = [];
foreach ($allRows as &$row) {
$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);
$octets = explode('.', $row['clientip']);
if (count($octets) === 4) {
$row['subnet'] = "$octets[0].$octets[1].$octets[2]";
$row['lastoctet'] = $octets[3];
}
$row['ramclass'] = StatisticsStyling::ramColorClass($row['mbram']);
$row['kvmclass'] = StatisticsStyling::kvmColorClass($row['kvmstate']);
$row['hddclass'] = StatisticsStyling::hddColorClass($row['gbtmp']);
if (empty($row['hostname'])) {
$row['hostname'] = $row['clientip'];
}
if (isset($machineWithConfigOverrides[$row['machineuuid']])) {
$row['confvars'] = $machineWithConfigOverrides[$row['machineuuid']];
}
if (isset($machineWithHdds[$row['machineuuid']])) {
$row['hddcount'] = $machineWithHdds[$row['machineuuid']];
}
if (isset($row['data']) && !$row['data']) {
$row['nohdd'] = true;
}
$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);
if ($data !== false) {
$row['moduleName'] = $data['moduleName'];
$row['modeName'] = $data['modeName'];
}
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;
if ($row['locationid'] > 0) {
$row['location'] = $location[$row['locationid']];
}
$rows[] =& $row;
}
$data = array(
'rowCount' => count($rows),
'rows' => $rows,
'showList' => 1,
'show' => 'list',
'redirect' => $_SERVER['QUERY_STRING'],
'rebootcontrol' => (Module::get('rebootcontrol') !== false),
'canReboot' => !empty($rebootAllowedLocations),
'canShutdown' => !empty($shutdownAllowedLocations),
'canDelete' => !empty($deleteAllowedLocations),
'canWol' => !empty($wolAllowedLocations),
'canExec' => !empty($execAllowedLocations),
'canBenchmark' => !empty($benchmarkAllowedLocations),
);
Render::addTemplate('clientlist', $data);
}
private static function buildLocationLookup()
{
$ret = [];
$i = 0;
foreach (Location::getLocationsAssoc() as $lid => $data) {
$ret[$lid] = ['sort' => ++$i, 'name' => $data['locationname']];
}
return $ret;
}
}