summaryrefslogtreecommitdiffstats
path: root/modules-available/systemstatus
diff options
context:
space:
mode:
authorSimon Rettberg2016-05-03 19:03:09 +0200
committerSimon Rettberg2016-05-03 19:03:09 +0200
commit50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66 (patch)
tree05e99fdffa696434960d7c77966c0bc36d6339e8 /modules-available/systemstatus
parentSecond half of merge.... (diff)
downloadslx-admin-50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66.tar.gz
slx-admin-50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66.tar.xz
slx-admin-50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66.zip
WIP
Diffstat (limited to 'modules-available/systemstatus')
-rw-r--r--modules-available/systemstatus/config.json4
-rw-r--r--modules-available/systemstatus/lang/de/templates/_page.json11
-rw-r--r--modules-available/systemstatus/lang/de/templates/addresses.json1
-rw-r--r--modules-available/systemstatus/lang/de/templates/diskstat.json12
-rw-r--r--modules-available/systemstatus/lang/de/templates/services.json1
-rw-r--r--modules-available/systemstatus/lang/de/templates/systeminfo.json15
-rw-r--r--modules-available/systemstatus/lang/en/module.json3
-rw-r--r--modules-available/systemstatus/lang/en/templates/_page.json11
-rw-r--r--modules-available/systemstatus/lang/en/templates/addresses.json2
-rw-r--r--modules-available/systemstatus/lang/en/templates/diskstat.json12
-rw-r--r--modules-available/systemstatus/lang/en/templates/services.json2
-rw-r--r--modules-available/systemstatus/lang/en/templates/systeminfo.json15
-rw-r--r--modules-available/systemstatus/lang/pt/module.json26
-rw-r--r--modules-available/systemstatus/page.inc.php361
-rw-r--r--modules-available/systemstatus/templates/_page.html129
-rw-r--r--modules-available/systemstatus/templates/addresses.html8
-rw-r--r--modules-available/systemstatus/templates/diskstat.html63
-rw-r--r--modules-available/systemstatus/templates/services.html6
-rw-r--r--modules-available/systemstatus/templates/systeminfo.html115
19 files changed, 797 insertions, 0 deletions
diff --git a/modules-available/systemstatus/config.json b/modules-available/systemstatus/config.json
new file mode 100644
index 00000000..650ab2fe
--- /dev/null
+++ b/modules-available/systemstatus/config.json
@@ -0,0 +1,4 @@
+{
+ "category":"main.status",
+ "enabled":"true"
+}
diff --git a/modules-available/systemstatus/lang/de/templates/_page.json b/modules-available/systemstatus/lang/de/templates/_page.json
new file mode 100644
index 00000000..9c97961a
--- /dev/null
+++ b/modules-available/systemstatus/lang/de/templates/_page.json
@@ -0,0 +1,11 @@
+{
+ "lang_addressConfiguration": "Adresskonfiguration",
+ "lang_advanced": "Erweitert \/ Debug",
+ "lang_dmsdLog": "dmsd Log",
+ "lang_iAmSure": "Ja, ich bin sicher",
+ "lang_ldadpLog": "AD\/LDAP-Proxy Log",
+ "lang_maintenance": "Maintenance",
+ "lang_services": "Dienste",
+ "lang_space": "Speicherplatz",
+ "lang_system": "System"
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/de/templates/addresses.json b/modules-available/systemstatus/lang/de/templates/addresses.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/modules-available/systemstatus/lang/de/templates/addresses.json
@@ -0,0 +1 @@
+{}
diff --git a/modules-available/systemstatus/lang/de/templates/diskstat.json b/modules-available/systemstatus/lang/de/templates/diskstat.json
new file mode 100644
index 00000000..c44433ea
--- /dev/null
+++ b/modules-available/systemstatus/lang/de/templates/diskstat.json
@@ -0,0 +1,12 @@
+{
+ "lang_capacity": "Kapazit\u00e4t",
+ "lang_foundStore": "Vorgefunden:",
+ "lang_free": "Frei",
+ "lang_goToStoreConf": "Zur VM-Store-Konfiguration wechseln",
+ "lang_storeMissingExpected": "VM-Store nicht eingebunden. Erwartet:",
+ "lang_storeNotConfigured": "Kein VM-Store konfiguriert!",
+ "lang_systemPartition": "Systempartition",
+ "lang_systemStoreError": "Fehler beim Ermitteln des verf\u00fcgbaren Systemspeichers",
+ "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/de/templates/services.json b/modules-available/systemstatus/lang/de/templates/services.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/modules-available/systemstatus/lang/de/templates/services.json
@@ -0,0 +1 @@
+{}
diff --git a/modules-available/systemstatus/lang/de/templates/systeminfo.json b/modules-available/systemstatus/lang/de/templates/systeminfo.json
new file mode 100644
index 00000000..cd4027f1
--- /dev/null
+++ b/modules-available/systemstatus/lang/de/templates/systeminfo.json
@@ -0,0 +1,15 @@
+{
+ "lang_attention": "Achtung!",
+ "lang_average": "Durchschnitt",
+ "lang_cpuLoad": "CPU-Last",
+ "lang_free": "Frei",
+ "lang_logicCPUs": "Logische CPUs",
+ "lang_notDetermined": "Konnte nicht ermittelt werden",
+ "lang_occupied": "Belegt",
+ "lang_onlyOS": "Nur OS",
+ "lang_ramUsage": "RAM-Nutzung",
+ "lang_swapUsage": "swap-Nutzung",
+ "lang_swapWarning": "Es wird swap-Speicher genutzt. Dies kann ein Hinweis darauf sein, dass dem Satelliten-Server zu wenig physikalischer Speicher zur Verf\u00fcgung steht. Im Falle von Performance-Problemen oder Instabilit\u00e4t des Servers sollten Sie erw\u00e4gen, den Server mit mehr RAM auszustatten.",
+ "lang_total": "Gesamt",
+ "lang_uptimeOS": "OS Uptime"
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/module.json b/modules-available/systemstatus/lang/en/module.json
new file mode 100644
index 00000000..126d6bb8
--- /dev/null
+++ b/modules-available/systemstatus/lang/en/module.json
@@ -0,0 +1,3 @@
+{
+ "module_name": "Server"
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/templates/_page.json b/modules-available/systemstatus/lang/en/templates/_page.json
new file mode 100644
index 00000000..f698521d
--- /dev/null
+++ b/modules-available/systemstatus/lang/en/templates/_page.json
@@ -0,0 +1,11 @@
+{
+ "lang_addressConfiguration": "Address Configuration",
+ "lang_advanced": "Advanced \/ Debug",
+ "lang_dmsdLog": "dmsd log",
+ "lang_iAmSure": "Yes, I am sure",
+ "lang_ldadpLog": "AD\/LDAP proxy log",
+ "lang_maintenance": "Maintenance",
+ "lang_services": "Services",
+ "lang_space": "Space",
+ "lang_system": "System"
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/en/templates/addresses.json b/modules-available/systemstatus/lang/en/templates/addresses.json
new file mode 100644
index 00000000..2c63c085
--- /dev/null
+++ b/modules-available/systemstatus/lang/en/templates/addresses.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/modules-available/systemstatus/lang/en/templates/diskstat.json b/modules-available/systemstatus/lang/en/templates/diskstat.json
new file mode 100644
index 00000000..6c880ebe
--- /dev/null
+++ b/modules-available/systemstatus/lang/en/templates/diskstat.json
@@ -0,0 +1,12 @@
+{
+ "lang_capacity": "Capacity",
+ "lang_foundStore": "Found:",
+ "lang_free": "Free",
+ "lang_goToStoreConf": "Go to VM store configuration",
+ "lang_storeMissingExpected": "VM store not mounted. Expected:",
+ "lang_storeNotConfigured": "No VM store configured!",
+ "lang_systemPartition": "System Partition",
+ "lang_systemStoreError": "Error querying available system storage",
+ "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/lang/en/templates/services.json b/modules-available/systemstatus/lang/en/templates/services.json
new file mode 100644
index 00000000..2c63c085
--- /dev/null
+++ b/modules-available/systemstatus/lang/en/templates/services.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/modules-available/systemstatus/lang/en/templates/systeminfo.json b/modules-available/systemstatus/lang/en/templates/systeminfo.json
new file mode 100644
index 00000000..602693f5
--- /dev/null
+++ b/modules-available/systemstatus/lang/en/templates/systeminfo.json
@@ -0,0 +1,15 @@
+{
+ "lang_attention": "Attention!",
+ "lang_average": "Average",
+ "lang_cpuLoad": "CPU Load",
+ "lang_free": "Free",
+ "lang_logicCPUs": "Logic CPUs",
+ "lang_notDetermined": "Could not be determined",
+ "lang_occupied": "Occupied",
+ "lang_onlyOS": "OS Only",
+ "lang_ramUsage": "RAM 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_total": "Total",
+ "lang_uptimeOS": "OS Uptime"
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/lang/pt/module.json b/modules-available/systemstatus/lang/pt/module.json
new file mode 100644
index 00000000..c191bcfd
--- /dev/null
+++ b/modules-available/systemstatus/lang/pt/module.json
@@ -0,0 +1,26 @@
+{
+ "lang_addressConfiguration": "Configura\u00e7\u00e3o do Endere\u00e7o",
+ "lang_attention": "Aten\u00e7\u00e3o!",
+ "lang_average": "M\u00e9dia",
+ "lang_capacity": "Capacidade",
+ "lang_cpuLoad": "Carga da CPU",
+ "lang_free": "Livre",
+ "lang_iAmSure": "Sim, eu tenho certeza",
+ "lang_logicCPUs": "CPUs L\u00f3gicas",
+ "lang_maintenance": "Manuten\u00e7\u00e3o",
+ "lang_notDetermined": "N\u00e3o foi poss\u00edvel determinar",
+ "lang_occupied": "Ocupado",
+ "lang_onlyOS": "Apenas SO",
+ "lang_ramUsage": "Uso da RAM",
+ "lang_services": "Servi\u00e7os",
+ "lang_space": "Espa\u00e7o",
+ "lang_swapUsage": "Uso do swap",
+ "lang_swapWarning": "Swap de mem\u00f3ria est\u00e1 sendo usado. Isso pode ser uma indica\u00e7\u00e3o de que o servidor de sat\u00e9lite n\u00e3o tem mem\u00f3ria f\u00edsica suficiente dispon\u00edvel. No caso de problemas de desempenho ou instabilidade do servidor voc\u00ea deve considerar equipar o servidor com mais mem\u00f3ria RAM.",
+ "lang_system": "Sistema",
+ "lang_systemPartition": "Parti\u00e7\u00e3o do Sistema",
+ "lang_total": "Total",
+ "lang_uptimeOS": "Tempo de Atividade do SO",
+ "lang_vmStore": "Armazenamento da VM",
+ "lang_vmStoreError": "Erro ao determinar o espa\u00e7o em disco dispon\u00edvel no local da VM. Por favor, verifique a configura\u00e7\u00e3o.",
+ "module_name": "Servidor"
+} \ No newline at end of file
diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php
new file mode 100644
index 00000000..2a5382e1
--- /dev/null
+++ b/modules-available/systemstatus/page.inc.php
@@ -0,0 +1,361 @@
+<?php
+
+class Page_SystemStatus extends Page
+{
+
+ private $rebootTask = false;
+
+ protected function doPreprocess()
+ {
+ User::load();
+
+ if (!User::isLoggedIn()) {
+ Message::addError('no-permission');
+ Util::redirect('?do=Main');
+ }
+
+ if (Request::post('action') === 'reboot') {
+ if (Request::post('confirm') !== 'yep') {
+ Message::addError('reboot-unconfirmed');
+ Util::redirect('?do=SystemStatus');
+ }
+ $this->rebootTask = Taskmanager::submit('Reboot');
+ }
+ }
+
+ protected function doRender()
+ {
+ $data = array();
+ if (is_array($this->rebootTask) && isset($this->rebootTask['id'])) {
+ $data['rebootTask'] = $this->rebootTask['id'];
+ }
+ Render::addScriptTop('custom');
+ Render::addScriptBottom('circles.min');
+ Render::addTemplate('_page', $data);
+ }
+
+ protected function doAjax()
+ {
+ User::load();
+
+ if (!User::isLoggedIn())
+ return;
+
+ $action = 'ajax' . Request::any('action');
+ if (method_exists($this, $action)) {
+ $this->$action();
+ Message::renderList();
+ } else {
+ echo "Action $action not known in " . get_class();
+ }
+ }
+
+ protected function ajaxDmsdUsers()
+ {
+ $ret = Download::asStringPost('http://127.0.0.1:9080/status/fileserver', false, 2, $code);
+ if ($code != 200) {
+ Header('HTTP/1.1 502 Internal Server Error');
+ die('Internal Server Wurst');
+ }
+ $data = @json_decode($ret, true);
+ if (is_array($data)) {
+ $ret = 'Uploads: ' . $data['activeUploads'] . ', Downloads: ' . $data['activeDownloads'];
+ } else {
+ $ret = '???';
+ }
+ die($ret);
+ }
+
+ protected function ajaxDiskStat()
+ {
+ $task = Taskmanager::submit('DiskStat');
+ if ($task === false)
+ 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['notConfigured'] = true;
+ }
+ echo Render::parse('diskstat', $data);
+ }
+
+ protected function ajaxAddressList()
+ {
+ $task = Taskmanager::submit('LocalAddressesList');
+ if ($task === false)
+ return;
+ $task = Taskmanager::waitComplete($task, 3000);
+
+ if (!isset($task['data']['addresses']) || empty($task['data']['addresses'])) {
+ Taskmanager::addErrorMessage($task);
+ return;
+ }
+
+ $sort = array();
+ $primary = Property::getServerIp();
+ foreach ($task['data']['addresses'] as &$addr) {
+ $sort[] = $addr['type'] . $addr['ip'];
+ if ($addr['ip'] === $primary)
+ $addr['primary'] = true;
+ }
+ array_multisort($sort, SORT_STRING, $task['data']['addresses']);
+ echo Render::parse('addresses', array(
+ 'addresses' => $task['data']['addresses']
+ ));
+ }
+
+ private function sysInfo()
+ {
+ $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);
+ foreach ($out as $e) {
+ $data[$e[1]] = $e[2];
+ }
+ 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'];
+ $data['CpuSystem'] = $out['irq'] + $out['softirq'];
+ }
+ return $data;
+ }
+
+ protected function ajaxSystemInfo()
+ {
+ $cpuInfo = file_get_contents('/proc/cpuinfo');
+ $uptime = file_get_contents('/proc/uptime');
+ $cpuCount = preg_match_all('/\bprocessor\s/', $cpuInfo, $out);
+ //$cpuCount = count($out);
+ $data = array(
+ 'cpuCount' => $cpuCount,
+ 'memTotal' => '???',
+ 'memFree' => '???',
+ 'swapTotal' => '???',
+ 'swapUsed' => '???',
+ 'uptime' => '???'
+ );
+ 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'); // TODO: i18n
+ }
+ $info = $this->sysInfo();
+ if (isset($info['MemTotal']) && isset($info['MemFree']) && isset($info['SwapTotal'])) {
+ $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['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['SwapTotal'] - $info['SwapFree']) > 200000);
+ }
+ if (isset($info['CpuIdle']) && isset($info['CpuSystem']) && isset($info['CpuTotal'])) {
+ $data['cpuLoad'] = 100 - round(($info['CpuIdle'] / $info['CpuTotal']) * 100);
+ $data['cpuSystem'] = round(($info['CpuSystem'] / $info['CpuTotal']) * 100);
+ $data['cpuLoadOk'] = true;
+ $data['CpuTotal'] = $info['CpuTotal'];
+ $data['CpuIdle'] = $info['CpuIdle'];
+ }
+ echo Render::parse('systeminfo', $data);
+ }
+
+ protected function ajaxSysPoll()
+ {
+ $info = $this->sysInfo();
+ $data = array(
+ 'CpuTotal' => $info['CpuTotal'],
+ 'CpuIdle' => $info['CpuIdle'],
+ 'MemPercent' => 100 - round((($info['MemFree'] + $info['Buffers'] + $info['Cached']) / $info['MemTotal']) * 100),
+ 'SwapPercent' => 100 - round(($info['SwapFree'] / $info['SwapTotal']) * 100)
+ );
+ Header('Content-Type: application/json; charset=utf-8');
+ die(json_encode($data));
+ }
+
+ protected function ajaxServices()
+ {
+ $data = array();
+
+ $taskId = Trigger::ldadp();
+ if ($taskId === false)
+ return;
+ $status = Taskmanager::waitComplete($taskId, 10000);
+
+ if (Taskmanager::isFailed($status)) {
+ if (isset($status['data']['messages']))
+ $data['ldadpError'] = $status['data']['messages'];
+ else
+ $data['ldadpError'] = 'Taskmanager error';
+ }
+ // TODO: Dozentenmodul, tftp, ...
+
+ echo Render::parse('services', $data);
+ }
+
+ protected function ajaxDmsdLog()
+ {
+ $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;
+ }
+ // 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);
+ }
+ }
+ if (strlen($data) < 5990) {
+ $start = 0;
+ } else {
+ $start = strpos($data, "\n") + 1;
+ }
+ echo '<pre>', htmlspecialchars(substr($data, $start)), '</pre>';
+ }
+
+ protected function ajaxLdadpLog()
+ {
+ $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 = ConfigModule::get($out[1]);
+ 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;
+ } else {
+ $start = strpos($data, "\n") + 1;
+ }
+ echo '<pre>', htmlspecialchars(substr($data, $start)), '</pre>';
+ }
+ }
+
+ protected function ajaxNetstat()
+ {
+ $taskId = Taskmanager::submit('Netstat');
+ if ($taskId === false)
+ return;
+ $status = Taskmanager::waitComplete($taskId, 3500);
+
+ if (isset($status['data']['messages']))
+ $data = $status['data']['messages'];
+ else
+ $data = 'Taskmanager error';
+
+ echo '<pre>', htmlspecialchars($data), '</pre>';
+ }
+
+ protected function ajaxPsList()
+ {
+ $taskId = Taskmanager::submit('PsList');
+ if ($taskId === false)
+ return;
+ $status = Taskmanager::waitComplete($taskId, 3500);
+
+ if (isset($status['data']['messages']))
+ $data = $status['data']['messages'];
+ else
+ $data = 'Taskmanager error';
+
+ echo '<pre>', htmlspecialchars($data), '</pre>';
+ }
+
+ private function usageColor($percent)
+ {
+ if ($percent <= 50) {
+ $r = $b = $percent / 3;
+ $g = (100 - $percent * (50 / 80));
+ } elseif ($percent <= 70) {
+ $r = 55 + ($percent - 50) * (30 / 20);
+ $g = 60;
+ $b = 0;
+ } else {
+ $r = ($percent - 70) / 3 + 90;
+ $g = (100 - $percent) * (60 / 30);
+ $b = 0;
+ }
+ $r = dechex(round($r * 2.55));
+ $g = dechex(round($g * 2.55));
+ $b = dechex(round($b * 2.55));
+ return sprintf("%02s%02s%02s", $r, $g, $b);
+ }
+
+}
diff --git a/modules-available/systemstatus/templates/_page.html b/modules-available/systemstatus/templates/_page.html
new file mode 100644
index 00000000..51aa5b55
--- /dev/null
+++ b/modules-available/systemstatus/templates/_page.html
@@ -0,0 +1,129 @@
+{{#rebootTask}}
+<div data-tm-id="{{rebootTask}}" data-tm-log="messages">Reboot...</div>
+{{/rebootTask}}
+
+<div class="row">
+
+ <div class="col-sm-6">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_space}}
+ </div>
+ <div class="panel-body" id="diskstat">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-sm-6">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_services}}
+ </div>
+ <div class="panel-body" id="services">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+ </div>
+ </div>
+
+</div>
+
+
+<div class="row">
+
+ <div class="col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_addressConfiguration}}
+ </div>
+ <div class="panel-body" id="addresses">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_system}}
+ </div>
+ <div class="panel-body" id="systeminfo">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+ </div>
+ </div>
+
+</div>
+
+<div class="row">
+
+ <div class="col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_maintenance}}
+ </div>
+ <div class="panel-body">
+ <form class="form-adduser" action="?do=SystemStatus" method="post">
+ <input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" value="reboot">
+ <div>Server Reboot</div>
+ <label><input type="checkbox" name="confirm" value="yep"> {{lang_iAmSure}}</label>
+ <button class="btn btn-warning btn-xs" type="submit">Reboot</button>
+ </form>
+ <div id="dmsd-users"></div>
+ </div>
+ </div>
+ </div>
+
+</div>
+
+<h3>{{lang_advanced}}</h3>
+
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_dmsdLog}}
+ </div>
+ <div class="panel-body" id="dmsd-log">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+</div>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_ldadpLog}}
+ </div>
+ <div class="panel-body" id="ldadp-log">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+</div>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ netstat -tulpn
+ </div>
+ <div class="panel-body" id="netstat">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+</div>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ ps auxf
+ </div>
+ <div class="panel-body" id="pslist">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+</div>
+
+<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');
+ setTimeout(function() {
+ $('#dmsd-log').load('?do=SystemStatus&action=DmsdLog');
+ $('#netstat').load('?do=SystemStatus&action=Netstat');
+ $('#pslist').load('?do=SystemStatus&action=PsList');
+ $('#ldadp-log').load('?do=SystemStatus&action=LdadpLog');
+ }, 300);
+ }, false);
+</script>
diff --git a/modules-available/systemstatus/templates/addresses.html b/modules-available/systemstatus/templates/addresses.html
new file mode 100644
index 00000000..ce92c4d5
--- /dev/null
+++ b/modules-available/systemstatus/templates/addresses.html
@@ -0,0 +1,8 @@
+<table class="slx-table">
+ {{#addresses}}
+ <tr {{#primary}} class="slx-bold" {{/primary}}>
+ <td>{{ip}}</td>
+ <td>({{iface}})</td>
+ </tr>
+ {{/addresses}}
+</table> \ No newline at end of file
diff --git a/modules-available/systemstatus/templates/diskstat.html b/modules-available/systemstatus/templates/diskstat.html
new file mode 100644
index 00000000..528d9792
--- /dev/null
+++ b/modules-available/systemstatus/templates/diskstat.html
@@ -0,0 +1,63 @@
+<div class="slx-storechart">
+ {{#system}}
+ <b>{{lang_systemPartition}}</b>
+ <div id="circles-system"></div>
+ <div>{{lang_capacity}}: {{size}}</div>
+ <div>{{lang_free}}: {{free}}</div>
+ {{/system}}
+ {{^system}}
+ <b>{{lang_systemStoreError}}</b>
+ {{/system}}
+</div>
+<div class="slx-storechart">
+ {{#store}}
+ <b>{{lang_vmStore}}</b>
+ <div id="circles-store"></div>
+ <div>{{lang_capacity}}: {{size}}</div>
+ <div>{{lang_free}}: {{free}}</div>
+ {{/store}}
+ {{^store}}
+ <b>{{lang_vmStoreError}}</b>
+ {{/store}}
+</div>
+<div class="clearfix"></div>
+{{#notConfigured}}
+<div>{{lang_storeNotConfigured}}</div>
+{{/notConfigured}}
+{{#storeMissing}}
+<div>{{lang_storeMissingExpected}} {{storeMissing}}</div>
+{{/storeMissing}}
+{{#wrongStore}}
+<div>{{lang_foundStore}} {{wrongStore}}</div>
+{{/wrongStore}}
+<a href="?do=VmStore">{{lang_goToStoreConf}}</a>
+<script type="text/javascript">
+ {{#store}}
+ Circles.create({
+ id: 'circles-store',
+ radius: 60,
+ value: {{{percent}}},
+ maxValue: 100,
+ width: 10,
+ text: function(value){return value + '%'; },
+ colors: ['#D3B6C6', '#{{color}}'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ {{/store}}
+ {{#system}}
+ Circles.create({
+ id: 'circles-system',
+ radius: 60,
+ value: {{{percent}}},
+ maxValue: 100,
+ width: 10,
+ text: function(value){return value + '%'; },
+ colors: ['#D3B6C6', '#{{color}}'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ {{/system}}
+</script>
diff --git a/modules-available/systemstatus/templates/services.html b/modules-available/systemstatus/templates/services.html
new file mode 100644
index 00000000..6c4f0b93
--- /dev/null
+++ b/modules-available/systemstatus/templates/services.html
@@ -0,0 +1,6 @@
+{{#ldadpError}}
+<pre>{{ldadpError}}</pre>
+{{/ldadpError}}
+{{^ldadpError}}
+<div class="alert alert-success">LDAP-AD-Proxy: OK</div>
+{{/ldadpError}}
diff --git a/modules-available/systemstatus/templates/systeminfo.html b/modules-available/systemstatus/templates/systeminfo.html
new file mode 100644
index 00000000..ed4a1532
--- /dev/null
+++ b/modules-available/systemstatus/templates/systeminfo.html
@@ -0,0 +1,115 @@
+<div>
+ {{lang_uptimeOS}}: {{uptime}}
+</div>
+
+<div class="slx-storechart">
+ <b>{{lang_cpuLoad}}</b>
+ {{#cpuLoadOk}}
+ <div id="circles-cpuload"></div>
+ <div>{{lang_average}}: {{cpuLoad}}%</div>
+ <div>{{lang_onlyOS}}: {{cpuSystem}}%</div>
+ <div>{{lang_logicCPUs}}: {{cpuCount}}</div>
+ {{/cpuLoadOk}}
+ {{^cpuLoadOk}}
+ {{lang_notDetermined}}
+ {{/cpuLoadOk}}
+</div>
+
+<div class="slx-storechart">
+ <b>{{lang_ramUsage}}</b>
+ {{#memTotal}}
+ <div id="circles-mem"></div>
+ <div>{{lang_total}}: {{memTotal}}</div>
+ <div>{{lang_free}}: {{memFree}}</div>
+ {{/memTotal}}
+ {{^memTotal}}
+ {{lang_notDetermined}}
+ {{/memTotal}}
+</div>
+
+<div class="slx-storechart">
+ <b>{{lang_swapUsage}}</b>
+ {{#memTotal}}
+ <div id="circles-swap"></div>
+ <div>{{lang_total}}: {{swapTotal}}</div>
+ <div>{{lang_occupied}}: {{swapUsed}}</div>
+ {{/memTotal}}
+ {{^memTotal}}
+ {{lang_notDetermined}}
+ {{/memTotal}}
+</div>
+
+<div class="clearfix"></div>
+
+{{#swapWarning}}
+<div>
+ <b>{{lang_attention}}</b> {{lang_swapWarning}}
+</div>
+{{/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;
+ }
+ }, 'json').fail(function(data) {
+ console.log(data);
+ }).always(function() {
+ setTimeout(updateSystem, 1200);
+ });
+ }
+ setTimeout(updateSystem, 1000);
+</script>