*
* @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
*
*/
namespace OCA\ServerInfo\OperatingSystems;
use OCA\ServerInfo\Resources\Disk;
use OCA\ServerInfo\Resources\Memory;
class DefaultOs implements IOperatingSystem {
/**
* @return bool
*/
public function supported(): bool {
return true;
}
public function getMemory(): Memory {
$data = new Memory();
try {
$meminfo = $this->readContent('/proc/meminfo');
} catch (\RuntimeException $e) {
return $data;
}
$matches = [];
$pattern = '/(?(?:MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree)+):\s+(?\d+)\s+(?\w{2})/';
$result = preg_match_all($pattern, $meminfo, $matches);
if ($result === 0 || $result === false) {
return $data;
}
foreach ($matches['Key'] as $i => $key) {
// Value is always in KB: https://github.com/torvalds/linux/blob/c70672d8d316ebd46ea447effadfe57ab7a30a50/fs/proc/meminfo.c#L58-L60
$value = (int)($matches['Value'][$i] / 1024);
switch ($key) {
case 'MemTotal':
$data->setMemTotal($value);
break;
case 'MemFree':
$data->setMemFree($value);
break;
case 'MemAvailable':
$data->setMemAvailable($value);
break;
case 'SwapTotal':
$data->setSwapTotal($value);
break;
case 'SwapFree':
$data->setSwapFree($value);
break;
}
}
return $data;
}
public function getCpuName(): string {
$data = 'Unknown Processor';
try {
$cpuinfo = $this->readContent('/proc/cpuinfo');
} catch (\RuntimeException $e) {
return $data;
}
$matches = [];
$pattern = '/model name\s:\s(.+)/';
$result = preg_match_all($pattern, $cpuinfo, $matches);
if ($result === 0 || $result === false) {
return $data;
}
$model = $matches[1][0];
$cores = count($matches[1]);
if ($cores === 1) {
$data = $model . ' (1 core)';
} else {
$data = $model . ' (' . $cores . ' cores)';
}
return $data;
}
/**
* @return string
*/
public function getTime() {
$uptime = shell_exec('date');
return $uptime;
}
public function getUptime(): int {
$data = -1;
try {
$uptime = $this->readContent('/proc/uptime');
} catch (\RuntimeException $e) {
return $data;
}
[$uptimeInSeconds,] = array_map('intval', explode(' ', $uptime));
return $uptimeInSeconds;
}
/**
* @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;
}
public function getDiskInfo(): array {
$data = [];
try {
$disks = $this->executeCommand('df -TPk');
} catch (\RuntimeException $e) {
return $data;
}
$matches = [];
$pattern = '/^(?[\S]+)\s*(?[\S]+)\s*(?\d+)\s*(?\d+)\s*(?\d+)\s*(?\d+%)\s*(?[\w\/-]+)$/m';
$result = preg_match_all($pattern, $disks, $matches);
if ($result === 0 || $result === false) {
return $data;
}
foreach ($matches['Filesystem'] as $i => $filesystem) {
if (in_array($matches['Type'][$i], ['tmpfs', 'devtmpfs'], false)) {
continue;
}
$disk = new Disk();
$disk->setDevice($filesystem);
$disk->setFs($matches['Type'][$i]);
$disk->setUsed((int)($matches['Used'][$i] / 1024));
$disk->setAvailable((int)($matches['Available'][$i] / 1024));
$disk->setPercent($matches['Capacity'][$i]);
$disk->setMount($matches['Mounted'][$i]);
$data[] = $disk;
}
return $data;
}
protected function readContent(string $filename): string {
$data = @file_get_contents($filename);
if ($data === false || $data === '') {
throw new \RuntimeException('Unable to read: "' . $filename . '"');
}
return $data;
}
protected function executeCommand(string $command): string {
$output = @shell_exec(escapeshellcmd($command));
if ($output === null || $output === '') {
throw new \RuntimeException('No output for command: "' . $command . '"');
}
return $output;
}
}