diff options
Diffstat (limited to 'modules-available/systemstatus/page.inc.php')
-rw-r--r-- | modules-available/systemstatus/page.inc.php | 493 |
1 files changed, 295 insertions, 198 deletions
diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php index 04423eaf..f774c4e0 100644 --- a/modules-available/systemstatus/page.inc.php +++ b/modules-available/systemstatus/page.inc.php @@ -3,7 +3,7 @@ class Page_SystemStatus extends Page { - private $rebootTask = false; + const TM_UPDATE_UUID = '345-45763457-24356-234324556'; protected function doPreprocess() { @@ -14,29 +14,96 @@ class Page_SystemStatus extends Page Util::redirect('?do=Main'); } - if (Request::post('action') === 'reboot') { + $action = Request::post('action', false, 'string'); + $aptAction = null; + switch ($action) { + case 'reboot': User::assertPermission("serverreboot"); - $this->rebootTask = Taskmanager::submit('Reboot'); + $task = Taskmanager::submit('Reboot'); + if (Taskmanager::isTask($task)) { + Util::redirect('?do=systemstatus&taskid=' . $task['id']); + } + break; + case 'service-start': + case 'service-restart': + $this->handleServiceAction(substr($action, 8)); + break; + case 'apt-update': + User::assertPermission('apt.update'); + $aptAction = 'UPDATE'; + break; + case 'apt-upgrade': + User::assertPermission('apt.upgrade'); + $aptAction = 'UPGRADE'; + break; + case 'apt-full-upgrade': + User::assertPermission('apt.upgrade'); + $aptAction = 'FULL_UPGRADE'; + break; + case 'apt-autoremove': + User::assertPermission('apt.autoremove'); + $aptAction = 'AUTOREMOVE'; + break; + case 'apt-fix': + User::assertPermission('apt.fix'); + $aptAction = 'FIX'; + break; + default: + } + if ($aptAction !== null) { + if (!Taskmanager::isRunning(Taskmanager::status(self::TM_UPDATE_UUID))) { + $task = Taskmanager::submit('AptUpgrade', ['mode' => $aptAction, 'id' => self::TM_UPDATE_UUID]); + Taskmanager::release($task); + } + Util::redirect('?do=systemstatus#id-ListUpgradable_pane'); + } + if (Request::isPost()) { + Util::redirect('?do=systemstatus'); } User::assertPermission('*'); } + private function handleServiceAction(string $action) + { + $service = Request::post('service', Request::REQUIRED, 'string'); + $task = Taskmanager::submit('Systemctl', ['operation' => $action, 'service' => $service]); + $extra = ''; + $cmp = preg_replace('/(@.*|\.service)$/', '', $service); + User::assertPermission("restart.$cmp"); + if ($cmp === 'dmsd') { + $extra = '#id-DmsdLog_pane'; + } elseif ($cmp === 'ldadp') { + $extra = '#id-LdadpLog_pane'; + } elseif ($cmp === 'dnbd3-server') { + $extra = '#id-Dnbd3Log_pane'; + } + Util::redirect('?do=systemstatus&taskid=' . $task['id'] . '&taskname=' . urlencode($service) . $extra); + } + protected function doRender() { $data = array(); - if (is_array($this->rebootTask) && isset($this->rebootTask['id'])) { - $data['rebootTask'] = $this->rebootTask['id']; - } - $tabs = array('DmsdLog', 'Netstat', 'PsList', 'LdadpLog', 'LighttpdLog'); + $data['taskid'] = Request::get('taskid', '', 'string'); + $data['taskname'] = Request::get('taskname', 'Reboot', 'string'); + $tabs = ['DmsdLog', 'Netstat', 'PsList', 'LdadpLog', 'LighttpdLog', 'Dnbd3Log', 'ListUpgradable']; $data['tabs'] = array(); + // Dictionary::translate('tab_DmsdLog') Dictionary::translate('tab_LdadpLog') Dictionary::translate('tab_Netstat') + // Dictionary::translate('tab_LighttpdLog') Dictionary::translate('tab_PsList') Dictionary::translate('tab_Dnbd3Log') + // Dictionary::translate('tab_ListUpgradable') foreach ($tabs as $tab) { $data['tabs'][] = array( 'type' => $tab, 'name' => Dictionary::translate('tab_' . $tab), 'enabled' => User::hasPermission('tab.' . $tab), + 'important' => $tab === 'ListUpgradable' + && (SystemStatus::getAptLastDbUpdateTime() + 864000 < time() || SystemStatus::getUpgradableSecurityCount() > 0), ); } Permission::addGlobalTags($data['perms'], null, ['serverreboot']); + $pkgs = SystemStatus::getPackagesRequiringReboot(); + if (!empty($pkgs)) { + $data['packages'] = implode(', ', $pkgs); + } Render::addTemplate('_page', $data); } @@ -52,90 +119,82 @@ class Page_SystemStatus extends Page $this->$action(); Message::renderList(); } else { - echo "Action $action not known in " . get_class(); + // get_class() !== get_class($this) + echo "Action $action not known in " . get_class($this); } } - - protected function ajaxDmsdUsers() + + protected function ajaxListUpgradable() { - User::assertPermission("show.overview.dmsdusers"); - $ret = Download::asStringPost('http://127.0.0.1:9080/status/fileserver', false, 2, $code); - $args = array(); - if ($code != 200) { - $args['dmsd_error'] = true; - } else { - $data = @json_decode($ret, true); - if (is_array($data)) { - $args['uploads'] = $data['activeUploads']; - $args['downloads'] = $data['activeDownloads']; + User::assertPermission("tab.listupgradable"); + + if (User::hasPermission('apt.update') + && Taskmanager::isRunning(Taskmanager::status(self::TM_UPDATE_UUID))) { + echo Render::parse('sys-update-update', [ + 'taskid' => self::TM_UPDATE_UUID, + 'rnd' => mt_rand(), + ]); + return; + } + + $task = SystemStatus::getUpgradableTask(); + + // Estimate last time package list was updated + $lastPackageInstalled = SystemStatus::getDpkgLastPackageChanges(); + $lastListDownloadAttempt = SystemStatus::getAptLastUpdateAttemptTime(); + $updateDbTime = SystemStatus::getAptLastDbUpdateTime(); + + $perms = []; + Permission::addGlobalTags($perms, 0, ['apt.update', 'apt.upgrade', 'apt.autoremove', 'apt.fix']); + + if ($task !== false) { + $task = Taskmanager::waitComplete($task, 30000); + + if (Taskmanager::isFailed($task) || !Taskmanager::isFinished($task)) { + Taskmanager::addErrorMessage($task); + return; + } + if (!Taskmanager::isFailed($task) && empty($task['data']['packages'])) { + $task['data']['error'] = ''; } + } else { + $task['data']['error'] = 'ECONNREFUSED'; } - if (file_exists('/run/reboot-required.pkgs')) { - $lines = file('/run/reboot-required.pkgs', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - $lines = array_unique($lines); - $args['packages'] = implode(', ', $lines); + + foreach ($task['data']['packages'] as &$pkg) { + if (substr($pkg['source'], -9) === '-security') { + $pkg['row_class'] = 'bg-danger'; + } else { + $pkg['row_class'] = ''; + } } - echo Render::parse('ajax-reboot', $args); + unset($pkg); + + echo Render::parse('sys-update-main', [ + 'task' => $task['data'], + 'lastDownload' => Util::prettyTime($lastListDownloadAttempt), + 'lastChanged' => Util::prettyTime($updateDbTime), + 'lastInstalled' => Util::prettyTime($lastPackageInstalled), + 'perm' => $perms, + 'list_old' => $lastListDownloadAttempt + 86400 < time(), + 'needReboot' => implode(', ', SystemStatus::getPackagesRequiringReboot()), + ]); } protected function ajaxDiskStat() { User::assertPermission("show.overview.diskstat"); - $task = Taskmanager::submit('DiskStat'); - if ($task === false) + if (!SystemStatus::diskStat($systemUsage, $storeUsage, $currentSource, $wantedSource)) return; - $task = Taskmanager::waitComplete($task, 3000); - - if (!isset($task['data']['list']) || empty($task['data']['list'])) { - Taskmanager::addErrorMessage($task); - return; - } - $store = Property::getVmStoreUrl(); - $storeUsage = false; - $systemUsage = false; - if ($store !== false) { - if ($store === '<local>') - $storePoint = '/'; - else - $storePoint = CONFIG_VMSTORE_DIR; - // Determine free space - foreach ($task['data']['list'] as $entry) { - if ($entry['mountPoint'] === $storePoint) { - $storeUsage = array( - 'percent' => $entry['usedPercent'], - 'size' => Util::readableFileSize($entry['sizeKb'] * 1024), - 'free' => Util::readableFileSize($entry['freeKb'] * 1024), - 'color' => $this->usageColor($entry['usedPercent']) - ); - } - if ($entry['mountPoint'] === '/') { - $systemUsage = array( - 'percent' => $entry['usedPercent'], - 'size' => Util::readableFileSize($entry['sizeKb'] * 1024), - 'free' => Util::readableFileSize($entry['freeKb'] * 1024), - 'color' => $this->usageColor($entry['usedPercent']) - ); - } - } - $data = array( - 'store' => $storeUsage, - 'system' => $systemUsage - ); - // Determine if proper vm store is being used - if ($store !== '<local>') { - $data['storeMissing'] = $store; - } - foreach ($task['data']['list'] as $entry) { - if ($entry['mountPoint'] !== CONFIG_VMSTORE_DIR) - continue; - if ($store !== $entry['fileSystem']) { - $data['wrongStore'] = $entry['fileSystem']; - break; - } - $data['storeMissing'] = false; - } - } else { + $data = ['system' => $this->convertDiskStat($systemUsage, 3000)]; + if ($wantedSource === false) { // Not configured yet, nothing to display $data['notConfigured'] = true; + } elseif ($wantedSource === $currentSource) { // Fine and dandy + $data['store'] = $this->convertDiskStat($storeUsage, 250000); + } elseif ($currentSource === false) { // No current source, nothing mounted + $data['storeMissing'] = true; + } else { // Something else mounted + $data['wrongStore'] = $currentSource; } echo Render::parse('diskstat', $data); } @@ -148,7 +207,7 @@ class Page_SystemStatus extends Page return; $task = Taskmanager::waitComplete($task, 3000); - if (!isset($task['data']['addresses']) || empty($task['data']['addresses'])) { + if (empty($task['data']['addresses'])) { Taskmanager::addErrorMessage($task); return; } @@ -165,16 +224,17 @@ class Page_SystemStatus extends Page 'addresses' => $task['data']['addresses'] )); } - - private function sysInfo() + + private function sysInfo(): array { $data = array(); $memInfo = file_get_contents('/proc/meminfo'); $stat = file_get_contents('/proc/stat'); - preg_match_all('/\b(\w+):\s+(\d+)\s/s', $memInfo, $out, PREG_SET_ORDER); + preg_match_all('/\b(\w+):\s+(\d+)\s/', $memInfo, $out, PREG_SET_ORDER); foreach ($out as $e) { $data[$e[1]] = $e[2]; } + /** @var array{user: numeric, nice: numeric, system: numeric, idle: numeric, iowait: numeric, irq: numeric, softirq: numeric} $out */ if (preg_match('/\bcpu\s+(?<user>\d+)\s+(?<nice>\d+)\s+(?<system>\d+)\s+(?<idle>\d+)\s+(?<iowait>\d+)\s+(?<irq>\d+)\s+(?<softirq>\d+)(\s|$)/', $stat, $out)) { $data['CpuTotal'] = $out['user'] + $out['nice'] + $out['system'] + $out['idle'] + $out['iowait'] + $out['irq'] + $out['softirq']; $data['CpuIdle'] = $out['idle'] + $out['iowait']; @@ -189,27 +249,32 @@ class Page_SystemStatus extends Page $cpuInfo = file_get_contents('/proc/cpuinfo'); $uptime = file_get_contents('/proc/uptime'); $cpuCount = preg_match_all('/\bprocessor\s/', $cpuInfo, $out); - //$cpuCount = count($out); + $out = parse_ini_file('/etc/os-release'); $data = array( 'cpuCount' => $cpuCount, 'memTotal' => '???', 'memFree' => '???', 'swapTotal' => '???', 'swapUsed' => '???', - 'uptime' => '???' + 'uptime' => '???', + 'kernel' => php_uname('r'), + 'distribution' => $out['PRETTY_NAME'] ?? (($out['NAME'] ?? '???') . ' ' . ($out['VERSION'] ?? '???')), ); if (preg_match('/^(\d+)\D/', $uptime, $out)) { $data['uptime'] = floor($out[1] / 86400) . ' ' . Dictionary::translate('lang_days') . ', ' . floor(($out[1] % 86400) / 3600) . ' ' . Dictionary::translate('lang_hours'); } $info = $this->sysInfo(); if (isset($info['MemTotal']) && isset($info['MemFree']) && isset($info['SwapTotal'])) { + $avail = $info['MemAvailable'] ?? ($info['MemFree'] + $info['Buffers'] + $info['Cached']); $data['memTotal'] = Util::readableFileSize($info['MemTotal'] * 1024); - $data['memFree'] = Util::readableFileSize(($info['MemFree'] + $info['Buffers'] + $info['Cached']) * 1024); - $data['memPercent'] = 100 - round((($info['MemFree'] + $info['Buffers'] + $info['Cached']) / $info['MemTotal']) * 100); + $data['memFree'] = Util::readableFileSize($avail * 1024); + $data['memPercent'] = 100 - round(($avail / $info['MemTotal']) * 100); $data['swapTotal'] = Util::readableFileSize($info['SwapTotal'] * 1024); $data['swapUsed'] = Util::readableFileSize(($info['SwapTotal'] - $info['SwapFree']) * 1024); $data['swapPercent'] = 100 - round(($info['SwapFree'] / $info['SwapTotal']) * 100); - $data['swapWarning'] = ($data['swapPercent'] > 50 || $info['SwapFree'] < 400000); + if ($data['swapTotal'] > 0 && $data['memPercent'] > 75) { + $data['swapWarning'] = ($data['swapPercent'] > 80 || $info['SwapFree'] < 400000); + } } if (isset($info['CpuIdle']) && isset($info['CpuSystem']) && isset($info['CpuTotal'])) { $data['cpuLoad'] = 100 - round(($info['CpuIdle'] / $info['CpuTotal']) * 100); @@ -242,8 +307,9 @@ class Page_SystemStatus extends Page $tasks = array(); $todo = ['dmsd', 'tftpd-hpa']; - if (Module::isAvailable('dnbd3') && Dnbd3::isEnabled()) { + if (Module::get('dnbd3') !== false) { $todo[] = 'dnbd3-server'; + $todo[] = 'dnbd3-master-proxy'; } foreach ($todo as $svc) { @@ -252,10 +318,16 @@ class Page_SystemStatus extends Page 'task' => Taskmanager::submit('Systemctl', ['service' => $svc, 'operation' => 'is-active']) ); } - $tasks[] = array( - 'name' => 'LDAP/AD-Proxy', - 'task' => Trigger::ldadp() - ); + $ldapIds = $ldadp = false; + if (Module::isAvailable('sysconfig')) { + $ldapIds = ConfigModuleBaseLdap::getActiveModuleIds(); + if (!empty($ldapIds)) { + $ldadp = array( // No name - no display + 'task' => ConfigModuleBaseLdap::ldadp('check', $ldapIds) // TODO: Proper --check usage + ); + $tasks[] =& $ldadp; + } + } $deadline = time() + 10; do { $done = true; @@ -271,13 +343,40 @@ class Page_SystemStatus extends Page } while (!$done && time() < $deadline); foreach ($tasks as $task) { + if (!isset($task['name'])) + continue; $fail = Taskmanager::isFailed($task['task']); - $data['services'][] = array( + $entry = array( 'name' => $task['name'], + 'service' => $task['name'], 'fail' => $fail, - 'data' => isset($task['data']) ? $task['data'] : null, - 'unknown' => $task['task'] === false ); + if ($fail) { + if (!isset($task['task']['data'])) { + $entry['error'] = 'Taskmanager Error'; + } elseif (isset($task['task']['data']['messages'])) { + $entry['error'] = $task['task']['data']['messages']; + } + } + $data['services'][] = $entry; + } + if ($ldadp !== false) { + //error_log(print_r($ldadp, true)); + preg_match_all('/^ldadp@(\d+)\.service\s+(\S+)$/m', $ldadp['task']['data']['messages'], $out, PREG_SET_ORDER); + $instances = []; + foreach ($out as $instance) { + $instances[$instance[1]] = $instance[2]; + } + foreach ($ldapIds as $id) { + $status = $instances[$id] ?? 'failed'; + $fail = ($status !== 'running'); + $data['services'][] = [ + 'name' => 'LDAP/AD Proxy #' . $id, + 'service' => 'ldadp@' . $id, + 'fail' => $fail, + 'error' => $fail ? $status : false, + ]; + } } echo Render::parse('services', $data); @@ -285,107 +384,87 @@ class Page_SystemStatus extends Page protected function ajaxDmsdLog() { - User::assertPermission("tab.dmsdlog"); - $fh = @fopen('/var/log/dmsd.log', 'r'); - if ($fh === false) { - echo 'Error opening log file'; - return; - } - fseek($fh, -6000, SEEK_END); - $data = fread($fh, 6000); - @fclose($fh); - if ($data === false) { - echo 'Error reading from log file'; - return; + $this->showJournal('dmsd.service', 'tab.dmsdlog'); + } + + protected function ajaxDnbd3Log() + { + $this->showJournal('dnbd3-server.service', 'tab.dnbd3log'); + } + + protected function showJournal($service, $permission) + { + $cmp = preg_replace('/(@.*|\.service)$/', '', $service); + User::assertPermission($permission); + $output = [ + 'name' => $service, + 'service' => $service, + 'task' => Taskmanager::submit('Systemctl', ['operation' => 'journal', 'service' => $service]), + 'restart_disabled' => User::hasPermission('restart.' . $cmp) + ? '' : 'disabled', + ]; + echo Render::parse('ajax-journal', ['modules' => [$output]]); + } + + private function grepLighttpdLog(string $file, int $num): array + { + $fh = @fopen($file, 'r'); + if ($fh === false) + return ['Error opening ' . $file]; + $ret = []; + fseek($fh, -($num * 2000), SEEK_END); + if (ftell($fh) > 0) { + // Throw away first line, as it's most likely incomplete + fgets($fh, 1000); } - // If we could read less, try the .1 file too - $amount = 6000 - strlen($data); - if ($amount > 100) { - $fh = @fopen('/var/log/dmsd.log.1', 'r'); - if ($fh !== false) { - fseek($fh, -$amount, SEEK_END); - $data = fread($fh, $amount) . $data; - @fclose($fh); + while (($line = fgets($fh, 1000))) { + if (strpos($line, ':SSL routines:') === false + && strpos($line, ' SSL: -1 5 104 Connection reset by peer') === false + && strpos($line, 'GET/HEAD with content-length') === false + && strpos($line, 'POST-request, but content-length missing') === false) { + $ret[] = $line; } } - if (strlen($data) < 5990) { - $start = 0; - } else { - $start = strpos($data, "\n") + 1; - } - echo '<pre>', htmlspecialchars(substr($data, $start), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; + fclose($fh); + return array_slice($ret, -$num); } protected function ajaxLighttpdLog() { User::assertPermission("tab.lighttpdlog"); - $fh = @fopen('/var/log/lighttpd/error.log', 'r'); - if ($fh === false) { - echo 'Error opening log file'; - return; + $lines = $this->grepLighttpdLog('/var/log/lighttpd/error.log', 60); + if (count($lines) < 50) { + $lines = array_merge( + $this->grepLighttpdLog('/var/log/lighttpd/error.log.1', 60 - count($lines)), $lines); } - fseek($fh, -6000, SEEK_END); - $data = fread($fh, 6000); - @fclose($fh); - if ($data === false) { - echo 'Error reading from log file'; - return; - } - // If we could read less, try the .1 file too - $amount = 6000 - strlen($data); - if ($amount > 100) { - $fh = @fopen('/var/log/lighttpd/error.log.1', 'r'); - if ($fh !== false) { - fseek($fh, -$amount, SEEK_END); - $data = fread($fh, $amount) . $data; - @fclose($fh); - } - } - if (strlen($data) < 5990) { - $start = 0; - } else { - $start = strpos($data, "\n") + 1; - } - echo '<pre>', htmlspecialchars(substr($data, $start), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; + echo '<pre>', htmlspecialchars(implode('', $lines), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; } protected function ajaxLdadpLog() { User::assertPermission("tab.ldadplog"); - $haveSysconfig = Module::isAvailable('sysconfig'); - $files = glob('/var/log/ldadp/*.log', GLOB_NOSORT); - if ($files === false || empty($files)) echo('No logs found'); - $now = time(); - foreach ($files as $file) { - $mod = filemtime($file); - if ($now - $mod > 86400) continue; - // New enough - handle - preg_match(',/(\d+)\.log,', $file, $out); - $module = $haveSysconfig ? ConfigModule::get($out[1]) : false; - if ($module === false) { - echo '<h4>Module ', $out[1], '</h4>'; - } else { - echo '<h4>Module ', htmlspecialchars($module->title()), '</h4>'; - } - $fh = @fopen($file, 'r'); - if ($fh === false) { - echo '<pre>Error opening log file</pre>'; - continue; - } - fseek($fh, -5000, SEEK_END); - $data = fread($fh, 5000); - @fclose($fh); - if ($data === false) { - echo '<pre>Error reading from log file</pre>'; - continue; - } - if (strlen($data) < 4990) { - $start = 0; + if (!Module::isAvailable('sysconfig')) { + die('SysConfig module not enabled'); + } + $ids = ConfigModuleBaseLdap::getActiveModuleIds(); + //error_log(print_r($ids, true)); + $output = []; + foreach ($ids as $id) { + $module = ConfigModule::get($id); + if ($module === null) { + $name = "#$id"; } else { - $start = strpos($data, "\n") + 1; + $name = $module->title(); } - echo '<pre>', htmlspecialchars(substr($data, $start), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; + $service = "ldadp@{$id}.service"; + $output[] = [ + 'name' => $name, + 'service' => $service, + 'task' => Taskmanager::submit('Systemctl', ['operation' => 'journal', 'service' => $service]), + ]; } + //error_log(print_r($output, true)); + echo Render::parse('ajax-journal', ['modules' => $output]); } protected function ajaxNetstat() @@ -396,10 +475,7 @@ class Page_SystemStatus extends Page return; $status = Taskmanager::waitComplete($taskId, 3500); - if (isset($status['data']['messages'])) - $data = $status['data']['messages']; - else - $data = 'Taskmanager error'; + $data = $status['data']['messages'] ?? 'Taskmanager error'; echo '<pre>', htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; } @@ -412,31 +488,52 @@ class Page_SystemStatus extends Page return; $status = Taskmanager::waitComplete($taskId, 3500); - if (isset($status['data']['messages'])) - $data = $status['data']['messages']; - else - $data = 'Taskmanager error'; + $data = $status['data']['messages'] ?? 'Taskmanager error'; echo '<pre>', htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>'; } - private function usageColor($percent) + /** + * @return array{percent: numeric, size: string, free: string, color: string, filesystem: string} + */ + private function convertDiskStat(array $stat, int $minFreeMb): array { - if ($percent <= 50) { - $r = $b = $percent / 3; - $g = (100 - $percent * (50 / 80)); - } elseif ($percent <= 70) { - $r = 55 + ($percent - 50) * (30 / 20); + return [ + 'percent' => $stat['usedPercent'], + 'size' => Util::readableFileSize($stat['sizeKb'] * 1024), + 'free' => Util::readableFileSize($stat['freeKb'] * 1024), + 'color' => $this->usageColor($stat, $minFreeMb), + 'filesystem' => $stat['fileSystem'], + ]; + } + + private function usageColor(array $stat, int $minFreeMb): string + { + $freeMb = round($stat['freeKb'] / 1024); + // All good is half space free, or 4x the min free amount, whatever is more + $okFreeMb = max($minFreeMb * 4, round($stat['sizeKb']) / (1024 * 2)); + if ($freeMb > $okFreeMb) { + $usedPercent = 0; + } elseif ($freeMb < $minFreeMb) { + $usedPercent = 100; + } else { + $usedPercent = 100 - round(($freeMb - $minFreeMb) / ($okFreeMb - $minFreeMb) * 100); + } + if ($usedPercent <= 50) { + $r = $b = $usedPercent / 3; + $g = (100 - $usedPercent * (50 / 80)); + } elseif ($usedPercent <= 70) { + $r = 55 + ($usedPercent - 50) * (30 / 20); $g = 60; $b = 0; } else { - $r = ($percent - 70) / 3 + 90; - $g = (100 - $percent) * (60 / 30); + $r = ($usedPercent - 70) / 3 + 90; + $g = (100 - $usedPercent) * (60 / 30); $b = 0; } - $r = dechex(round($r * 2.55)); - $g = dechex(round($g * 2.55)); - $b = dechex(round($b * 2.55)); + $r = dechex((int)round($r * 2.55)); + $g = dechex((int)round($g * 2.55)); + $b = dechex((int)round($b * 2.55)); return sprintf("%02s%02s%02s", $r, $g, $b); } |