Skip to content

Commit

Permalink
feat: rename DefaultOs to Linux
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
  • Loading branch information
kesselb committed Aug 1, 2023
1 parent adea3c6 commit 59ffb61
Show file tree
Hide file tree
Showing 10 changed files with 616 additions and 455 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ php occ serverinfo:update-storage-statistics -v --output=json_pretty
}
```

Show phpinfo
##### Enforce default os (>= Nextcloud 28)

To obtain information about your server, the serverinfo app reads files outside the application directory (e.g. /proc on Linux) or executes shell commands (e.g. df on Linux).

If you don't want that (for example, to avoid open_basedir warnings) enforce the default os. The default os only returns the hostname.

Enable:

``php occ config:app:set --value=yes serverinfo force_default_os``

Disable:

``php occ config:app:delete serverinfo force_default_os``

##### Show phpinfo (>= Nextcloud 28)

Enable:

``php occ config:app:set --value=yes serverinfo phpinfo``

Disable:

``php occ config:app:delete serverinfo phpinfo``
239 changes: 13 additions & 226 deletions lib/OperatingSystems/DefaultOs.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,259 +23,46 @@

namespace OCA\ServerInfo\OperatingSystems;

use OCA\ServerInfo\Resources\Disk;
use OCA\ServerInfo\Resources\Memory;
use OCA\ServerInfo\Resources\NetInterface;
use RuntimeException;

class DefaultOs implements IOperatingSystem {
private const AF_INET = 2;
private const AF_INET6 = 10;

public function supported(): bool {
return true;
return false;
}

public function getMemory(): Memory {
$data = new Memory();

try {
$meminfo = $this->readContent('/proc/meminfo');
} catch (RuntimeException $e) {
return $data;
}

$matches = [];
$pattern = '/(?<Key>(?:MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree)+):\s+(?<Value>\d+)\s+(?<Unit>\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)((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;
return new Memory();
}

public function getCpuName(): string {
$data = 'Unknown Processor';

try {
$cpuinfo = $this->readContent('/proc/cpuinfo');
} catch (RuntimeException $e) {
return $data;
}

$matches = [];

if (str_contains($cpuinfo, 'Raspberry Pi')) {
$pattern = '/Model\s+:\s(.+)/';
} elseif (str_contains($cpuinfo, 'PowerNV') || str_contains($cpuinfo, 'CHRP IBM pSeries')) {
$pattern = '/cpu\s+:\s+(.+)/';
} else {
$pattern = '/model name\s:\s(.+)/';
}

$result = preg_match_all($pattern, $cpuinfo, $matches);
if ($result === 0 || $result === false) {
return $data;
}

$model = $matches[1][0];

$pattern = '/processor\s+:\s(.+)/';

preg_match_all($pattern, $cpuinfo, $matches);
$cores = count($matches[1]);

if ($cores === 1) {
$data = $model . ' (1 core)';
} else {
$data = $model . ' (' . $cores . ' cores)';
}

return $data;
return 'Unknown Processor';
}

public function getTime(): string {
return (string)shell_exec('date');
return '';
}

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 -1;
}

public function getNetworkInfo(): array {
$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 [
'hostname' => \gethostname(),
'dns' => '',
'gateway' => '',
];
}

public function getNetworkInterfaces(): array {
$data = [];

foreach ($this->getNetInterfaces() as $interfaceName => $interface) {
$netInterface = new NetInterface($interfaceName, $interface['up']);
$data[] = $netInterface;

foreach ($interface['unicast'] as $unicast) {
if (isset($unicast['family'])) {
if ($unicast['family'] === self::AF_INET) {
$netInterface->addIPv4($unicast['address']);
}
if ($unicast['family'] === self::AF_INET6) {
$netInterface->addIPv6($unicast['address']);
}
}
}

if ($netInterface->isLoopback()) {
continue;
}

$interfacePath = '/sys/class/net/' . $interfaceName;

try {
$netInterface->setMAC($this->readContent($interfacePath . '/address'));

$speed = (int)$this->readContent($interfacePath . '/speed');
if ($speed >= 1000) {
$netInterface->setSpeed($speed / 1000 . ' Gbps');
} else {
$netInterface->setSpeed($speed . ' Mbps');
}

$netInterface->setDuplex($this->readContent($interfacePath . '/duplex'));
} catch (RuntimeException $e) {
// unable to read interface data
}
}

return $data;
return [];
}

public function getDiskInfo(): array {
$data = [];

try {
$disks = $this->executeCommand('df -TPk');
} catch (RuntimeException $e) {
return $data;
}

$matches = [];
$pattern = '/^(?<Filesystem>[\S]+)\s*(?<Type>[\S]+)\s*(?<Blocks>\d+)\s*(?<Used>\d+)\s*(?<Available>\d+)\s*(?<Capacity>\d+%)\s*(?<Mounted>[\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', 'squashfs', 'overlay'], false)) {
continue;
} elseif (in_array($matches['Mounted'][$i], ['/etc/hostname', '/etc/hosts'], false)) {
continue;
}

$disk = new Disk();
$disk->setDevice($filesystem);
$disk->setFs($matches['Type'][$i]);
$disk->setUsed((int)((int)$matches['Used'][$i] / 1024));
$disk->setAvailable((int)((int)$matches['Available'][$i] / 1024));
$disk->setPercent($matches['Capacity'][$i]);
$disk->setMount($matches['Mounted'][$i]);

$data[] = $disk;
}

return $data;
return [];
}

public function getThermalZones(): array {
$thermalZones = glob('/sys/class/thermal/thermal_zone*') ?: [];
$result = [];

foreach ($thermalZones as $thermalZone) {
$tzone = [];
try {
$tzone['hash'] = md5($thermalZone);
$tzone['type'] = $this->readContent($thermalZone . '/type');
$tzone['temp'] = (float)((int)($this->readContent($thermalZone . '/temp')) / 1000);
} catch (RuntimeException $e) {
continue;
}
$result[] = $tzone;
}

return $result;
}

/**
* @throws RuntimeException
*/
protected function readContent(string $filename): string {
$data = @file_get_contents($filename);
if ($data === false || $data === '') {
throw new RuntimeException('Unable to read: "' . $filename . '"');
}
return trim($data);
}

protected function executeCommand(string $command): string {
$output = @shell_exec(escapeshellcmd($command));
if ($output === false || $output === null || $output === '') {
throw new RuntimeException('No output for command: "' . $command . '"');
}
return $output;
}

/**
* Wrapper for net_get_interfaces
*
* @throws RuntimeException
*/
protected function getNetInterfaces(): array {
$data = net_get_interfaces();
if ($data === false) {
throw new RuntimeException('Unable to get network interfaces');
}
return $data;
return [];
}
}
Loading

0 comments on commit 59ffb61

Please sign in to comment.