diff options
author | Roeland Jago Douma <rullzer@users.noreply.github.com> | 2019-04-15 15:08:22 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-15 15:08:22 +0300 |
commit | df89e0de3e050e11287ab371dcbf55ac2ea0df22 (patch) | |
tree | f3d3de17f5df8ee029861b5f5f179d745ffb3dad | |
parent | 4675aaf9921f7476c414356943cbe7f81d54793e (diff) | |
parent | e499dd0b4d68912ea2a517bcf97d39c100d85d08 (diff) |
Merge pull request #146 from nextcloud/moreinfo
adding more info to the page. This is only the first step
-rw-r--r-- | AUTHORS.md | 2 | ||||
-rw-r--r-- | CHANGELOG.md | 6 | ||||
-rw-r--r-- | appinfo/info.xml | 1 | ||||
-rw-r--r-- | appinfo/routes.php | 4 | ||||
-rw-r--r-- | css/style.css | 107 | ||||
-rw-r--r-- | img/hdd-o.svg | 3 | ||||
-rw-r--r-- | img/server.svg | 3 | ||||
-rw-r--r-- | img/sort.svg | 3 | ||||
-rw-r--r-- | js/script.js | 107 | ||||
-rw-r--r-- | lib/Controller/ApiController.php | 80 | ||||
-rw-r--r-- | lib/OperatingSystems/DefaultOs.php | 176 | ||||
-rw-r--r-- | lib/Os.php | 185 | ||||
-rw-r--r-- | lib/Settings/AdminSection.php | 4 | ||||
-rw-r--r-- | lib/Settings/AdminSettings.php | 15 | ||||
-rw-r--r-- | templates/settings-admin.php | 270 | ||||
-rw-r--r-- | tests/lib/Controller/ApiControllerTest.php | 137 |
16 files changed, 871 insertions, 232 deletions
@@ -1,4 +1,4 @@ # Authors * Bjoern Schiessle: <bjoern@schiessle.org> - +* Frank Karlitschek: <frank@karlitschek.de> diff --git a/CHANGELOG.md b/CHANGELOG.md index cafd0e8..e69de29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +0,0 @@ -owncloud-serverinfo (0.0.1) -* **Security**: Security description here -* **Backwards incompatible change**: Changes in the API -* **New dependency**: New dependencies such as a new ownCloud or PHP version -* **Bugfix**: Bugfix description -* **Enhancement**: New feature description
\ No newline at end of file diff --git a/appinfo/info.xml b/appinfo/info.xml index ed4e0ea..9359818 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -9,6 +9,7 @@ <licence>agpl</licence> <author>Bjoern Schiessle</author> <author>Ivan Sein Santiago</author> + <author>Frank Karlitschek</author> <namespace>ServerInfo</namespace> <default_enable/> <category>monitoring</category> diff --git a/appinfo/routes.php b/appinfo/routes.php index e1da318..7725e92 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -34,5 +34,7 @@ return [ ], 'ocs' => [ ['name' => 'api#info', 'url' => '/api/v1/info', 'verb' => 'GET'], - ] + ['name' => 'api#DiskData', 'url' => '/api/v1/diskdata', 'verb' => 'GET'], + ['name' => 'api#BasicData', 'url' => '/api/v1/basicdata', 'verb' => 'GET'], + ], ]; diff --git a/css/style.css b/css/style.css index b2aaefc..9fbad5d 100644 --- a/css/style.css +++ b/css/style.css @@ -1,5 +1,5 @@ .barchart { - max-width: 700px; + max-width: 200px; max-height: 350px; } @@ -17,4 +17,107 @@ #monitoring-endpoint-url { width: 80%; max-width: 415px; -}
\ No newline at end of file +} + +.rambox { + padding: 0px; + margin: 0px; + height: 10px; + width: 10px; + background-color: #555; + border-radius: 20%; +} + +.swapbox { + height: 10px; + width: 10px; + background-color: #222; + border-radius: 20%; +} + +.info { + font-weight: bold; + text-color: #777777; +} + +.smallinfo { + color: #888888; + font-size: 11px; +} + +.infobox { + width: 400px; + border: 1px solid #DDDDDD; + margin: 10px 0px 20px 0px; + padding: 15px; + color: #555555; + background-color: #F9F9F9; + border-radius: 6px; + box-shadow: 1px 1px 9px 1px #EEEEEE; +} + +.infobox h3 { + color: #555555; + font-size: 22px; + font-weight: bold; + padding: 5px 0px 10px 0px; + margin: 0px; +} + +.infobox h2 { + color: #555555; + font-size: 18px; + font-weight: bold; + padding: 5px 5px 5px 5px; + margin: 0px; +} + +.infoicon { + width: 28px; + float: left; + padding: 5px; +} + +.chart-container { + height:300px; + width: 800px; + margin: 5px 10px 5px 5px; +} + +.diskchart-container { + position: static; + display: inline-block; + height:130px; + width:130px; + float:left; + border: 1px black; + margin: 5px 10px 5px 5px; +} + +.wrapper { + overflow:hidden; +} + +.wrapper div { + min-height: 100px; + padding: 0px; +} +#one { + float:left; + width:440px; + margin-right: 10px; +} + +#two { + overflow:hidden; + width:440px; + min-height:100px; +} + +@media screen and (max-width: 1000px) { + #one { + float: none; + margin-right:0; + width:auto; + } +} diff --git a/img/hdd-o.svg b/img/hdd-o.svg new file mode 100644 index 0000000..472a231 --- /dev/null +++ b/img/hdd-o.svg @@ -0,0 +1,3 @@ +<svg width="1536" height="1536" xmlns="http://www.w3.org/2000/svg"> + <path d="M1040 1216c0 44-36 80-80 80s-80-36-80-80 36-80 80-80 80 36 80 80zm256 0c0 44-36 80-80 80s-80-36-80-80 36-80 80-80 80 36 80 80zm112 160v-320c0-17-15-32-32-32H160c-17 0-32 15-32 32v320c0 17 15 32 32 32h1216c17 0 32-15 32-32zM178 896h1180l-157-482c-5-17-24-30-42-30H377c-18 0-37 13-42 30zm1358 160v320c0 88-72 160-160 160H160c-88 0-160-72-160-160v-320c0-27 8-50 16-75l197-606c23-70 90-119 164-119h782c74 0 141 49 164 119l197 606c8 25 16 48 16 75z"/> +</svg> diff --git a/img/server.svg b/img/server.svg new file mode 100644 index 0000000..37ac886 --- /dev/null +++ b/img/server.svg @@ -0,0 +1,3 @@ +<svg width="1536" height="1536" xmlns="http://www.w3.org/2000/svg"> + <path d="M128 1408h1024v-128H128v128zm0-512h1024V768H128v128zm1568 448c0-53-43-96-96-96s-96 43-96 96 43 96 96 96 96-43 96-96zM128 384h1024V256H128v128zm1568 448c0-53-43-96-96-96s-96 43-96 96 43 96 96 96 96-43 96-96zm0-512c0-53-43-96-96-96s-96 43-96 96 43 96 96 96 96-43 96-96zm96 832v384H0v-384h1792zm0-512v384H0V640h1792zm0-512v384H0V128h1792z"/> +</svg> diff --git a/img/sort.svg b/img/sort.svg new file mode 100644 index 0000000..af6e731 --- /dev/null +++ b/img/sort.svg @@ -0,0 +1,3 @@ +<svg width="1536" height="1536" xmlns="http://www.w3.org/2000/svg"> + <path d="M1024 1088c0 17-7 33-19 45l-448 448c-12 12-28 19-45 19s-33-7-45-19L19 1133c-12-12-19-28-19-45 0-35 29-64 64-64h896c35 0 64 29 64 64zm0-384c0 35-29 64-64 64H64c-35 0-64-29-64-64 0-17 7-33 19-45l448-448c12-12 28-19 45-19s33 7 45 19l448 448c12 12 19 28 19 45z"/> +</svg> diff --git a/js/script.js b/js/script.js index a69c8a2..77670e9 100644 --- a/js/script.js +++ b/js/script.js @@ -29,8 +29,14 @@ sharesChart; $(document).ready(function () { + var x = document.getElementById('rambox'); + x.style.backgroundColor = OCA.Theming ? OCA.Theming.color : 'rgb(54, 129, 195)'; - var updateTimer = setInterval(updateInfo, 1000); + var x = document.getElementById('swapbox'); + x.style.backgroundColor = 'rgba(100, 100, 100, 0.8)'; + + + var updateTimer = setInterval(updateInfo, 300); resizeSystemCharts(); updateActiveUsersStatistics(); @@ -78,14 +84,14 @@ if (typeof cpuLoadChart === 'undefined') { cpuLoadChart = new SmoothieChart( { - millisPerPixel: 250, + millisPerPixel: 100, minValue: 0, - grid: { fillStyle: 'rgba(0,0,0,0.03)', strokeStyle: 'transparent' }, + grid: { fillStyle: 'rgba(249,249,249,1)', strokeStyle: 'transparent' }, labels: { fillStyle: 'rgba(0,0,0,0.4)', fontSize: 12 } }); cpuLoadChart.streamTo(document.getElementById("cpuloadcanvas"), 1000/*delay*/); cpuLoadLine = new TimeSeries(); - cpuLoadChart.addTimeSeries(cpuLoadLine, { lineWidth: 1, strokeStyle: 'rgb(0, 0, 255)', fillStyle: 'rgba(0, 0, 255, 0.2)' }); + cpuLoadChart.addTimeSeries(cpuLoadLine, { lineWidth: 1, strokeStyle: 'rgb(180, 180, 180)', fillStyle: OCA.Theming ? OCA.Theming.color : 'rgb(54, 129, 195)' }); } $('#cpuFooterInfo').text(t('serverinfo', 'Load average')+": "+cpu1+" ("+t('serverinfo', 'Last minute')+")"); @@ -121,17 +127,17 @@ if (typeof memoryUsageChart === 'undefined') { memoryUsageChart = new SmoothieChart( { - millisPerPixel: 250, + millisPerPixel: 100, maxValue: maxValueOfChart, minValue: 0, - grid: { fillStyle: 'rgba(0,0,0,0.03)', strokeStyle: 'transparent' }, + grid: { fillStyle: 'rgba(0,0,0,0)', strokeStyle: 'transparent' }, labels: { fillStyle: 'rgba(0,0,0,0.4)', fontSize: 12 } }); memoryUsageChart.streamTo(document.getElementById("memorycanvas"), 1000/*delay*/); memoryUsageLine = new TimeSeries(); - memoryUsageChart.addTimeSeries(memoryUsageLine, {lineWidth:1, strokeStyle:'rgb(0, 255, 0)', fillStyle:'rgba(0, 255, 0, 0.2)'}); + memoryUsageChart.addTimeSeries(memoryUsageLine, {lineWidth:1, strokeStyle:'rgb(180, 180, 180)', fillStyle:OCA.Theming ? OCA.Theming.color : 'rgb(54, 129, 195)'}); swapUsageLine = new TimeSeries(); - memoryUsageChart.addTimeSeries(swapUsageLine, {lineWidth:1, strokeStyle:'rgb(255, 0, 0)', fillStyle:'rgba(255, 0, 0, 0.2)'}); + memoryUsageChart.addTimeSeries(swapUsageLine, {lineWidth:1, strokeStyle:'rgb(100, 100, 100)', fillStyle:'rgba(100, 100, 100, 0.2)'}); } $('#memFooterInfo').text("RAM: "+t('serverinfo', 'Total')+": "+OC.Util.humanFileSize(memTotalBytes)+" - "+t('serverinfo', 'Current usage')+": "+OC.Util.humanFileSize(memUsageBytes)); @@ -223,9 +229,9 @@ type: 'line', data: { labels: [ - t('serverinfo', 'Last 24 hours'), - t('serverinfo', 'Last 1 hour'), - t('serverinfo', 'Last 5 mins') + t('serverinfo', '24 hours'), + t('serverinfo', '1 hour'), + t('serverinfo', '5 mins') ], datasets: [{ label: " ", @@ -274,18 +280,29 @@ var cpu_canvas = document.getElementById("cpuloadcanvas"), mem_canvas = document.getElementById("memorycanvas"); + activeuserscanvas = document.getElementById("activeuserscanvas"); + sharecanvas = document.getElementById("sharecanvas"); var newWidth = $('#cpuSection').width(); newHeight = newWidth / 4 if (newWidth <= 100) newWidth = 100; + if (newWidth >= 500) newWidth = 500; if (newHeight > 150) newHeight = 150; + cpuloadcanvas.width = newWidth; cpuloadcanvas.height = newHeight; mem_canvas.width = newWidth; mem_canvas.height = newHeight; + + activeuserscanvas.width = 600; + activeuserscanvas.height = 500; + + sharecanvas.width = 800; + + } function initMonitoringLinkToClipboard() { @@ -333,3 +350,71 @@ } })(jQuery, OC); + + +$(document).ready(function(){ + $.ajax({ + url: OC.linkToOCS('apps/serverinfo/api/v1/', 2) + 'diskdata?format=json', + method: "GET", + success: function(response) { + var diskdata = response.ocs.data; + var x = document.querySelectorAll(".DiskChart"); + var i; + for (i = 0; i < x.length; i++) { + var chartdata = { + labels: ["Used GB", "Available GB"], + datasets : [ + { + backgroundColor: [ + OCA.Theming ? OCA.Theming.color : 'rgb(54, 129, 195)', + 'rgb(249, 249, 249)', + ], + borderWidth: 0, + data: diskdata[i] + } + ] + }; + var ctx = x[i]; + var barGraph = new Chart(ctx, { + type: 'doughnut', + data: chartdata, + options: { + legend: { + display: false, + }, + tooltips: { + enabled: true, + }, + cutoutPercentage: 60 + } + }); + } + }, + error: function(data) { + console.log(data); + } + }); + + var interval = 1000; // 1000 = 1 second, 3000 = 3 seconds + function doAjax() { + $.ajax({ + url: OC.linkToOCS('apps/serverinfo/api/v1/', 2) + 'basicdata?format=json', + method: "GET", + success: function(response) { + var data = response.ocs.data; + document.getElementById("servertime").innerHTML = data.servertime; + document.getElementById("uptime").innerHTML = data.uptime; + document.getElementById("timeservers").innerHTML = data.timeservers; + }, + error: function(data) { + console.log(data); + }, + complete: function (data) { + setTimeout(doAjax, interval); + } + }); + } + setTimeout(doAjax, interval); + + +}); diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index 8757238..bbd2f31 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -19,10 +19,10 @@ * */ - namespace OCA\ServerInfo\Controller; use OCA\ServerInfo\DatabaseStatistics; +use OCA\ServerInfo\Os; use OCA\ServerInfo\PhpStatistics; use OCA\ServerInfo\SessionStatistics; use OCA\ServerInfo\ShareStatistics; @@ -34,6 +34,9 @@ use OCP\IRequest; class ApiController extends OCSController { + /** @var Os */ + private $os; + /** @var SystemStatistics */ private $systemStatistics; @@ -57,6 +60,7 @@ class ApiController extends OCSController { * * @param string $appName * @param IRequest $request + * @param Os $os * @param SystemStatistics $systemStatistics * @param StorageStatistics $storageStatistics * @param PhpStatistics $phpStatistics @@ -66,21 +70,22 @@ class ApiController extends OCSController { */ public function __construct($appName, IRequest $request, + Os $os, SystemStatistics $systemStatistics, StorageStatistics $storageStatistics, PhpStatistics $phpStatistics, DatabaseStatistics $databaseStatistics, ShareStatistics $shareStatistics, - SessionStatistics $sessionStatistics - ) { + SessionStatistics $sessionStatistics) { parent::__construct($appName, $request); - $this->systemStatistics = $systemStatistics; - $this->storageStatistics = $storageStatistics; - $this->phpStatistics = $phpStatistics; + $this->os = $os; + $this->systemStatistics = $systemStatistics; + $this->storageStatistics = $storageStatistics; + $this->phpStatistics = $phpStatistics; $this->databaseStatistics = $databaseStatistics; - $this->shareStatistics = $shareStatistics; - $this->sessionStatistics = $sessionStatistics; + $this->shareStatistics = $shareStatistics; + $this->sessionStatistics = $sessionStatistics; } /** @@ -90,24 +95,43 @@ class ApiController extends OCSController { */ public function info() { - return new DataResponse( - [ - 'nextcloud' => - [ - 'system' => $this->systemStatistics->getSystemStatistics(), - 'storage' => $this->storageStatistics->getStorageStatistics(), - 'shares' => $this->shareStatistics->getShareStatistics() - ], - 'server' => - [ - 'webserver' => $this->getWebserver(), - 'php' => $this->phpStatistics->getPhpStatistics(), - 'database' => $this->databaseStatistics->getDatabaseStatistics() - ], - 'activeUsers' => $this->sessionStatistics->getSessionStatistics() - ] - ); + return new DataResponse([ + 'nextcloud' => [ + 'system' => $this->systemStatistics->getSystemStatistics(), + 'storage' => $this->storageStatistics->getStorageStatistics(), + 'shares' => $this->shareStatistics->getShareStatistics() + ], + 'server' => [ + 'webserver' => $this->getWebserver(), + 'php' => $this->phpStatistics->getPhpStatistics(), + 'database' => $this->databaseStatistics->getDatabaseStatistics() + ], + 'activeUsers' => $this->sessionStatistics->getSessionStatistics() + ]); + + } + + /** + * @return DataResponse + */ + public function BasicData(): DataResponse { + $servertime = $this->os->getTime(); + $uptime = $this->os->getUptime(); + $timeservers = $this->os->getTimeServers()[0]; + + return new DataResponse([ + 'servertime' => $servertime, + 'uptime' => $uptime, + 'timeservers' => $timeservers + ]); + } + /** + * @return DataResponse + */ + public function DiskData(): DataResponse { + $result = $this->os->getDiskData(); + return new DataResponse($result); } /** @@ -119,10 +143,6 @@ class ApiController extends OCSController { if (isset($_SERVER['SERVER_SOFTWARE'])) { return $_SERVER['SERVER_SOFTWARE']; } - - return "unknown"; + return 'unknown'; } - - - } diff --git a/lib/OperatingSystems/DefaultOs.php b/lib/OperatingSystems/DefaultOs.php new file mode 100644 index 0000000..d695c34 --- /dev/null +++ b/lib/OperatingSystems/DefaultOs.php @@ -0,0 +1,176 @@ +<?php +/** + * @author Frank Karlitschek <frank@nextcloud.com> + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\Serverinfo\OperatingSystems; +/** + * Class Ubuntu + * + * @package OCA\ServerInfo\OperatingSystems + */ +class DefaultOs { + + public function __construct() {} + + /** + * @return bool + */ + public function supported() { + return true; + } + + /** + * @return string + */ + public function getHostname() { + $hostname = shell_exec('hostname'); + return $hostname; + } + + /** + * @return string + */ + public function getMemory() { + $memory = shell_exec('cat /proc/meminfo | grep -i \'MemTotal\' | cut -f 2 -d ":" | awk \'{$1=$1}1\''); + $memory = explode(' ', $memory); + $memory = round($memory[0] / 1024); + if ($memory < 1024) { + $memory = $memory . ' MB'; + } else { + $memory = round($memory / 1024, 1) . ' GB'; + } + return $memory; + } + + /** + * @return string + */ + public function getCPUName() { + $cpu = shell_exec('cat /proc/cpuinfo | grep -i \'Model name\' | cut -f 2 -d ":" | awk \'{$1=$1}1\''); + $cores = shell_exec('cat /proc/cpuinfo | grep -i \'cpu cores\' | cut -f 2 -d ":" | awk \'{$1=$1}1\''); + if ($cores === 1) { + $cores = ' (' . $cores . ' core)'; + } else { + $cores = ' (' . $cores . ' cores)'; + } + return $cpu . ' ' . $cores; + } + + /** + * @return string + */ + public function getTime() { + $uptime = shell_exec('date'); + return $uptime; + } + + /** + * @return string + */ + public function getUptime() { + $uptime = shell_exec('uptime -p'); + return $uptime; + } + + /** + * @return string + */ + public function getTimeServers() { + $servers = shell_exec('cat /etc/ntp.conf |grep \'^pool\' | cut -f 2 -d " "'); + $servers .= ' ' . shell_exec('cat /etc/systemd/timesyncd.conf |grep \'^NTP=\' | cut -f 2 -d " "'); + return $servers; + } + + /** + * @return string + */ + public function getNetworkInfo() { + $result = []; + $result['hostname'] = \gethostname(); + $dns = shell_exec('cat /etc/resolv.conf |grep -i \'^nameserver\'|head -n1|cut -d \' \' -f2'); + $result['dns'] = $dns; + $gw = shell_exec('ip route | awk \'/default/ { print $3 }\''); + $result['gateway'] = $gw; + return $result; + } + + /** + * @return string + */ + public function getNetworkInterfaces() { + $interfaces = glob('/sys/class/net/*'); + $result = []; + + foreach ($interfaces as $interface) { + $iface = []; + $iface['interface'] = basename($interface); + $iface['mac'] = shell_exec('ip addr show dev ' . $iface['interface'] . ' | grep "link/ether " | cut -d \' \' -f 6 | cut -f 1 -d \'/\''); + $iface['ipv4'] = shell_exec('ip addr show dev ' . $iface['interface'] . ' | grep "inet " | cut -d \' \' -f 6 | cut -f 1 -d \'/\''); + $iface['ipv6'] = shell_exec('ip -o -6 addr show ' . $iface['interface'] . ' | sed -e \'s/^.*inet6 \([^ ]\+\).*/\1/\''); + if ($iface['interface'] !== 'lo') { + $iface['status'] = shell_exec('cat /sys/class/net/' . $iface['interface'] . '/operstate'); + $iface['speed'] = shell_exec('cat /sys/class/net/' . $iface['interface'] . '/speed'); + if ($iface['speed'] !== '') { + $iface['speed'] = $iface['speed'] . 'Mbps'; + } else { + $iface['speed'] = 'unknown'; + } + + $duplex = shell_exec('cat /sys/class/net/' . $iface['interface'] . '/duplex'); + if ($duplex !== '') { + $iface['duplex'] = 'Duplex: ' . $duplex; + } else { + $iface['duplex'] = ''; + } + } else { + $iface['status'] = 'up'; + $iface['speed'] = 'unknown'; + $iface['duplex'] = ''; + } + $result[] = $iface; + } + + return $result; + } + + /** + * @return array + */ + public function getDiskInfo() { + $blacklist = ['', 'Type', 'tmpfs', 'devtmpfs']; + $data = shell_exec('df -T'); + $lines = preg_split('/[\r\n]+/', $data); + + foreach ($lines as $line) { + $entry = preg_split('/\s+/', trim($line)); + if (isset($entry[1]) && !in_array($entry[1], $blacklist)) { + $items = []; + $items['device'] = $entry[0]; + $items['fs'] = $entry[1]; + $items['used'] = $entry[3]; + $items['available'] = $entry[4]; + $items['percent'] = $entry[5]; + $items['mount'] = $entry[6]; + $result[] = $items; + } + } + return $result; + } + +} diff --git a/lib/Os.php b/lib/Os.php new file mode 100644 index 0000000..52a6c64 --- /dev/null +++ b/lib/Os.php @@ -0,0 +1,185 @@ +<?php +/** + * @author Frank Karlitschek <frank@nextcloud.com> + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\ServerInfo; + +use bantu\IniGetWrapper\IniGetWrapper; +use OCA\ServerInfo\OperatingSystems\DefaultOs; +use OCP\AppFramework\Http; +use OCP\Http\Client\IClientService; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IL10N; + +class Os { + + /** @var IClientService */ + protected $clientService; + + /** @var IConfig */ + protected $config; + + /** @var IDBConnection */ + protected $connection; + + /** @var IniGetWrapper */ + protected $phpIni; + + /** @var \OCP\IL10N */ + protected $l; + + /** @var */ + protected $backend; + + /** @var */ + protected $osname; + + /** + * Os constructor. + * + * @param IClientService $clientService + * @param IConfig $config + * @param IDBConnection $connection + * @param IniGetWrapper $phpIni + * @param IL10N $l + */ + public function __construct(IClientService $clientService, + IConfig $config, + IDBConnection $connection, + IniGetWrapper $phpIni, + IL10N $l) { + $this->clientService = $clientService; + $this->config = $config; + $this->connection = $connection; + $this->phpIni = $phpIni; + $this->l = $l; + $this->backend = new DefaultOs(); + } + + /** + * @return bool + */ + public function supported() { + $data = $this->backend->supported(); + return $data; + } + + /** + * @return string + */ + public function getHostname() { + $data = $this->backend->getHostname(); + return $data; + } + + /** + * @return string + */ + public function getOSName() { + $data = $this->osname; + return $data; + } + + /** + * @return string + */ + public function getMemory() { + $data = $this->backend->getMemory(); + return $data; + } + + /** + * @return string + */ + public function getCPUName() { + $data = $this->backend->getCPUName(); + return $data; + } + + /** + * @return string + */ + public function getTime() { + $data = $this->backend->getTime(); + return $data; + } + + /** + * @return string + */ + public function getUptime() { + $data = $this->backend->getUptime(); + return $data; + } + + /** + * @return string + */ + public function getTimeServers() { + $data = $this->backend->getTimeServers(); + return explode("\n", $data); + } + + /** + * @return string + */ + public function getDiskInfo() { + $data = $this->backend->getDiskInfo(); + return $data; + } + + /** + * @return string + */ + public function getDiskData() { + $disks = $this->backend->getDiskInfo(); + $data = array(); + $i = 0; + foreach ($disks as $disk) { + $data[$i] = [ + round(($disk['used']) / 1024 / 1024, 1), + round($disk['available'] / 1024 / 1024, 1) + ]; + $i++; + } + +// debug data + // $data = array('0'=>array(1,2),'1'=>array(4,5),'2'=>array(3,1)); + + return $data; + } + + /** + * @return string + */ + public function getNetworkInfo() { + $data = $this->backend->getNetworkInfo(); + return $data; + } + + /** + * @return string + */ + public function getNetworkInterfaces() { + $data = $this->backend->getNetworkInterfaces(); + return $data; + } + +} diff --git a/lib/Settings/AdminSection.php b/lib/Settings/AdminSection.php index eb74dfa..1b0a552 100644 --- a/lib/Settings/AdminSection.php +++ b/lib/Settings/AdminSection.php @@ -55,7 +55,7 @@ class AdminSection implements IIconSection { * @return string */ public function getName() { - return $this->l->t('Monitoring'); + return $this->l->t('System'); } /** @@ -66,7 +66,7 @@ class AdminSection implements IIconSection { * keep the server setting at the top, right after "overview" and "basic settings" */ public function getPriority() { - return 1; + return 90; } /** diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php index 8a2eaa4..03bfeb2 100644 --- a/lib/Settings/AdminSettings.php +++ b/lib/Settings/AdminSettings.php @@ -22,7 +22,7 @@ namespace OCA\ServerInfo\Settings; - +use OCA\ServerInfo\Os; use OCP\AppFramework\Http\TemplateResponse; use OCP\IL10N; use OCP\IURLGenerator; @@ -36,6 +36,8 @@ use OCA\ServerInfo\SystemStatistics; class AdminSettings implements ISettings { + /** @var Os */ + private $os; /** @var IL10N */ private $l; @@ -73,7 +75,8 @@ class AdminSettings implements ISettings { * @param SessionStatistics $sessionStatistics * @param SystemStatistics $systemStatistics */ - public function __construct(IL10N $l, + public function __construct(Os $os, + IL10N $l, IURLGenerator $urlGenerator, StorageStatistics $storageStatistics, PhpStatistics $phpStatistics, @@ -82,6 +85,7 @@ class AdminSettings implements ISettings { SessionStatistics $sessionStatistics, SystemStatistics $systemStatistics ) { + $this->os = $os; $this->l = $l; $this->urlGenerator = $urlGenerator; $this->storageStatistics = $storageStatistics; @@ -98,6 +102,13 @@ class AdminSettings implements ISettings { public function getForm() { $monitoringEndPoint = $this->urlGenerator->getAbsoluteURL('ocs/v2.php/apps/serverinfo/api/v1/info'); $params = [ + 'hostname' => $this-> os -> getHostname(), + 'osname' => $this-> os -> getOSName(), + 'memory' => $this-> os -> getMemory(), + 'cpu' => $this-> os -> getCPUName(), + 'diskinfo' => $this-> os -> getDiskInfo(), + 'networkinfo' => $this-> os -> getNetworkInfo(), + 'networkinterfaces' => $this-> os -> getNetworkInterfaces(), 'ocs' => $monitoringEndPoint, 'storage' => $this->storageStatistics->getStorageStatistics(), 'shares' => $this->shareStatistics->getShareStatistics(), diff --git a/templates/settings-admin.php b/templates/settings-admin.php index e94fa16..52b4b99 100644 --- a/templates/settings-admin.php +++ b/templates/settings-admin.php @@ -19,71 +19,261 @@ * */ - script('serverinfo', 'script'); script('serverinfo', 'smoothie'); script('serverinfo', 'Chart.min'); style('serverinfo', 'style'); +function FormatBytes($byte) { + $unim = array('B', 'KB', 'MB', 'GB', 'TB', 'PB'); + $count = 1; + while ($byte >= 1024) { + $count++; + $byte = $byte / 1024; + } + return number_format($byte, 2, '.', '.') . ' ' . $unim[$count]; +} + ?> -<div class="section" id="cpuSection"> - <h2><?php p($l->t('CPU load'));?></h2> - <canvas id="cpuloadcanvas" width="600" height="150"></canvas> - <p><em id="cpuFooterInfo"></em></p> +<!-- SERVER INFOS --> +<div class="section"> + <h2> + <img class="infoicon" src="<?php p(image_path('serverinfo', 'server.svg'));?>"> + <?php p($_['hostname']);?> + </h2> + + <p> + <?php p($l->t('Operating System'));?>: + <span class="info"><?php p($_['osname']);?></span> + </p> + <p> + <?php p($l->t('CPU'));?>: + <span class="info"><?php p($_['cpu']);?></span> + </p> + <p> + <?php p($l->t('Memory'));?>: + <span class="info"><?php p($_['memory']);?></span> + </p> + <p> + <?php p($l->t('Server time'));?>: + <span class="info" id="servertime"></span> + </p> + <p> + <?php p($l->t('Uptime'));?>: + <span class="info" id="uptime"></span> + </p> + <p> + <?php p($l->t('Time Servers'));?>: + <span class="info" id="timeservers"></span> + </p> + + <div class="wrapper"> + + <div id="one"> + <div class="infobox" id="cpuSection"> + <h2><?php p($l->t('Load'));?></h2> + <canvas id="cpuloadcanvas" width="100" height="150"></canvas> + </div> + <p><em id="cpuFooterInfo"></em></p> + </div> + + <div id="two"> + <div class="infobox"> + <h2><?php p($l->t('Memory'));?></h2> + <canvas id="memorycanvas" width="300" height="150"></canvas> + </div> + <p><span class="rambox" id="rambox"> </span> <em id="memFooterInfo"></em></p> + <p><span class="swapbox" id="swapbox"> </span> <em id="swapFooterInfo"></em></p> + </div> + + </div> </div> -<div class="section" id="memorySection"> - <h2><?php p($l->t('Memory usage'));?></h2> - <canvas id="memorycanvas" width="600" height="150"></canvas> - <p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYBDCANxB9ROQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAUSURBVBjTY2T4z4AHMDEwjEpjAgBALQETBkU7DgAAAABJRU5ErkJggg==" alt="RAM color" /> <em id="memFooterInfo"></em></p> - <p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYBDB0ds0AJ4wAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAASSURBVBjTY/zPgA8wMYxKYwEAQSwBE2ViEDMAAAAASUVORK5CYII=" alt="SWAP color" /> <em id="swapFooterInfo"></em></p> + +<!-- DISK STATUS --> +<div class="section"> + <h2> + <img class="infoicon" src="<?php p(image_path('serverinfo', 'hdd-o.svg'));?>"> + <?php p($l->t('Disk'));?> + </h2> + <p> + <?php foreach ($_['diskinfo'] as $disk) {?> + + <div class="infobox"> + <div class="diskchart-container"> + <canvas id="DiskChart" class="DiskChart" width="50" height="50"></canvas> + </div> + + <h3><?php p(basename($disk['device']));?></h3> + <p> + <?php p($l->t('Mount'));?> : + <span class="info"><?php p($disk['mount']);?></span> + </p> + <p> + <?php p($l->t('Filesystem'));?> : + <span class="info"><?php p($disk['fs']);?></span> + </p> + <p> + <?php p($l->t('Size'));?> : + <span class="info"><?php p(FormatBytes($disk['used'] + $disk['available']));?></span> + </p> + <p> + <?php p($l->t('Available'));?> : + <span class="info"><?php p(FormatBytes($disk['available']));?></span> + </p> + <p> + <?php p($l->t('Used'));?> : + <span class="info"><?php p($disk['percent']);?></span> + </p> + </div> + + <?php }?> + + <div class="smallinfo"> <?php p($l->t('You will get a notification once one of your disks is nearly full.'));?></div> + + <p><?php p($l->t('Files:'));?> <em id="numFilesStorage"><?php p($_['storage']['num_files']);?></em></p> + <p><?php p($l->t('Storages:'));?> <em id="numFilesStorages"><?php p($_['storage']['num_storages']);?></em></p> + <p><?php p($l->t('Free Space:'));?> <em id="systemDiskFreeSpace"><?php p($_['system']['freespace']);?></em></p> + </p> +</div> + +<!-- NETWORK --> +<div class="section"> + <h2> + <img class="infoicon" src="<?php p(image_path('serverinfo', 'sort.svg'));?>"> + <?php p($l->t('Network'));?> + </h2> + <p> + <p> + <?php p($l->t('Hostname'));?>: + <span class="info"><?php p($_['networkinfo']['hostname']);?></span> + </p> + <p> + <?php p($l->t('DNS'));?>: + <span class="info"><?php p($_['networkinfo']['dns']);?></span> + </p> + <p> + <?php p($l->t('Gateway'));?>: + <span class="info"><?php p($_['networkinfo']['gateway']);?></span> + </p> + <p> + <?php foreach ($_['networkinterfaces'] as $interface) {?> + + <div class="infobox"> + <h3><?php p($interface['interface'])?></h3> + <p> + <?php p($l->t('Status'));?>: + <span class="info"><?php p($interface['status'])?></span> + </p> + <p> + <?php p($l->t('Speed'));?>: + <span class="info"><?php p($interface['speed'] . ' ' . $interface['duplex'])?></span> + </p> + <?php if (!empty($interface['mac'])) {?> + <p> + <?php p($l->t('MAC'));?>: + <span class="info"><?php p($interface['mac'])?></span> + </p> + <?php }?> + <p> + <?php p($l->t('IPv4'));?>: + <span class="info"><?php p($interface['ipv4'])?></span> + </p> + <p> + <?php p($l->t('IPv6'));?>: + <span class="info"><?php p($interface['ipv6'])?></span> + </p> + </div> + + <?php }?> + + </p> </div> + +<!-- ACTIVE USERS --> <div class="section" id="activeUsersSection"> - <h2><?php p($l->t('Active users'));?></h2> - <br> - <canvas data-users="<?php p(json_encode($_['activeUsers'])) ?>" class="barchart" id="activeuserscanvas"></canvas> + <div class="infobox"> + <h2><?php p($l->t('Active users'));?></h2> + <br> + <div class="chart-container"> + <canvas width="400" height="250" data-users="<?php p(json_encode($_['activeUsers']))?>" class="barchart" id="activeuserscanvas"></canvas> + </div> + <p> + <?php p($l->t('Total users:'));?> + <em id="numUsersStorage"><?php p($_['storage']['num_users']);?></em> + </p> + </div> </div> + +<!-- SHARES --> <div class="section" id="sharesSection"> - <h2><?php p($l->t('Shares'));?></h2> - <br> - <canvas data-shares="<?php p(json_encode($_['shares'])) ?>" class="barchart" id="sharecanvas"></canvas> -</div> -<div class="section" id="storageSection"> - <h2><?php p($l->t('Storage'));?></h2> - <p><?php p($l->t('Users:'));?> <em id="numUsersStorage"><?php p($_['storage']['num_users']);?></em></p> - <p><?php p($l->t('Files:'));?> <em id="numFilesStorage"><?php p($_['storage']['num_files']);?></em></p> - <p><?php p($l->t('Storages:'));?> <em id="numFilesStorages"><?php p($_['storage']['num_storages']);?></em></p> - <p><?php p($l->t('Free Space:'));?> <em id="systemDiskFreeSpace"><?php p($_['system']['freespace']);?></em></p> -</div> -<div class="section" id="ncSection"> - <h2><?php p($l->t('Nextcloud'));?></h2> - <p><?php p($l->t('Version:'));?> <em id="ncVersion"><?php p($_['system']['version']);?></em></p> - <p><?php p($l->t('Apps installed:'));?> <em id="ncAppsInstalled"><?php p($_['system']['apps']['num_installed']);?></em></p> - <p><?php p($l->t('Apps updates available:'));?> <em id="ncAppsUpdates"><?php p($_['system']['apps']['num_updates_available']);?></em></p> + <div class="infobox"> + <h2><?php p($l->t('Shares'));?></h2> + <br> + <div class="chart-container"> + <canvas data-shares="<?php p(json_encode($_['shares']))?>" class="barchart" id="sharecanvas"></canvas> + </div> + </div> </div> + +<!-- PHPINFO --> <div class="section" id="phpSection"> - <h2><?php p($l->t('PHP'));?></h2> - <p><?php p($l->t('Version:'));?> <em id="phpVersion"><?php p($_['php']['version']);?></em></p> - <p><?php p($l->t('Memory Limit:'));?> <em id="phpMemLimit"><?php p($_['php']['memory_limit']);?></em></p> - <p><?php p($l->t('Max Execution Time:'));?> <em id="phpMaxExecTime"><?php p($_['php']['max_execution_time']);?></em></p> - <p><?php p($l->t('Upload max size:'));?> <em id="phpUploadMaxSize"><?php p($_['php']['upload_max_filesize']);?></em></p> + <h2> + <img class="infoicon" src="<?php p(image_path('serverinfo', 'hdd-o.svg'));?>"> + <?php p($l->t('PHP'));?> + </h2> + <div class="infobox"> + <p> + <?php p($l->t('Version:'));?> + <em id="phpVersion"><?php p($_['php']['version']);?></em> + </p> + <p> + <?php p($l->t('Memory Limit:'));?> + <em id="phpMemLimit"><?php p($_['php']['memory_limit']);?></em> + </p> + <p> + <?php p($l->t('Max Execution Time:'));?> + <em id="phpMaxExecTime"><?php p($_['php']['max_execution_time']);?></em> + </p> + <p> + <?php p($l->t('Upload max size:'));?> + <em id="phpUploadMaxSize"><?php p($_['php']['upload_max_filesize']);?></em> + </p> + </div> </div> + +<!-- DATABASE --> <div class="section" id="databaseSection"> - <h2><?php p($l->t('Database'));?></h2> - <p><?php p($l->t('Type:'));?> <em id="databaseType"><?php p($_['database']['type']);?></em></p> - <p><?php p($l->t('Version:'));?> <em id="databaseVersion"><?php p($_['database']['version']);?></em></p> - <p><?php p($l->t('Size:'));?> <em id="databaseSize"><?php p($_['database']['size']);?></em></p> + <h2> + <img class="infoicon" src="<?php p(image_path('serverinfo', 'hdd-o.svg'));?>"> + <?php p($l->t('Database'));?> + </h2> + <div class="infobox"> + <p> + <?php p($l->t('Type:'));?> + <em id="databaseType"><?php p($_['database']['type']);?></em> + </p> + <p> + <?php p($l->t('Version:'));?> + <em id="databaseVersion"><?php p($_['database']['version']);?></em> + </p> + <p> + <?php p($l->t('Size:'));?> + <em id="databaseSize"><?php p($_['database']['size']);?></em> + </p> + </div> </div> +<!-- OCS ENDPOINT --> <div class="section" id="ocsEndPoint"> <h2><?php p($l->t('External monitoring tool'));?></h2> <p> - <?php p($l->t('You can connect an external monitoring tool by using this end point:')); ?> + <?php p($l->t('You can connect an external monitoring tool by using this end point:'));?> </p> <div> <input type="text" readonly="readonly" id="monitoring-endpoint-url" value="<?php echo p($_['ocs']); ?>" /> <a class="clipboardButton icon icon-clippy" data-clipboard-target="#monitoring-endpoint-url"></a> - <span class="icon-info svg" title="" data-original-title="<?php p($l->t('Did you know?')); ?> <?php p($l->t('Appending "?format=json" at the end of the URL gives you the result in JSON format!')); ?>"></span> + <span class="icon-info svg" title="" data-original-title="<?php p($l->t('Did you know?'));?> <?php p($l->t('Appending "?format=json" at the end of the URL gives you the result in JSON format!'));?>"></span> </div> </div> diff --git a/tests/lib/Controller/ApiControllerTest.php b/tests/lib/Controller/ApiControllerTest.php deleted file mode 100644 index b891c24..0000000 --- a/tests/lib/Controller/ApiControllerTest.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -namespace OCA\ServerInfo\Tests\lib\Controller; - - -use OCA\ServerInfo\Controller\ApiController; -use OCA\ServerInfo\DatabaseStatistics; -use OCA\ServerInfo\PhpStatistics; -use OCA\ServerInfo\SessionStatistics; -use OCA\ServerInfo\ShareStatistics; -use OCA\ServerInfo\StorageStatistics; -use OCA\ServerInfo\SystemStatistics; -use OCP\AppFramework\Http\DataResponse; -use OCP\IRequest; -use Test\TestCase; - -class ApiControllerTest extends TestCase { - - /** @var IRequest | \PHPUnit_Framework_MockObject_MockObject */ - private $request; - - /** @var SystemStatistics | \PHPUnit_Framework_MockObject_MockObject */ - private $systemStatistics; - - /** @var StorageStatistics | \PHPUnit_Framework_MockObject_MockObject */ - private $storageStatistics; - - /** @var PhpStatistics | \PHPUnit_Framework_MockObject_MockObject */ - private $phpStatistics; - - /** @var DatabaseStatistics | \PHPUnit_Framework_MockObject_MockObject */ - private $databaseStatistics; - - /** @var ShareStatistics | \PHPUnit_Framework_MockObject_MockObject */ - private $shareStatistics; - - /** @var SessionStatistics | \PHPUnit_Framework_MockObject_MockObject */ - private $sessionStatistics; - - /** @var ApiController */ - private $instance; - - public function setUp() { - parent::setUp(); - - $this->request = $this->getMockBuilder('OCP\IRequest') - ->disableOriginalConstructor() - ->getMock(); - - $this->systemStatistics = $this->getMockBuilder('OCA\ServerInfo\SystemStatistics') - ->disableOriginalConstructor() - ->getMock(); - - $this->storageStatistics = $this->getMockBuilder('OCA\ServerInfo\StorageStatistics') - ->disableOriginalConstructor() - ->getMock(); - - $this->phpStatistics = $this->getMockBuilder('OCA\ServerInfo\PhpStatistics') - ->disableOriginalConstructor() - ->getMock(); - - $this->databaseStatistics = $this->getMockBuilder('OCA\ServerInfo\DatabaseStatistics') - ->disableOriginalConstructor() - ->getMock(); - - $this->shareStatistics = $this->getMockBuilder('OCA\ServerInfo\ShareStatistics') - ->disableOriginalConstructor() - ->getMock(); - - $this->sessionStatistics = $this->getMockBuilder('OCA\ServerInfo\SessionStatistics') - ->disableOriginalConstructor() - ->getMock(); - - - $this->instance = new ApiController( - 'ServerInfoTest', - $this->request, - $this->systemStatistics, - $this->storageStatistics, - $this->phpStatistics, - $this->databaseStatistics, - $this->shareStatistics, - $this->sessionStatistics - ); - } - - public function testInfo() { - - $this->systemStatistics->expects($this->once())->method('getSystemStatistics') - ->willReturn('systemStatistics'); - $this->storageStatistics->expects($this->once())->method('getStorageStatistics') - ->willReturn('storageStatistics'); - $this->phpStatistics->expects($this->once())->method('getPhpStatistics') - ->willReturn('phpStatistics'); - $this->databaseStatistics->expects($this->once())->method('getDatabaseStatistics') - ->willReturn('databaseStatistics'); - $this->shareStatistics->expects($this->once())->method('getShareStatistics') - ->willReturn('shareStatistics'); - $this->sessionStatistics->expects($this->once())->method('getSessionStatistics') - ->willReturn('sessionStatistics'); - - $result = $this->instance->info(); - $this->assertTrue($result instanceof DataResponse); - $data = $result->getData(); - $this->assertTrue(isset($data['nextcloud'])); - $this->assertTrue(isset($data['server'])); - - $this->assertSame('systemStatistics', $data['nextcloud']['system']); - $this->assertSame('storageStatistics', $data['nextcloud']['storage']); - $this->assertSame('shareStatistics', $data['nextcloud']['shares']); - $this->assertSame('unknown', $data['server']['webserver']); - $this->assertSame('databaseStatistics', $data['server']['database']); - $this->assertSame('phpStatistics', $data['server']['php']); - $this->assertSame('sessionStatistics', $data['activeUsers']); - } - -} |