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.php27
-rw-r--r--modules-available/systemstatus/inc/systemstatus.inc.php160
-rw-r--r--modules-available/systemstatus/lang/de/messages.json5
-rw-r--r--modules-available/systemstatus/lang/de/module.json3
-rw-r--r--modules-available/systemstatus/lang/de/permissions.json9
-rw-r--r--modules-available/systemstatus/lang/de/template-tags.json26
-rw-r--r--modules-available/systemstatus/lang/en/messages.json5
-rw-r--r--modules-available/systemstatus/lang/en/module.json3
-rw-r--r--modules-available/systemstatus/lang/en/permissions.json9
-rw-r--r--modules-available/systemstatus/lang/en/template-tags.json42
-rw-r--r--modules-available/systemstatus/page.inc.php493
-rw-r--r--modules-available/systemstatus/permissions/permissions.json27
-rw-r--r--modules-available/systemstatus/templates/_page.html67
-rw-r--r--modules-available/systemstatus/templates/ajax-journal.html20
-rw-r--r--modules-available/systemstatus/templates/ajax-reboot.html14
-rw-r--r--modules-available/systemstatus/templates/diskstat.html2
-rw-r--r--modules-available/systemstatus/templates/services.html32
-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.html158
21 files changed, 935 insertions, 326 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 406ae73c..6b0ac981 100644
--- a/modules-available/systemstatus/hooks/main-warning.inc.php
+++ b/modules-available/systemstatus/hooks/main-warning.inc.php
@@ -1,7 +1,26 @@
<?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)) {
+ if ($current === $wanted && isset($storeUsage['freeKb']) && $storeUsage['freeKb'] < 60000000) { // 60GB
+ Message::addWarning('systemstatus.storage-low-vmstore', true, Util::readableFileSize($storeUsage['freeKb'], -1 , 1));
+ }
+ if (isset($systemUsage['freeKb']) && $systemUsage['freeKb'] < 600000) { // 600MB
+ Message::addWarning('systemstatus.storage-low-system', true, Util::readableFileSize($systemUsage['freeKb'], -1 , 1));
+ }
} \ No newline at end of file
diff --git a/modules-available/systemstatus/inc/systemstatus.inc.php b/modules-available/systemstatus/inc/systemstatus.inc.php
new file mode 100644
index 00000000..c50e0ef6
--- /dev/null
+++ b/modules-available/systemstatus/inc/systemstatus.inc.php
@@ -0,0 +1,160 @@
+<?php
+
+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,
+ * usedPercent, sizeKb, freeKb.
+ * @param array|false $systemUsage
+ * @param array|false $storeUsage
+ * @param string|false $currentSource What's currently mounted as vmstore
+ * @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): bool
+ {
+ $task = Taskmanager::submit('DiskStat');
+ if ($task === false)
+ return false;
+ $task = Taskmanager::waitComplete($task, 3000);
+
+ if (empty($task['data']['list']))
+ return false;
+ $wantedSource = Property::getVmStoreUrl();
+ $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 actual directory of the vmstore, or / if we use internal storage
+ if ($entry['mountPoint'] === $storePoint) {
+ $storeUsage = $entry;
+ }
+ // Always report free space on system disk
+ if ($entry['mountPoint'] === '/') {
+ $systemUsage = $entry;
+ }
+ // Record what's mounted at destination, regardless of config, to indicate something is wrong
+ 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 1a6df1b3..551e937a 100644
--- a/modules-available/systemstatus/lang/de/messages.json
+++ b/modules-available/systemstatus/lang/de/messages.json
@@ -1,4 +1,7 @@
{
- "reboot-unconfirmed": "Sicherheitsabfrage zum Reboot nicht best\u00e4tigt",
+ "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}}"
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/de/module.json b/modules-available/systemstatus/lang/de/module.json
index dd1a115c..3b310b1d 100644
--- a/modules-available/systemstatus/lang/de/module.json
+++ b/modules-available/systemstatus/lang/de/module.json
@@ -1,8 +1,11 @@
{
"module_name": "System-Status",
+ "page_title": "Systemstatus des Servers",
"tab_DmsdLog": "bwLehrpool-Suite Server Log",
+ "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 a3041fbc..f2dd9a21 100644
--- a/modules-available/systemstatus/lang/de/permissions.json
+++ b/modules-available/systemstatus/lang/de/permissions.json
@@ -1,4 +1,11 @@
{
+ "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.",
"serverreboot": "Server neustarten.",
"show.overview.addresses": "Zeige Adresskonfiguration auf \u00dcbersichtsseite.",
"show.overview.diskstat": "Zeige Speicherplatzwerte auf \u00dcbersichtsseite.",
@@ -6,8 +13,10 @@
"show.overview.services": "Zeige Dienste auf \u00dcbersichtsseite.",
"show.overview.systeminfo": "Zeige Systemwerte auf \u00dcbersichtsseite.",
"tab.dmsdlog": "Zugriff auf bwLehrpool-Suite-Server Statusausgabe.",
+ "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 eeb75f9a..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_downloads": "Downloads",
+ "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,9 +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!",
@@ -31,10 +51,10 @@
"lang_systemPartition": "Systempartition",
"lang_systemStoreError": "Fehler beim Ermitteln des verf\u00fcgbaren Systemspeichers",
"lang_total": "Gesamt",
- "lang_unknownState": "Unbekannter Status",
"lang_updatedPackages": "Ausstehende Updates",
- "lang_uploads": "Uploads",
+ "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 5098eb76..2afc3431 100644
--- a/modules-available/systemstatus/lang/en/messages.json
+++ b/modules-available/systemstatus/lang/en/messages.json
@@ -1,4 +1,7 @@
{
- "reboot-unconfirmed": "Confirmation prompt to reboot not confirmed",
+ "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}}"
} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/module.json b/modules-available/systemstatus/lang/en/module.json
index 9f6d937a..cc2b5283 100644
--- a/modules-available/systemstatus/lang/en/module.json
+++ b/modules-available/systemstatus/lang/en/module.json
@@ -1,8 +1,11 @@
{
"module_name": "System Status",
+ "page_title": "System status of server",
"tab_DmsdLog": "bwLehrpool-Suite log",
+ "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 879fa882..21e7538f 100644
--- a/modules-available/systemstatus/lang/en/permissions.json
+++ b/modules-available/systemstatus/lang/en/permissions.json
@@ -1,4 +1,11 @@
{
+ "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.",
"serverreboot": "Reboot server.",
"show.overview.addresses": "Show addresses on overview page.",
"show.overview.diskstat": "Show diskstats on overview page.",
@@ -6,8 +13,10 @@
"show.overview.services": "Show services on overview page.",
"show.overview.systeminfo": "Show systeminfo on overview page.",
"tab.dmsdlog": "Show bwLehrpool-Suite status.",
+ "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 5f6ad898..7758c71c 100644
--- a/modules-available/systemstatus/lang/en/template-tags.json
+++ b/modules-available/systemstatus/lang/en/template-tags.json
@@ -1,40 +1,60 @@
{
"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_downloads": "Downloads",
+ "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_logicCPUs": "Logic CPUs",
+ "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",
"lang_notDetermined": "Could not be determined",
- "lang_occupied": "Occupied",
- "lang_onlyOS": "OS Only",
+ "lang_occupied": "In use",
+ "lang_onlyOS": "OS only",
"lang_overview": "Overview",
- "lang_ramUsage": "RAM Usage",
+ "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!",
- "lang_swapUsage": "swap Usage",
+ "lang_swapUsage": "swap usage",
"lang_swapWarning": "Memory swap is being used. This may be an indication that the satellite server does not have enough physical memory available. In the case of performance problems or server instability you should consider equipping the server with more RAM.",
"lang_system": "System",
- "lang_systemPartition": "System Partition",
+ "lang_systemPartition": "System partition",
"lang_systemStoreError": "Error querying available system storage",
"lang_total": "Total",
- "lang_unknownState": "Unknown status",
"lang_updatedPackages": "Pending updates",
- "lang_uploads": "Uploads",
- "lang_uptimeOS": "OS Uptime",
- "lang_vmStore": "VM Store",
+ "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 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);
}
diff --git a/modules-available/systemstatus/permissions/permissions.json b/modules-available/systemstatus/permissions/permissions.json
index 29e26b5e..0be0a8c5 100644
--- a/modules-available/systemstatus/permissions/permissions.json
+++ b/modules-available/systemstatus/permissions/permissions.json
@@ -5,6 +5,9 @@
"tab.dmsdlog": {
"location-aware": false
},
+ "tab.dnbd3log": {
+ "location-aware": false
+ },
"tab.netstat": {
"location-aware": false
},
@@ -17,6 +20,9 @@
"tab.lighttpdlog": {
"location-aware": false
},
+ "tab.listupgradable": {
+ "location-aware": false
+ },
"show.overview.addresses": {
"location-aware": false
},
@@ -31,5 +37,26 @@
},
"show.overview.systeminfo": {
"location-aware": false
+ },
+ "restart.dnbd3-server": {
+ "location-aware": false
+ },
+ "restart.ldadp": {
+ "location-aware": false
+ },
+ "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 3d0f9dfb..dedcf01a 100644
--- a/modules-available/systemstatus/templates/_page.html
+++ b/modules-available/systemstatus/templates/_page.html
@@ -1,12 +1,12 @@
<h1>{{lang_moduleHeading}}</h1>
-{{#rebootTask}}
-<div data-tm-id="{{rebootTask}}" data-tm-log="messages">Reboot...</div>
-{{/rebootTask}}
+{{#taskid}}
+<div data-tm-id="{{taskid}}" data-tm-log="messages">{{taskname}}</div>
+{{/taskid}}
<ul class="nav nav-tabs tabs-up">
<li class="active">
- <a href="#id-default_pane" id="id-default" class="active" data-toggle="tab" role="tab">
+ <a href="#id-default_pane" id="id-default" class="ajax-tab" data-toggle="tab" role="tab">
{{lang_overview}}
</a>
</li>
@@ -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>
@@ -100,7 +106,16 @@
</button>
<div class="hidden" id="confirm-reboot">{{lang_areYouSureReboot}}</div>
</form>
- <div id="dmsd-users"></div>
+ <div id="dmsd-users">
+ {{lang_runningUploads}}: <span class="uploads">??</span>,
+ {{lang_runningDownloads}}: <span class="downloads">??</span>
+ <div class="alert alert-warning collapse">{{lang_dmsdUnreachable}}</div>
+ </div>
+ <div>
+ {{#packages}}
+ {{lang_updatedPackages}}: {{packages}}
+ {{/packages}}
+ </div>
</div>
</div>
</div>
@@ -119,20 +134,48 @@
<script type="text/javascript"><!--
document.addEventListener("DOMContentLoaded", function() {
- $('#diskstat').load('?do=SystemStatus&action=DiskStat');
- $('#addresses').load('?do=SystemStatus&action=AddressList');
- $('#systeminfo').load('?do=SystemStatus&action=SystemInfo');
- $('#services').load('?do=SystemStatus&action=Services');
- $('#dmsd-users').load('?do=SystemStatus&action=DmsdUsers');
var slxDone = {};
- $('.ajax-tab').on('shown.bs.tab', function (e) {
+ var loadTab = function (e) {
var $this = $(this);
var w = $this.attr('id');
if (!slxDone[w]) {
slxDone[w] = true;
var $pane = $('#' + w + '_pane');
- $pane.load('?do=SystemStatus&action=' + w.substring(3));
+ var tab = w.substring(3);
+ if (tab === 'default') {
+ $('#diskstat').load('?do=SystemStatus&action=DiskStat');
+ $('#addresses').load('?do=SystemStatus&action=AddressList');
+ $('#systeminfo').load('?do=SystemStatus&action=SystemInfo');
+ $('#services').load('?do=SystemStatus&action=Services');
+ } else {
+ $pane.load('?do=SystemStatus&action=' + tab, function() {
+ $(this).find('button[data-confirm]').click(slxModalConfirmHandler);
+ });
+ }
}
+ };
+ $('.ajax-tab').on('shown.bs.tab', loadTab);
+ // Need a better solution for this -- there is already code handling tabs in slx-fixes, maybe put this in there?
+ if (location.hash === '' || location.hash === '#' || location.hash === '#id-default_pane') {
+ history.replaceState(null, null, '#id-default_pane');
+ loadTab.call($('#id-default'));
+ }
+ var $dmsd = $('#dmsd-users');
+ $.ajax({
+ url: '?do=dozmod&section=special&action=dmsd-status',
+ timeout: 3000,
+ dataType: 'json'
+ }).done(function (data) {
+ if (!data || data.error) {
+ $dmsd.find('.alert').show();
+ } else {
+ if (data.downloads !== null) $dmsd.find('.downloads').text(data.downloads);
+ if (data.uploads !== null) $dmsd.find('.uploads').text(data.uploads);
+ }
+ }).fail(function () {
+ $dmsd.find('.alert').show();
});
}, false);
//--></script>
+
+<div class="hidden" id="confirm-restart">{{lang_confirmRestart}}</div> \ No newline at end of file
diff --git a/modules-available/systemstatus/templates/ajax-journal.html b/modules-available/systemstatus/templates/ajax-journal.html
new file mode 100644
index 00000000..5b476d9c
--- /dev/null
+++ b/modules-available/systemstatus/templates/ajax-journal.html
@@ -0,0 +1,20 @@
+<form method="post" action="?do=systemstatus">
+ <input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" value="service-restart">
+ {{#modules}}
+ <div class="slx-space">
+ <div class="pull-right">
+ <button class="btn btn-warning btn-sm pull-right" name="service" value="{{service}}"
+ data-confirm="#confirm-restart" {{restart_disabled}}>
+ <span class="glyphicon glyphicon-refresh"></span>
+ {{lang_restart}}
+ </button>
+ </div>
+ <h4>{{name}}</h4>
+ <div data-tm-id="{{task.id}}" data-tm-log="messages">{{service}}</div>
+ </div>
+ {{/modules}}
+</form>
+<script>
+ tmInit();
+</script> \ No newline at end of file
diff --git a/modules-available/systemstatus/templates/ajax-reboot.html b/modules-available/systemstatus/templates/ajax-reboot.html
deleted file mode 100644
index a1aaf1e6..00000000
--- a/modules-available/systemstatus/templates/ajax-reboot.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<div>
- {{^dmsd_error}}
- {{lang_uploads}}: {{uploads}},
- {{lang_downloads}}: {{downloads}}
- {{/dmsd_error}}
- {{#dmsd_error}}
- <div class="alert alert-warning">{{lang_dmsdUnreachable}}</div>
- {{/dmsd_error}}
-</div>
-<div>
- {{#packages}}
- {{lang_updatedPackages}}: {{packages}}
- {{/packages}}
-</div> \ No newline at end of file
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/services.html b/modules-available/systemstatus/templates/services.html
index 29b33687..2614fca9 100644
--- a/modules-available/systemstatus/templates/services.html
+++ b/modules-available/systemstatus/templates/services.html
@@ -1,20 +1,20 @@
+<form method="post" action="?do=systemstatus">
+ <input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" value="service-start">
+ <table class="table">
{{#services}}
- {{#unknown}}
- <div class="alert alert-warning">
- {{name}}: {{lang_unknownState}}
- </div>
- {{/unknown}}
- {{^unknown}}
+ <tr class="bg-{{#fail}}danger{{/fail}}{{^fail}}success{{/fail}}">
+ <td>
{{#fail}}
- <div class="alert alert-danger">
- {{name}}: <b>{{lang_failure}}</b>
- {{#data.messages}}<pre>{{data.messages}}</pre>{{/data.messages}}
- </div>
+ <button class="btn btn-default btn-xs pull-right" name="service" value="{{service}}">
+ {{lang_restart}}
+ </button>
{{/fail}}
- {{^fail}}
- <div class="alert alert-success">
- {{name}}: {{lang_OK}}
- </div>
- {{/fail}}
- {{/unknown}}
+ {{name}}: {{#fail}}{{lang_failure}}{{/fail}}{{^fail}}{{lang_OK}}{{/fail}}
+ <div class="clearfix"></div>
+ {{#error}}<pre>{{error}}</pre>{{/error}}
+ </td>
+ </tr>
{{/services}}
+ </table>
+</form> \ No newline at end of file
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 ed4a1532..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,68 +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 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;
- $.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;
+ (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;
+ }
+
+ {{#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>