diff options
Diffstat (limited to 'modules-available/statistics/inc')
-rw-r--r-- | modules-available/statistics/inc/parser.inc.php | 4 | ||||
-rw-r--r-- | modules-available/statistics/inc/statisticsfilter.inc.php (renamed from modules-available/statistics/inc/filter.inc.php) | 267 | ||||
-rw-r--r-- | modules-available/statistics/inc/statisticsfilterset.inc.php (renamed from modules-available/statistics/inc/filterset.inc.php) | 16 | ||||
-rw-r--r-- | modules-available/statistics/inc/statisticsstyling.inc.php | 42 |
4 files changed, 291 insertions, 38 deletions
diff --git a/modules-available/statistics/inc/parser.inc.php b/modules-available/statistics/inc/parser.inc.php index fe850109..764d18c1 100644 --- a/modules-available/statistics/inc/parser.inc.php +++ b/modules-available/statistics/inc/parser.inc.php @@ -74,6 +74,8 @@ class Parser { 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 (self::convertSize($out[1], 'M', false) < 35) + continue; // TODO: Parsing this line by line is painful. Check for other indicators, like Locator $ramslot['size'] = self::convertSize($out[1], 'G'); } elseif (!isset($row['ramslot']) || (count($row['ramslot']) < 8 && (!isset($row['ramslotcount']) || $row['ramslotcount'] <= 8))) { $ramslot['size'] = '_____'; @@ -126,7 +128,7 @@ class Parser { { if (!preg_match('/(\d+)\s*([TGMK]?)/i', $string, $out)) return false; - $val = (int)$out[1] * self::LOOKUP[$out[2]]; + $val = (int)$out[1] * self::LOOKUP[strtoupper($out[2])]; if (!array_key_exists($scale, self::LOOKUP)) { foreach (self::LOOKUP as $k => $v) { if ($k === '' || $val / 8 >= $v || abs($val - $v) < 50) { diff --git a/modules-available/statistics/inc/filter.inc.php b/modules-available/statistics/inc/statisticsfilter.inc.php index 46de467b..1556a1e0 100644 --- a/modules-available/statistics/inc/filter.inc.php +++ b/modules-available/statistics/inc/statisticsfilter.inc.php @@ -3,19 +3,43 @@ /* base class with rudimentary SQL generation abilities. * WARNING: argument is escaped, but $column and $operator are passed unfiltered into SQL */ -class Filter +class StatisticsFilter { /** * Delimiter for js_selectize filters */ const DELIMITER = '~,~'; + const SIZE_ID44 = array(0, 8, 16, 24, 30, 40, 50, 60, 80, 100, 120, 150, 180, 250, 300, 400, 500, 1000, 2000, 4000); + const SIZE_RAM = array(1, 2, 3, 4, 6, 8, 10, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 320, 480, 512, 768, 1024); + public $column; public $operator; public $argument; private static $keyCounter = 0; + public static function findBestValue($array, $value, $up) + { + $best = 0; + for ($i = 0; $i < count($array); ++$i) { + if (abs($array[$i] - $value) < abs($array[$best] - $value)) { + $best = $i; + } + } + if (!$up && $best === 0) { + return $array[0]; + } + if ($up && $best + 1 === count($array)) { + return $array[$best]; + } + if ($up) { + return ($array[$best] + $array[$best + 1]) / 2; + } + + return ($array[$best] + $array[$best - 1]) / 2; + } + public static function getNewKey($colname) { return $colname . '_' . (self::$keyCounter++); @@ -31,11 +55,11 @@ class Filter /* returns a where clause and adds needed operators to the passed array */ public function whereClause(&$args, &$joins) { - $key = Filter::getNewKey($this->column); + $key = StatisticsFilter::getNewKey($this->column); $addendum = ''; /* check if we have to do some parsing*/ - if (Page_Statistics::$columns[$this->column]['type'] === 'date') { + if (self::$columns[$this->column]['type'] === 'date') { $args[$key] = strtotime($this->argument); } else { $args[$key] = $this->argument; @@ -68,12 +92,12 @@ class Filter continue; // Special case: User pasted UUID, turn into filter if (preg_match('/^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/', $q)) { - $filters[] = new Filter('machineuuid', '=', $q); + $filters[] = new StatisticsFilter('machineuuid', '=', $q); continue; } // Special case: User pasted IP, turn into filter if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $q)) { - $filters[] = new Filter('clientip', '=', $q); + $filters[] = new StatisticsFilter('clientip', '=', $q); continue; } /* find position of first operator */ @@ -95,20 +119,20 @@ class Filter $rhs = trim(substr($q, $pos + strlen($operator))); if ($lhs === 'gbram') { - $filters[] = new RamGbFilter($operator, $rhs); + $filters[] = new RamGbStatisticsFilter($operator, $rhs); } elseif ($lhs === 'runtime') { - $filters[] = new RuntimeFilter($operator, $rhs); + $filters[] = new RuntimeStatisticsFilter($operator, $rhs); } elseif ($lhs === 'state') { - $filters[] = new StateFilter($operator, $rhs); + $filters[] = new StateStatisticsFilter($operator, $rhs); } elseif ($lhs === 'hddgb') { - $filters[] = new Id44Filter($operator, $rhs); + $filters[] = new Id44StatisticsFilter($operator, $rhs); } elseif ($lhs === 'location') { - $filters[] = new LocationFilter($operator, $rhs); + $filters[] = new LocationStatisticsFilter($operator, $rhs); } elseif ($lhs === 'subnet') { - $filters[] = new SubnetFilter($operator, $rhs); + $filters[] = new SubnetStatisticsFilter($operator, $rhs); } else { - if (array_key_exists($lhs, Page_Statistics::$columns) && Page_Statistics::$columns[$lhs]['column']) { - $filters[] = new Filter($lhs, $operator, $rhs); + if (array_key_exists($lhs, self::$columns) && self::$columns[$lhs]['column']) { + $filters[] = new StatisticsFilter($lhs, $operator, $rhs); } else { Message::addError('invalid-filter-key', $lhs); } @@ -117,9 +141,194 @@ class Filter return $filters; } + + /** + * @param \StatisticsFilterSet $filterSet + */ + public static function renderFilterBox($show, $filterSet, $query) + { + $data = array( + 'show' => $show, + 'query' => $query, + 'delimiter' => StatisticsFilter::DELIMITER, + 'sortDirection' => $filterSet->getSortDirection(), + 'sortColumn' => $filterSet->getSortColumn(), + 'columns' => json_encode(StatisticsFilter::$columns), + ); + + if ($show === 'list') { + $data['listButtonClass'] = 'active'; + $data['statButtonClass'] = ''; + } else { + $data['listButtonClass'] = ''; + $data['statButtonClass'] = 'active'; + } + + + $locsFlat = array(); + if (Module::isAvailable('locations')) { + $allowed = $filterSet->getAllowedLocations(); + foreach (Location::getLocations() as $loc) { + $locsFlat['L' . $loc['locationid']] = array( + 'pad' => $loc['locationpad'], + 'name' => $loc['locationname'], + 'disabled' => $allowed !== false && !in_array($loc['locationid'], $allowed), + ); + } + } + + Permission::addGlobalTags($data['perms'], null, ['view.summary', 'view.list']); + $data['locations'] = json_encode($locsFlat); + Render::addTemplate('filterbox', $data); + } + + private static $query = false; + + public static function getQuery() + { + if (self::$query === false) { + self::$query = Request::any('filters', false, 'string'); + if (self::$query === false) { + self::$query = 'lastseen > ' . gmdate('Y-m-d', strtotime('-30 day')); + } + } + return self::$query; + } + + /* + * Simple filters that map directly to DB columns + */ + + const OP_ORDINAL = ['!=', '<=', '>=', '=', '<', '>']; + const OP_STRCMP = ['!~', '~', '=', '!=']; + const OP_NOMINAL = ['!=', '=']; + public static $columns; + + /** + * Do this here instead of const since we need to check for available modules while building array. + */ + public static function initConstants() + { + + self::$columns = [ + 'machineuuid' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'string', + 'column' => true, + ], + 'macaddr' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'string', + 'column' => true, + ], + 'firstseen' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'date', + 'column' => true, + ], + 'lastseen' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'date', + 'column' => true, + ], + 'logintime' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'date', + 'column' => true, + ], + 'realcores' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'column' => true, + ], + 'systemmodel' => [ + 'op' => self::OP_STRCMP, + 'type' => 'string', + 'column' => true, + ], + 'cpumodel' => [ + 'op' => self::OP_STRCMP, + 'type' => 'string', + 'column' => true, + ], + 'hddgb' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'column' => false, + 'map_sort' => 'id44mb' + ], + 'gbram' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'map_sort' => 'mbram', + 'column' => false, + ], + 'kvmstate' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'enum', + 'column' => true, + 'values' => ['ENABLED', 'DISABLED', 'UNSUPPORTED'] + ], + 'badsectors' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'column' => true + ], + 'clientip' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'string', + 'column' => true + ], + 'hostname' => [ + 'op' => self::OP_STRCMP, + 'type' => 'string', + 'column' => true + ], + 'subnet' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'string', + 'column' => false + ], + 'currentuser' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'string', + 'column' => true + ], + 'state' => [ + 'op' => self::OP_NOMINAL, + 'type' => 'enum', + 'column' => true, + 'values' => ['occupied', 'on', 'off', 'idle', 'standby'] + ], + 'live_swapfree' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'column' => true + ], + 'live_memfree' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'column' => true + ], + 'live_tmpfree' => [ + 'op' => self::OP_ORDINAL, + 'type' => 'int', + 'column' => true + ], + ]; + if (Module::isAvailable('locations')) { + self::$columns['location'] = [ + 'op' => self::OP_STRCMP, + 'type' => 'enum', + 'column' => false, + 'values' => array_keys(Location::getLocationsAssoc()), + ]; + } + } + } -class RamGbFilter extends Filter +class RamGbStatisticsFilter extends StatisticsFilter { public function __construct($operator, $argument) { @@ -128,9 +337,8 @@ class RamGbFilter extends Filter public function whereClause(&$args, &$joins) { - global $SIZE_RAM; - $lower = floor(Page_Statistics::findBestValue($SIZE_RAM, (int)$this->argument, false) * 1024 - 100); - $upper = ceil(Page_Statistics::findBestValue($SIZE_RAM, (int)$this->argument, true) * 1024 + 100); + $lower = floor(StatisticsFilter::findBestValue(StatisticsFilter::SIZE_RAM, (int)$this->argument, false) * 1024 - 100); + $upper = ceil(StatisticsFilter::findBestValue(StatisticsFilter::SIZE_RAM, (int)$this->argument, true) * 1024 + 100); if ($this->operator == '=') { return " mbram BETWEEN $lower AND $upper"; } elseif ($this->operator == '<') { @@ -151,7 +359,7 @@ class RamGbFilter extends Filter } } -class RuntimeFilter extends Filter +class RuntimeStatisticsFilter extends StatisticsFilter { public function __construct($operator, $argument) { @@ -160,7 +368,6 @@ class RuntimeFilter extends Filter public function whereClause(&$args, &$joins) { - global $SIZE_RAM; $upper = time() - (int)$this->argument * 3600; $lower = $upper - 3600; $common = "state IN ('OCCUPIED', 'IDLE', 'STANDBY') AND"; @@ -183,7 +390,7 @@ class RuntimeFilter extends Filter } } -class Id44Filter extends Filter +class Id44StatisticsFilter extends StatisticsFilter { public function __construct($operator, $argument) { @@ -192,10 +399,9 @@ class Id44Filter extends Filter public function whereClause(&$args, &$joins) { - global $SIZE_ID44; if ($this->operator === '=' || $this->operator === '!=') { - $lower = floor(Page_Statistics::findBestValue($SIZE_ID44, $this->argument, false) * 1024 - 100); - $upper = ceil(Page_Statistics::findBestValue($SIZE_ID44, $this->argument, true) * 1024 + 100); + $lower = floor(StatisticsFilter::findBestValue(StatisticsFilter::SIZE_ID44, $this->argument, false) * 1024 - 100); + $upper = ceil(StatisticsFilter::findBestValue(StatisticsFilter::SIZE_ID44, $this->argument, true) * 1024 + 100); } else { $lower = $upper = round($this->argument * 1024); } @@ -220,7 +426,7 @@ class Id44Filter extends Filter } } -class StateFilter extends Filter +class StateStatisticsFilter extends StatisticsFilter { public function __construct($operator, $argument) { @@ -232,7 +438,7 @@ class StateFilter extends Filter $map = [ 'on' => ['IDLE', 'OCCUPIED'], 'off' => ['OFFLINE'], 'idle' => ['IDLE'], 'occupied' => ['OCCUPIED'], 'standby' => ['STANDBY'] ]; $neg = $this->operator == '!=' ? 'NOT ' : ''; if (array_key_exists($this->argument, $map)) { - $key = Filter::getNewKey($this->column); + $key = StatisticsFilter::getNewKey($this->column); $args[$key] = $map[$this->argument]; return " machine.state $neg IN ( :$key ) "; } else { @@ -242,7 +448,7 @@ class StateFilter extends Filter } } -class LocationFilter extends Filter +class LocationStatisticsFilter extends StatisticsFilter { public function __construct($operator, $argument) { @@ -264,7 +470,7 @@ class LocationFilter extends Filter if ($this->argument === 0) { return "machine.locationid IS $neg NULL"; } else { - $key = Filter::getNewKey($this->column); + $key = StatisticsFilter::getNewKey($this->column); if ($recursive) { $args[$key] = array_keys(Location::getRecursiveFlat($this->argument)); } else { @@ -275,7 +481,7 @@ class LocationFilter extends Filter } } -class SubnetFilter extends Filter +class SubnetStatisticsFilter extends StatisticsFilter { public function __construct($operator, $argument) { @@ -289,7 +495,7 @@ class SubnetFilter extends Filter } } -class IsClientFilter extends Filter +class IsClientStatisticsFilter extends StatisticsFilter { public function __construct($argument) { @@ -305,4 +511,7 @@ class IsClientFilter extends Filter $joins[] = ' INNER JOIN runmode USING (machineuuid)'; return "runmode.isclient = 0"; } + } + +StatisticsFilter::initConstants();
\ No newline at end of file diff --git a/modules-available/statistics/inc/filterset.inc.php b/modules-available/statistics/inc/statisticsfilterset.inc.php index 774bfd18..c2642850 100644 --- a/modules-available/statistics/inc/filterset.inc.php +++ b/modules-available/statistics/inc/statisticsfilterset.inc.php @@ -1,9 +1,9 @@ <?php -class FilterSet +class StatisticsFilterSet { /** - * @var \Filter[] + * @var \StatisticsFilter[] */ private $filters; private $sortDirection; @@ -20,7 +20,7 @@ class FilterSet { $direction = ($direction === 'DESC' ? 'DESC' : 'ASC'); - if (!is_string($col) || !array_key_exists($col, Page_Statistics::$columns)) { + if (!is_string($col) || !array_key_exists($col, StatisticsFilter::$columns)) { /* default sorting column is clientip */ $col = 'clientip'; } @@ -56,8 +56,8 @@ class FilterSet $join = implode(' ', array_unique($joins)); $col = $this->sortColumn; - $isMapped = array_key_exists('map_sort', Page_Statistics::$columns[$col]); - $concreteCol = ($isMapped ? Page_Statistics::$columns[$col]['map_sort'] : $col) ; + $isMapped = array_key_exists('map_sort', StatisticsFilter::$columns[$col]); + $concreteCol = ($isMapped ? StatisticsFilter::$columns[$col]['map_sort'] : $col) ; if ($concreteCol === 'clientip') { $concreteCol = "INET_ATON(clientip)"; @@ -90,12 +90,12 @@ class FilterSet return; $this->cache = false; // Runmode module exists, add filter - $this->filters[] = new IsClientFilter(true); + $this->filters[] = new IsClientStatisticsFilter(true); } /** * @param string $type filter type (class name) - * @return false|Filter The filter, false if not found + * @return false|StatisticsFilter The filter, false if not found */ public function hasFilter($type) { @@ -124,7 +124,7 @@ class FilterSet return true; unset($this->filters['permissions']); } else { - $this->filters['permissions'] = new LocationFilter('=', $locs); + $this->filters['permissions'] = new LocationStatisticsFilter('=', $locs); } $this->cache = false; return true; diff --git a/modules-available/statistics/inc/statisticsstyling.inc.php b/modules-available/statistics/inc/statisticsstyling.inc.php new file mode 100644 index 00000000..1fd1d326 --- /dev/null +++ b/modules-available/statistics/inc/statisticsstyling.inc.php @@ -0,0 +1,42 @@ +<?php + +class StatisticsStyling +{ + + public static function ramColorClass($mb) + { + if ($mb < 1500) { + return 'danger'; + } + if ($mb < 2500) { + return 'warning'; + } + + return ''; + } + + public static function kvmColorClass($state) + { + if ($state === 'DISABLED') { + return 'danger'; + } + if ($state === 'UNKNOWN' || $state === 'UNSUPPORTED') { + return 'warning'; + } + + return ''; + } + + public static function hddColorClass($gb) + { + if ($gb < 7) { + return 'danger'; + } + if ($gb < 25) { + return 'warning'; + } + + return ''; + } + +}
\ No newline at end of file |