summaryrefslogtreecommitdiffstats
path: root/modules-available/systemstatus
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/systemstatus')
-rw-r--r--modules-available/systemstatus/hooks/cron.inc.php6
-rw-r--r--modules-available/systemstatus/hooks/main-warning.inc.php18
-rw-r--r--modules-available/systemstatus/inc/systemstatus.inc.php119
-rw-r--r--modules-available/systemstatus/lang/de/messages.json2
-rw-r--r--modules-available/systemstatus/lang/de/module.json1
-rw-r--r--modules-available/systemstatus/lang/de/permissions.json5
-rw-r--r--modules-available/systemstatus/lang/de/template-tags.json19
-rw-r--r--modules-available/systemstatus/lang/en/messages.json2
-rw-r--r--modules-available/systemstatus/lang/en/module.json1
-rw-r--r--modules-available/systemstatus/lang/en/permissions.json5
-rw-r--r--modules-available/systemstatus/lang/en/template-tags.json19
-rw-r--r--modules-available/systemstatus/page.inc.php248
-rw-r--r--modules-available/systemstatus/permissions/permissions.json15
-rw-r--r--modules-available/systemstatus/templates/_page.html6
-rw-r--r--modules-available/systemstatus/templates/diskstat.html2
-rw-r--r--modules-available/systemstatus/templates/sys-update-main.html118
-rw-r--r--modules-available/systemstatus/templates/sys-update-update.html35
-rw-r--r--modules-available/systemstatus/templates/systeminfo.html161
18 files changed, 632 insertions, 150 deletions
diff --git a/modules-available/systemstatus/hooks/cron.inc.php b/modules-available/systemstatus/hooks/cron.inc.php
new file mode 100644
index 00000000..91e069d4
--- /dev/null
+++ b/modules-available/systemstatus/hooks/cron.inc.php
@@ -0,0 +1,6 @@
+<?php
+
+if ((int)gmdate('i') < 5) {
+ // Don't care about task, this will register a callback
+ SystemStatus::getUpgradableTask();
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/hooks/main-warning.inc.php b/modules-available/systemstatus/hooks/main-warning.inc.php
index 5707c7d2..6b0ac981 100644
--- a/modules-available/systemstatus/hooks/main-warning.inc.php
+++ b/modules-available/systemstatus/hooks/main-warning.inc.php
@@ -1,9 +1,19 @@
<?php
-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);
- Message::addInfo('systemstatus.update-reboot-required', true, implode(', ', $lines));
+$cnt = SystemStatus::getUpgradableSecurityCount();
+if ($cnt > 0) {
+ Message::addWarning('systemstatus.security-updates-available', true, $cnt);
+}
+
+$pkgs = SystemStatus::getPackagesRequiringReboot();
+if (!empty($pkgs)) {
+ Message::addInfo('systemstatus.update-reboot-required', true, implode(', ', $pkgs));
+}
+
+$aptTs = SystemStatus::getAptLastDbUpdateTime();
+if ($aptTs + 864000 < time()) {
+ // No update for 10 days
+ Message::addWarning('systemstatus.apt-db-out-of-date', true, Util::prettyTime($aptTs));
}
if (SystemStatus::diskStat($systemUsage, $storeUsage, $current, $wanted)) {
diff --git a/modules-available/systemstatus/inc/systemstatus.inc.php b/modules-available/systemstatus/inc/systemstatus.inc.php
index 4413af5f..c50e0ef6 100644
--- a/modules-available/systemstatus/inc/systemstatus.inc.php
+++ b/modules-available/systemstatus/inc/systemstatus.inc.php
@@ -3,6 +3,8 @@
class SystemStatus
{
+ const PROP_UPGRADABLE_COUNT = 'systemstatus.upgradable-count';
+
/**
* Collect status about the disk and vmstore.
* The *Usage vars are filled with arrays with keys mountPoint, fileSystem,
@@ -13,27 +15,28 @@ class SystemStatus
* @param string|false $wantedSource What should be mounted as vmstore (false if nothing configured)
* @return bool false if querying fs data from taskmanager failed
*/
- public static function diskStat(&$systemUsage, &$storeUsage, &$currentSource = false, &$wantedSource = false)
+ public static function diskStat(&$systemUsage, &$storeUsage, &$currentSource = false, &$wantedSource = false): bool
{
$task = Taskmanager::submit('DiskStat');
if ($task === false)
return false;
$task = Taskmanager::waitComplete($task, 3000);
- if (!isset($task['data']['list']) || empty($task['data']['list']))
+ if (empty($task['data']['list']))
return false;
$wantedSource = Property::getVmStoreUrl();
- $currentSource = false;
$storeUsage = false;
$systemUsage = false;
if ($wantedSource === '<local>') {
$storePoint = '/';
+ $currentSource = $wantedSource;
} else {
$storePoint = CONFIG_VMSTORE_DIR;
+ $currentSource = false;
}
// Collect free space information
foreach ($task['data']['list'] as $entry) {
- // StorePoint is either the atual directory of the vmstore, or / if we use internal storage
+ // StorePoint is either the actual directory of the vmstore, or / if we use internal storage
if ($entry['mountPoint'] === $storePoint) {
$storeUsage = $entry;
}
@@ -42,12 +45,116 @@ class SystemStatus
$systemUsage = $entry;
}
// Record what's mounted at destination, regardless of config, to indicate something is wrong
- if (($currentSource === false && $wantedSource === '<local>' && $entry['mountPoint'] === '/')
- || $entry['mountPoint'] === CONFIG_VMSTORE_DIR) {
+ if ($entry['mountPoint'] === CONFIG_VMSTORE_DIR) {
$currentSource = $entry['fileSystem'];
+
+ // If internal/local storage is used but there is a mount on CONFIG_VMSTORE_DIR,
+ // we assume it's on purpose like a second hdd and use that
+ if ($wantedSource === '<local>') {
+ $wantedSource = $currentSource;
+ $storeUsage = $entry;
+ }
}
}
return true;
}
+ /**
+ * Get timestamp of the available updates. This is an estimate; the downloaded apt data usually
+ * preserves the Last-Modified timestamp from the HTTP download of the according data. Note
+ * that this list gets updated whenever any available package changes, so it does not necessarily
+ * mean that any currently installed package can be updated when the list changes.
+ */
+ public static function getAptLastDbUpdateTime(): int
+ {
+ $osRelease = parse_ini_file('/etc/os-release');
+ $updateDbTime = 0;
+ foreach (glob('/var/lib/apt/lists/*_dists_' . ($osRelease['VERSION_CODENAME'] ?? '') . '*_InRelease', GLOB_NOSORT) as $f) {
+ $b = basename($f);
+ if (preg_match('/dists_[a-z]+(?:[\-_](?:updates|security))?_InRelease$/', $b)) {
+ $updateDbTime = max($updateDbTime, filemtime($f));
+ }
+ }
+ return $updateDbTime;
+ }
+
+ /**
+ * Get timestamp when the apt database was last attempted to be updated. This does not
+ * imply that the operation was successful.
+ */
+ public static function getAptLastUpdateAttemptTime(): int
+ {
+ return (int)filemtime('/var/lib/apt/lists/partial');
+ }
+
+ /**
+ * Get when the dpkg database was last changed, i.e. when a package was last installed, updated or removed.
+ * This is an estimate as it just looks at the modification time of relevant files. It is possible these
+ * files get modified for other reasons.
+ */
+ public static function getDpkgLastPackageChanges(): int
+ {
+ return (int)filemtime(file_exists('/var/log/dpkg.log') ? '/var/log/dpkg.log' : '/var/lib/dpkg/status');
+ }
+
+ /**
+ * Get list of packages that have been updated, but require a reboot of the system
+ * to fully take effect.
+ * @return string[]
+ */
+ public static function getPackagesRequiringReboot(): array
+ {
+ if (!file_exists('/run/reboot-required.pkgs'))
+ return [];
+ $lines = file('/run/reboot-required.pkgs', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+ return array_unique($lines);
+ }
+
+ /**
+ * Get a task struct querying upgradable packages. This adds
+ * a hook to the task to cache the number of upgradable packages
+ * that are security upgrades, so it is preferred to call this
+ * wrapper instead of running the task directly.
+ */
+ public static function getUpgradableTask()
+ {
+ $task = Taskmanager::submit('AptGetUpgradable');
+ if (Taskmanager::isTask($task)) {
+ TaskmanagerCallback::addCallback($task, 'ssUpgradable');
+ }
+ return $task;
+ }
+
+ /**
+ * Called from Taskmanager callback after invoking getUpgradableTask().
+ */
+ public static function setUpgradableData(array $task)
+ {
+ if (Taskmanager::isFailed($task) || !Taskmanager::isFinished($task) || !isset($task['data']['packages']))
+ return;
+ $count = 0;
+ foreach ($task['data']['packages'] as $package) {
+ if (substr($package['source'], -9) === '-security') {
+ $count++;
+ }
+ }
+ error_log("Upgradable security count: $count, total count: " . count($task['data']['packages']));
+ Property::set(self::PROP_UPGRADABLE_COUNT, $count . '|' . count($task['data']['packages']), 61);
+ }
+
+ /**
+ * Get number of packages that can be upgraded and are security updates.
+ * This is a cached value and should be updated at least once an hour.
+ */
+ public static function getUpgradableSecurityCount(): int
+ {
+ $str = Property::get(self::PROP_UPGRADABLE_COUNT);
+ if ($str === false)
+ return 0;
+ $p = explode('|', $str);
+ if (empty($p) || !is_numeric($p[0]))
+ return 0;
+ return (int)$p[0];
+ }
+
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/de/messages.json b/modules-available/systemstatus/lang/de/messages.json
index 0aaefd23..551e937a 100644
--- a/modules-available/systemstatus/lang/de/messages.json
+++ b/modules-available/systemstatus/lang/de/messages.json
@@ -1,4 +1,6 @@
{
+ "apt-db-out-of-date": "Die Systemupdate-Datenbank ist veraltet ({{0}}). Erw\u00e4gen Sie, nach neuen Updates zu suchen, und diese zu installieren.",
+ "security-updates-available": "Ausstehende Sicherheitsupdates: {{0}}",
"storage-low-system": "Dem Betriebssystem geht der freie Speicher aus. Nur noch {{0}} frei. Versuchen Sie, alte \"Netboot Grundsystem\"-Versionen zu l\u00f6schen.",
"storage-low-vmstore": "Auf dem VMstore sind nur noch {{0}} frei",
"update-reboot-required": "Das Update der folgenden Pakete erfordert einen Reboot des Servers: {{0}}"
diff --git a/modules-available/systemstatus/lang/de/module.json b/modules-available/systemstatus/lang/de/module.json
index 22be8a1d..3b310b1d 100644
--- a/modules-available/systemstatus/lang/de/module.json
+++ b/modules-available/systemstatus/lang/de/module.json
@@ -5,6 +5,7 @@
"tab_Dnbd3Log": "DNBD3 Server Log",
"tab_LdadpLog": "LDAP\/AD",
"tab_LighttpdLog": "lighttpd Log",
+ "tab_ListUpgradable": "System-Updates",
"tab_Netstat": "netstat -tulpn",
"tab_PsList": "ps auxf"
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/de/permissions.json b/modules-available/systemstatus/lang/de/permissions.json
index 9e7c5be9..f2dd9a21 100644
--- a/modules-available/systemstatus/lang/de/permissions.json
+++ b/modules-available/systemstatus/lang/de/permissions.json
@@ -1,4 +1,8 @@
{
+ "apt.autoremove": "Nicht mehr ben\u00f6tigte Pakete deinstallieren.",
+ "apt.fix": "Installalations- und Abh\u00e4ngigkeitsprobleme beheben lassen.",
+ "apt.update": "Das System updaten.",
+ "apt.upgrade": "Das System mittels \"full-upgrade\" updaten.",
"restart.dmsd": "bwLehrpool-Suite neustarten.",
"restart.dnbd3-server": "DNBD3-Server neustarten.",
"restart.ldadp": "LDADP neustarten.",
@@ -12,6 +16,7 @@
"tab.dnbd3log": "Zugriff auf DNBD3 Log.",
"tab.ldadplog": "Zugriff auf LDAP\/AD-Proxy Logs.",
"tab.lighttpdlog": "Zugriff auf Webserver-Logs.",
+ "tab.listupgradable": "Zugriff auf System-Update-\u00dcbersicht.",
"tab.netstat": "Zeige Ausgabe von netstat.",
"tab.pslist": "Zeige Prozessliste."
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/de/template-tags.json b/modules-available/systemstatus/lang/de/template-tags.json
index 6641b9e1..c94720a6 100644
--- a/modules-available/systemstatus/lang/de/template-tags.json
+++ b/modules-available/systemstatus/lang/de/template-tags.json
@@ -1,17 +1,28 @@
{
"lang_OK": "OK",
"lang_addressConfiguration": "Adresskonfiguration",
+ "lang_aptOutput": "apt-get Ausgabe",
"lang_areYouSureReboot": "Server jetzt neustarten?",
"lang_attention": "Achtung!",
"lang_average": "Durchschnitt",
+ "lang_backToPackagelist": "Zur\u00fcck zur Update-\u00dcbersicht",
"lang_capacity": "Kapazit\u00e4t",
+ "lang_checkForUpdates": "Auf neue Updates pr\u00fcfen",
"lang_confirmRestart": "Diesen Dienst wirklich neustarten? Dies kann Auswirkungen auf den Betrieb haben.",
"lang_cpuLoad": "CPU-Last",
+ "lang_distribution": "Distribution",
"lang_dmsdUnreachable": "dmsd nicht erreichbar",
+ "lang_everythingUpToDate": "Das System ist auf dem aktuellen Stand",
"lang_failure": "Fehler",
+ "lang_fixDependencies": "Installationsprobleme beheben",
"lang_foundStore": "Vorgefunden:",
"lang_free": "Frei",
"lang_goToStoreConf": "Zur VM-Store-Konfiguration wechseln",
+ "lang_kernel": "Kernel",
+ "lang_lastPackageInstall": "Updates installiert",
+ "lang_lastUpdateCheck": "Letzter Update-Check",
+ "lang_lastestUpdate": "Neuste Updates von",
+ "lang_listOldWarning": "Die Update-Datenbank scheint veraltet. Es wird empfohlen, zun\u00e4chst nach Updates zu suchen.",
"lang_logicCPUs": "Logische CPUs",
"lang_maintenance": "Maintenance",
"lang_moduleHeading": "System-Status",
@@ -19,12 +30,18 @@
"lang_occupied": "Belegt",
"lang_onlyOS": "Nur OS",
"lang_overview": "\u00dcbersicht",
+ "lang_package": "Paket",
+ "lang_packagesNeedingReboot": "Pakete, die einen Systemneustart erfordern",
"lang_ramUsage": "RAM-Nutzung",
+ "lang_removeUnusedPackages": "Nicht mehr ben\u00f6tigte Pakete entfernen",
"lang_restart": "Neustarten",
+ "lang_runFullUpdate": "\"Full-Upgrade\" durchf\u00fchren",
+ "lang_runUpdate": "Update durchf\u00fchren",
"lang_runningDownloads": "Aktive Downloads",
"lang_runningUploads": "Aktive Uploads",
"lang_serverReboot": "Server neustarten",
"lang_services": "Dienste",
+ "lang_showPackageList": "Zur Update- und Paket-\u00dcbersicht",
"lang_space": "Speicherplatz",
"lang_storeMissingExpected": "VM-Store nicht eingebunden. Erwartet:",
"lang_storeNotConfigured": "Kein VM-Store konfiguriert!",
@@ -35,7 +52,9 @@
"lang_systemStoreError": "Fehler beim Ermitteln des verf\u00fcgbaren Systemspeichers",
"lang_total": "Gesamt",
"lang_updatedPackages": "Ausstehende Updates",
+ "lang_updatesWikiLink": "Mehr Informationen zu Updates im bwLehrpool-Wiki",
"lang_uptimeOS": "OS Uptime",
+ "lang_versionFromTo": "Update-Details",
"lang_vmStore": "VM-Speicher",
"lang_vmStoreError": "Fehler beim Ermitteln des verf\u00fcgbaren Speicherplatzes am VM-Speicherort. Bitte \u00fcberpr\u00fcfen Sie die Konfiguration."
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/messages.json b/modules-available/systemstatus/lang/en/messages.json
index dc9d3dd0..2afc3431 100644
--- a/modules-available/systemstatus/lang/en/messages.json
+++ b/modules-available/systemstatus/lang/en/messages.json
@@ -1,4 +1,6 @@
{
+ "apt-db-out-of-date": "The system update database is out of date ({{0}}). Consider checking for new updates and installing them.",
+ "security-updates-available": "Pending security updates: {{0}}",
"storage-low-system": "System storage running out. Only {{0}} free. You could try deleting old Net-boot OS versions.",
"storage-low-vmstore": "VMstore space is running out. Only {{0}} left.",
"update-reboot-required": "Updating the following system packages requires reboot: {{0}}"
diff --git a/modules-available/systemstatus/lang/en/module.json b/modules-available/systemstatus/lang/en/module.json
index f5fec515..cc2b5283 100644
--- a/modules-available/systemstatus/lang/en/module.json
+++ b/modules-available/systemstatus/lang/en/module.json
@@ -5,6 +5,7 @@
"tab_Dnbd3Log": "DNBD3 server log",
"tab_LdadpLog": "LDAP\/AD",
"tab_LighttpdLog": "lighttpd log",
+ "tab_ListUpgradable": "System updates",
"tab_Netstat": "netstat -tulpn",
"tab_PsList": "ps auxf"
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/permissions.json b/modules-available/systemstatus/lang/en/permissions.json
index d510e257..21e7538f 100644
--- a/modules-available/systemstatus/lang/en/permissions.json
+++ b/modules-available/systemstatus/lang/en/permissions.json
@@ -1,4 +1,8 @@
{
+ "apt.autoremove": "Remove packages that are no longer required.",
+ "apt.fix": "Try to fix installation and dependency problems.",
+ "apt.update": "Update system.",
+ "apt.upgrade": "Update system via \"full-upgrade\".",
"restart.dmsd": "Restart bwLehrpool-Suite.",
"restart.dnbd3-server": "Restart DNBD3 server.",
"restart.ldadp": "Restart LDADP.",
@@ -12,6 +16,7 @@
"tab.dnbd3log": "Show DNBD3 log.",
"tab.ldadplog": "Show LDAP\/AD proxy logs.",
"tab.lighttpdlog": "Show web server logs.",
+ "tab.listupgradable": "Show system update status.",
"tab.netstat": "Show output of netstat.",
"tab.pslist": "Show process list."
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/template-tags.json b/modules-available/systemstatus/lang/en/template-tags.json
index b7f9867a..7758c71c 100644
--- a/modules-available/systemstatus/lang/en/template-tags.json
+++ b/modules-available/systemstatus/lang/en/template-tags.json
@@ -1,17 +1,28 @@
{
"lang_OK": "OK",
"lang_addressConfiguration": "Address Configuration",
+ "lang_aptOutput": "apt-get output",
"lang_areYouSureReboot": "Reboot server now?",
"lang_attention": "Attention!",
"lang_average": "Average",
+ "lang_backToPackagelist": "Back up update page",
"lang_capacity": "Capacity",
+ "lang_checkForUpdates": "Check for updates",
"lang_confirmRestart": "Are you sure you want to restart this service? This can lead to interruptions.",
"lang_cpuLoad": "CPU Load",
+ "lang_distribution": "Distribution",
"lang_dmsdUnreachable": "dmsd not reachable",
+ "lang_everythingUpToDate": "Everything is up to date",
"lang_failure": "Failure",
+ "lang_fixDependencies": "Fix installation\/dependency problems",
"lang_foundStore": "Found:",
"lang_free": "Free",
"lang_goToStoreConf": "Go to VM store configuration",
+ "lang_kernel": "Kernel",
+ "lang_lastPackageInstall": "Updates installed",
+ "lang_lastUpdateCheck": "Last update check",
+ "lang_lastestUpdate": "Latest updates from",
+ "lang_listOldWarning": "The package database is out of date. Consider checking for updates before updating.",
"lang_logicCPUs": "Logical CPUs",
"lang_maintenance": "Maintenance",
"lang_moduleHeading": "System Status",
@@ -19,12 +30,18 @@
"lang_occupied": "In use",
"lang_onlyOS": "OS only",
"lang_overview": "Overview",
+ "lang_package": "Package",
+ "lang_packagesNeedingReboot": "Packages that require a system reboot",
"lang_ramUsage": "RAM usage",
+ "lang_removeUnusedPackages": "Remove unused packages",
"lang_restart": "Restart",
+ "lang_runFullUpdate": "Run \"full-upgrade\"",
+ "lang_runUpdate": "Run update",
"lang_runningDownloads": "Running downloads",
"lang_runningUploads": "Running uploads",
"lang_serverReboot": "Reboot Server",
"lang_services": "Services",
+ "lang_showPackageList": "Show updates and packages",
"lang_space": "Space",
"lang_storeMissingExpected": "VM store not mounted. Expected:",
"lang_storeNotConfigured": "No VM store configured!",
@@ -35,7 +52,9 @@
"lang_systemStoreError": "Error querying available system storage",
"lang_total": "Total",
"lang_updatedPackages": "Pending updates",
+ "lang_updatesWikiLink": "See bwLehrpool Wiki for more information regarding updates",
"lang_uptimeOS": "OS uptime",
+ "lang_versionFromTo": "Update details",
"lang_vmStore": "VM store",
"lang_vmStoreError": "Error determining available space of the VM storage. Please check the configuration."
} \ No newline at end of file
diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php
index 238537d8..f774c4e0 100644
--- a/modules-available/systemstatus/page.inc.php
+++ b/modules-available/systemstatus/page.inc.php
@@ -3,6 +3,8 @@
class Page_SystemStatus extends Page
{
+ const TM_UPDATE_UUID = '345-45763457-24356-234324556';
+
protected function doPreprocess()
{
User::load();
@@ -13,14 +15,47 @@ class Page_SystemStatus extends Page
}
$action = Request::post('action', false, 'string');
- if ($action === 'reboot') {
+ $aptAction = null;
+ switch ($action) {
+ case 'reboot':
User::assertPermission("serverreboot");
$task = Taskmanager::submit('Reboot');
if (Taskmanager::isTask($task)) {
Util::redirect('?do=systemstatus&taskid=' . $task['id']);
}
- } elseif ($action === 'service-start' || $action === 'service-restart') {
+ 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');
@@ -50,22 +85,24 @@ class Page_SystemStatus extends Page
$data = array();
$data['taskid'] = Request::get('taskid', '', 'string');
$data['taskname'] = Request::get('taskname', 'Reboot', 'string');
- $tabs = array('DmsdLog', 'Netstat', 'PsList', 'LdadpLog', 'LighttpdLog', 'Dnbd3Log');
+ $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, true),
+ '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']);
- 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);
- $data['packages'] = implode(', ', $lines);
+ $pkgs = SystemStatus::getPackagesRequiringReboot();
+ if (!empty($pkgs)) {
+ $data['packages'] = implode(', ', $pkgs);
}
Render::addTemplate('_page', $data);
}
@@ -82,20 +119,78 @@ 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 ajaxListUpgradable()
+ {
+ 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';
+ }
+
+ foreach ($task['data']['packages'] as &$pkg) {
+ if (substr($pkg['source'], -9) === '-security') {
+ $pkg['row_class'] = 'bg-danger';
+ } else {
+ $pkg['row_class'] = '';
+ }
+ }
+ 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");
if (!SystemStatus::diskStat($systemUsage, $storeUsage, $currentSource, $wantedSource))
return;
- $data = ['system' => $this->convertDiskStat($systemUsage)];
+ $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);
+ $data['store'] = $this->convertDiskStat($storeUsage, 250000);
} elseif ($currentSource === false) { // No current source, nothing mounted
$data['storeMissing'] = true;
} else { // Something else mounted
@@ -112,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;
}
@@ -129,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'];
@@ -153,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);
@@ -305,37 +406,38 @@ class Page_SystemStatus extends Page
echo Render::parse('ajax-journal', ['modules' => [$output]]);
}
- protected function ajaxLighttpdLog()
+ private function grepLighttpdLog(string $file, int $num): array
{
- User::assertPermission("tab.lighttpdlog");
- $fh = @fopen('/var/log/lighttpd/error.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;
+ $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/lighttpd/error.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;
+ fclose($fh);
+ return array_slice($ret, -$num);
+ }
+
+ protected function ajaxLighttpdLog()
+ {
+ User::assertPermission("tab.lighttpdlog");
+ $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);
}
- 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()
@@ -349,7 +451,7 @@ class Page_SystemStatus extends Page
$output = [];
foreach ($ids as $id) {
$module = ConfigModule::get($id);
- if ($module === false) {
+ if ($module === null) {
$name = "#$id";
} else {
$name = $module->title();
@@ -373,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>';
}
@@ -389,43 +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 convertDiskStat($stat)
+ /**
+ * @return array{percent: numeric, size: string, free: string, color: string, filesystem: string}
+ */
+ private function convertDiskStat(array $stat, int $minFreeMb): array
{
- if (!is_array($stat))
- return false;
return [
'percent' => $stat['usedPercent'],
'size' => Util::readableFileSize($stat['sizeKb'] * 1024),
'free' => Util::readableFileSize($stat['freeKb'] * 1024),
- 'color' => $this->usageColor($stat['usedPercent']),
+ 'color' => $this->usageColor($stat, $minFreeMb),
+ 'filesystem' => $stat['fileSystem'],
];
}
- private function usageColor($percent)
+ private function usageColor(array $stat, int $minFreeMb): string
{
- if ($percent <= 50) {
- $r = $b = $percent / 3;
- $g = (100 - $percent * (50 / 80));
- } elseif ($percent <= 70) {
- $r = 55 + ($percent - 50) * (30 / 20);
+ $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);
}
diff --git a/modules-available/systemstatus/permissions/permissions.json b/modules-available/systemstatus/permissions/permissions.json
index a116fd56..0be0a8c5 100644
--- a/modules-available/systemstatus/permissions/permissions.json
+++ b/modules-available/systemstatus/permissions/permissions.json
@@ -20,6 +20,9 @@
"tab.lighttpdlog": {
"location-aware": false
},
+ "tab.listupgradable": {
+ "location-aware": false
+ },
"show.overview.addresses": {
"location-aware": false
},
@@ -43,5 +46,17 @@
},
"restart.dmsd": {
"location-aware": false
+ },
+ "apt.update": {
+ "location-aware": false
+ },
+ "apt.upgrade": {
+ "location-aware": false
+ },
+ "apt.autoremove": {
+ "location-aware": false
+ },
+ "apt.fix": {
+ "location-aware": false
}
} \ No newline at end of file
diff --git a/modules-available/systemstatus/templates/_page.html b/modules-available/systemstatus/templates/_page.html
index 4b62104c..dedcf01a 100644
--- a/modules-available/systemstatus/templates/_page.html
+++ b/modules-available/systemstatus/templates/_page.html
@@ -14,6 +14,9 @@
{{^enabled}}
<li class="disabled">
<a>
+ {{#important}}
+ <span class="glyphicon glyphicon-warning-sign text-danger"></span>
+ {{/important}}
{{name}}
</a>
</li>
@@ -21,6 +24,9 @@
{{#enabled}}
<li>
<a href="#id-{{type}}_pane" class="ajax-tab" id="id-{{type}}" data-toggle="tab" role="tab">
+ {{#important}}
+ <span class="glyphicon glyphicon-warning-sign text-danger"></span>
+ {{/important}}
{{name}}
</a>
</li>
diff --git a/modules-available/systemstatus/templates/diskstat.html b/modules-available/systemstatus/templates/diskstat.html
index 528d9792..1cb8a3ef 100644
--- a/modules-available/systemstatus/templates/diskstat.html
+++ b/modules-available/systemstatus/templates/diskstat.html
@@ -1,6 +1,7 @@
<div class="slx-storechart">
{{#system}}
<b>{{lang_systemPartition}}</b>
+ <span class="glyphicon glyphicon-info-sign" title={{filesystem}}/>
<div id="circles-system"></div>
<div>{{lang_capacity}}: {{size}}</div>
<div>{{lang_free}}: {{free}}</div>
@@ -12,6 +13,7 @@
<div class="slx-storechart">
{{#store}}
<b>{{lang_vmStore}}</b>
+ <span class="glyphicon glyphicon-info-sign" title={{filesystem}}/>
<div id="circles-store"></div>
<div>{{lang_capacity}}: {{size}}</div>
<div>{{lang_free}}: {{free}}</div>
diff --git a/modules-available/systemstatus/templates/sys-update-main.html b/modules-available/systemstatus/templates/sys-update-main.html
new file mode 100644
index 00000000..ca502ddb
--- /dev/null
+++ b/modules-available/systemstatus/templates/sys-update-main.html
@@ -0,0 +1,118 @@
+<div class="panel panel-default">
+ <div class="panel-body">
+ <div class="pull-right">
+ <form action="?do=systemstatus" method="post">
+ <input type="hidden" name="token" value="{{token}}">
+ <div>
+ <button type="submit" class="btn btn-success" name="action"
+ value="apt-update" {{perm.apt.update.disabled}}>
+ <span class="glyphicon glyphicon-refresh"></span>
+ {{lang_checkForUpdates}}
+ </button>
+ </div>
+ <div class="slx-smallspace"></div>
+ <div class="btn-group dropdown">
+ <button type="submit" class="btn btn-primary" name="action"
+ value="apt-upgrade" {{perm.apt.upgrade.disabled}}>
+ <span class="glyphicon glyphicon-play"></span>
+ {{lang_runUpdate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-toggle"
+ data-toggle="dropdown" aria-haspopup="true">
+ <span class="caret"></span>
+ <span class="sr-only">Toggle Dropdown</span>
+ </button>
+ <div class="dropdown-menu" style="padding:0">
+ <div class="btn-group-vertical">
+ <button type="submit" name="action" value="apt-full-upgrade" class="btn btn-primary"
+ style="text-align: left !important" {{perm.apt.upgrade.disabled}}>
+ <span class="glyphicon glyphicon-play"></span>
+ {{lang_runFullUpdate}}
+ </button>
+ <button type="submit" name="action" value="apt-autoremove" class="btn btn-primary"
+ style="text-align: left !important" {{perm.apt.autoremove.disabled}}>
+ <span class="glyphicon glyphicon-trash"></span>
+ {{lang_removeUnusedPackages}}
+ </button>
+ <button type="submit" name="action" value="apt-fix" class="btn btn-primary"
+ style="text-align: left !important" {{perm.apt.fix.disabled}}>
+ <span class="glyphicon glyphicon-wrench"></span>
+ {{lang_fixDependencies}}
+ </button>
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+ <table>
+ <tr>
+ <td>{{lang_lastestUpdate}}:&nbsp;</td>
+ <td>{{lastChanged}}</td>
+ <tr>
+ <tr>
+ <td>{{lang_lastUpdateCheck}}:&nbsp;</td>
+ <td>{{lastDownload}}</td>
+ </tr>
+ <tr>
+ <td>{{lang_lastPackageInstall}}:&nbsp;</td>
+ <td>{{lastInstalled}}</td>
+ <tr>
+ </table>
+ {{#list_old}}
+ <div class="slx-smallspace"></div>
+ <div class="text-danger">
+ {{lang_listOldWarning}}
+ </div>
+ {{/list_old}}
+ </div>
+</div>
+
+{{#task.packages.0}}
+ <table class="table table-condensed">
+ <thead>
+ <tr>
+ <th>{{lang_package}}</th>
+ <th colspan="3">{{lang_versionFromTo}}</th>
+ </tr>
+ </thead>
+ {{#task.packages}}
+ <tr class="{{row_class}}">
+ <td><strong>{{name}}</strong><span class="text-muted">/{{source}}</span></td>
+ <td class="slx-smallcol">{{oldVersion}}</td>
+ <td class="slx-smallcol">&rarr;</td>
+ <td class="slx-smallcol">{{newVersion}}</td>
+ </tr>
+ {{/task.packages}}
+ </table>
+{{/task.packages.0}}
+
+{{^task.packages}}
+ {{^task.error}}
+ <div class="alert alert-success">
+ <span class="glyphicon glyphicon-ok"></span>
+ {{lang_everythingUpToDate}}
+ </div>
+ {{/task.error}}
+{{/task.packages}}
+
+{{#needReboot}}
+ <div class="alert alert-warning">
+ <span class="glyphicon glyphicon-exclamation-sign"></span>
+ {{lang_packagesNeedingReboot}}:
+ <a href="#id-default_pane">
+ {{.}}
+ </a>
+ </div>
+{{/needReboot}}
+
+{{#task.error}}
+ <div class="alert alert-warning">{{task.error}}</div>
+{{/task.error}}
+
+<div>
+ <a href="https://www.bwlehrpool.de/wiki/doku.php/satellite/system_updates" target="_blank">
+ {{lang_updatesWikiLink}}
+ <span class="glyphicon glyphicon-new-window"></span>
+ </a>
+</div>
+<div class="clearfix"></div> \ No newline at end of file
diff --git a/modules-available/systemstatus/templates/sys-update-update.html b/modules-available/systemstatus/templates/sys-update-update.html
new file mode 100644
index 00000000..7be4e648
--- /dev/null
+++ b/modules-available/systemstatus/templates/sys-update-update.html
@@ -0,0 +1,35 @@
+<div id="apt-output" data-tm-id="{{taskid}}" data-tm-log="output"
+ data-tm-callback="aptUpdate">{{lang_aptOutput}}</div>
+
+<div class="buttonbar pull-right" id="btn-bar">
+ <a id="fail-button" href="?do=systemstatus&amp;rnd={{rnd}}#id-ListUpgradable_pane" class="btn btn-warning collapse">
+ <span class="glyphicon glyphicon-arrow-left"></span>
+ {{lang_backToPackagelist}}
+ </a>
+ <a id="success-button" href="?do=systemstatus&amp;rnd={{rnd}}#id-ListUpgradable_pane" class="btn btn-success
+ collapse">
+ <span class="glyphicon glyphicon-arrow-right"></span>
+ {{lang_showPackageList}}
+ </a>
+</div>
+<div class="clearfix"></div>
+
+<script>
+ function aptUpdate(task) {
+ if (task.statusCode === 'TASK_ERROR') {
+ if (task.data && task.data.error) {
+ $('#apt-output').append($('<pre class="text-danger slx-bold">').text(task.data.error));
+ }
+ $('#fail-button').show();
+ }
+ if (task.statusCode === 'TASK_FINISHED') {
+ $('#success-button').show();
+ }
+ }
+
+ tmInit();
+ $('#btn-bar a').click(function () {
+ window.location.reload();
+ return false;
+ });
+</script> \ No newline at end of file
diff --git a/modules-available/systemstatus/templates/systeminfo.html b/modules-available/systemstatus/templates/systeminfo.html
index cf3f0cc2..2489bcaa 100644
--- a/modules-available/systemstatus/templates/systeminfo.html
+++ b/modules-available/systemstatus/templates/systeminfo.html
@@ -1,6 +1,6 @@
-<div>
- {{lang_uptimeOS}}: {{uptime}}
-</div>
+<div>{{lang_uptimeOS}}: <b>{{uptime}}</b></div>
+<div>{{lang_distribution}}: <b>{{distribution}}</b></div>
+<div>{{lang_kernel}}: <b>{{kernel}}</b></div>
<div class="slx-storechart">
<b>{{lang_cpuLoad}}</b>
@@ -48,73 +48,94 @@
{{/swapWarning}}
<script type="text/javascript">
- {{#cpuLoadOk}}
- var cpuCircle = Circles.create({
- id: 'circles-cpuload',
- radius: 60,
- value: {{{cpuLoad}}},
- maxValue: 100,
- width: 10,
- text: function(value){return value + '%'; },
- colors: ['#dbc', '#33f'],
- duration: 400,
- wrpClass: 'circles-wrp',
- textClass: 'circles-text'
- });
- var $cpu = $(cpuCircle._el);
- var lastCpuTotal = {{CpuTotal}};
- var lastCpuIdle = {{CpuIdle}};
- var lastCpuPercent = {{cpuLoad}};
- {{/cpuLoadOk}}
- {{#memTotal}}
- var memCircle = Circles.create({
- id: 'circles-mem',
- radius: 60,
- value: {{{memPercent}}},
- maxValue: 100,
- width: 10,
- text: function(value){return value + '%'; },
- colors: ['#dbc', '#33f'],
- duration: 400,
- wrpClass: 'circles-wrp',
- textClass: 'circles-text'
- });
- var swapCircle = Circles.create({
- id: 'circles-swap',
- radius: 60,
- value: {{{swapPercent}}},
- maxValue: 100,
- width: 10,
- text: function(value){return value + '%'; },
- colors: ['#dbc', '#f33'],
- duration: 400,
- wrpClass: 'circles-wrp',
- textClass: 'circles-text'
- });
- {{/memTotal}}
- function updateSystem() {
- if (!cpuCircle && !memCircle) return;
- if (!$cpu.is(':visible')) {
- setTimeout(updateSystem, 1200);
- return;
+ (function () {
+ var hiddenProp;
+ if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
+ hiddenProp = "hidden";
+ } else if (typeof document.msHidden !== "undefined") {
+ hiddenProp = "msHidden";
+ } else if (typeof document.webkitHidden !== "undefined") {
+ hiddenProp = "webkitHidden";
+ } else {
+ hiddenProp = null;
}
- $.post('?do=SystemStatus&action=SysPoll', { token: TOKEN }, function(data) {
- if (memCircle && data.MemPercent) memCircle.update(data.MemPercent);
- if (swapCircle && data.SwapPercent) swapCircle.update(data.SwapPercent);
- if (cpuCircle && data.CpuIdle) {
- var total = data.CpuTotal - lastCpuTotal;
- var load = total - (data.CpuIdle - lastCpuIdle);
- var percent = Math.round(100 * load / total);
- cpuCircle.update(percent, Math.abs(percent - lastCpuPercent) < 5 ? 0 : 250);
- lastCpuTotal = data.CpuTotal;
- lastCpuIdle = data.CpuIdle;
- lastCpuPercent = percent;
+
+ {{#cpuLoadOk}}
+ var cpuCircle = Circles.create({
+ id: 'circles-cpuload',
+ radius: 60,
+ value: {{{cpuLoad}}},
+ maxValue: 100,
+ width: 10,
+ text: function (value) {
+ return value + '%';
+ },
+ colors: ['#dbc', '#33f'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ var $cpu = $(cpuCircle._el);
+ var lastCpuTotal = {{CpuTotal}};
+ var lastCpuIdle = {{CpuIdle}};
+ var lastCpuPercent = {{cpuLoad}};
+ {{/cpuLoadOk}}
+ {{#memTotal}}
+ var memCircle = Circles.create({
+ id: 'circles-mem',
+ radius: 60,
+ value: {{{memPercent}}},
+ maxValue: 100,
+ width: 10,
+ text: function (value) {
+ return value + '%';
+ },
+ colors: ['#dbc', '#33f'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ var swapCircle = Circles.create({
+ id: 'circles-swap',
+ radius: 60,
+ value: {{{swapPercent}}},
+ maxValue: 100,
+ width: 10,
+ text: function (value) {
+ return value + '%';
+ },
+ colors: ['#dbc', '#f33'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ {{/memTotal}}
+
+ function updateSystem() {
+ if (!cpuCircle && !memCircle) return;
+ if (!$cpu.is(':visible') || (hiddenProp && document[hiddenProp])) {
+ setTimeout(updateSystem, 2500);
+ return;
}
- }, 'json').fail(function(data) {
- console.log(data);
- }).always(function() {
- setTimeout(updateSystem, 1200);
- });
- }
- setTimeout(updateSystem, 1000);
+ $.post('?do=SystemStatus&action=SysPoll', {token: TOKEN}, function (data) {
+ if (memCircle && data.MemPercent) memCircle.update(data.MemPercent);
+ if (swapCircle && data.SwapPercent) swapCircle.update(data.SwapPercent);
+ if (cpuCircle && data.CpuIdle) {
+ var total = data.CpuTotal - lastCpuTotal;
+ var load = total - (data.CpuIdle - lastCpuIdle);
+ var percent = Math.round(100 * load / total);
+ cpuCircle.update(percent, Math.abs(percent - lastCpuPercent) < 5 ? 0 : 250);
+ lastCpuTotal = data.CpuTotal;
+ lastCpuIdle = data.CpuIdle;
+ lastCpuPercent = percent;
+ }
+ }, 'json').fail(function (data) {
+ console.log(data);
+ }).always(function () {
+ setTimeout(updateSystem, 1200);
+ });
+ }
+
+ setTimeout(updateSystem, 1000);
+ })();
</script>